在窗口上跟蹤顯示鼠標(biāo)位置-Win32版本
響應(yīng) WM_MOUSEMOVE 消息獲得鼠標(biāo)位置,再響應(yīng) WM_PAINT 將鼠標(biāo)位置輸出到窗口中,學(xué)習(xí)二者之間的關(guān)鍵步驟:調(diào)用 InvalidateRect() 以通知窗口重繪。


響應(yīng) WM_MOUSEMOVE 消息獲得鼠標(biāo)位置,再響應(yīng) WM_PAINT 將鼠標(biāo)位置輸出到窗口中,學(xué)習(xí)二者之間的關(guān)鍵步驟:調(diào)用 InvalidateRect() 以通知窗口重繪。
一、關(guān)鍵知識點(diǎn)
1. BeginPaint() 對比 GetDC()
兩個(gè)API都能得到指定窗口的 DC (設(shè)備上下文),供程序后續(xù)在 DC 上畫圖、輸出文字等。二者區(qū)別在于,BeginPaint() 是在窗口收到 WM_PAINT 消息后使用。窗口收到 WM_PAINT 意味著:這個(gè)窗口當(dāng)前展現(xiàn)的內(nèi)容已經(jīng)失效,確實(shí)需要重畫。而 GetDC() 是直接獲得一個(gè)窗口的DC,然后直接開畫。
再往前推一步:一個(gè)程序有機(jī)會響應(yīng)某個(gè)窗口的消息(比如這里的 WM_PAINT),通常就意味著這個(gè)窗口是該程序自己創(chuàng)建出來的。
二者在參數(shù)上也有明顯不同,BeginPaint() 除窗口句柄外,還需要先創(chuàng)建一個(gè) PAINTSTRCT 的變量。
2. EndPaint()
GetDC() 調(diào)用后,要記得配套地寫上 ReleaseDC(),類似,我們從 BeginPaint() 得到一個(gè) DC,在完成使用該 DC 之后,要記得配套調(diào)用 EndPaint()。
3. WM_MOUSEMOVE 消息
坐標(biāo)點(diǎn)在該消息的響應(yīng)函數(shù)的 lParam 參數(shù),該參數(shù)的類型的是 LPARAM, 它是Windows開發(fā)庫定義的一個(gè)宏。其中 L 表示 “l(fā)ong” ,也就是長整型。然而,在 Windows 上,哪怕是 64 位的系統(tǒng),long 其實(shí)仍然一個(gè) int ,因此還是四字節(jié)。當(dāng)它用作 WM_MOUSEMOVE 的參數(shù)時(shí),從左到右,前兩個(gè)字節(jié)(低字),存儲鼠標(biāo)移動后的 x 坐標(biāo),高字存儲 y 坐標(biāo)。
對一個(gè)整數(shù)(int,long)取低字,可使用宏 LOWORD(),其中 LO 是 “l(fā)ow / 低” 的縮寫,對應(yīng)的取高字使用 HIWORD(), “HI” 是 “High / 高” 的縮寫。
4. InvalidateRect
函數(shù)原型(聲明)為:
InvalidateRect 用于讓指定窗口(hWnd)的指定區(qū)域(lpRect,說明見下)的繪圖內(nèi)容失效。
如果 lpRect 為空指針,則讓整個(gè)窗口的(嚴(yán)格講是客戶區(qū),即不包容標(biāo)題欄、邊框等)的繪圖內(nèi)容都失效。這樣,窗口就會收到 WM_PAINT 消息,然后程序調(diào)用處理該消息的函數(shù),開始重繪。
bErase 為真時(shí),如果該窗口設(shè)置了合適的默認(rèn)背景刷子(Brush,類似于 Pen,也是一種繪圖資源 ), 系統(tǒng)將保證在重繪前,使用該刷子(特定顏色、樣式),“刷掉” 原有內(nèi)容。注意,窗口并不一定有合適的背景刷子。在我們的示例程序中,以下這一行保證了這一點(diǎn):
其中的 RECT 是一個(gè)結(jié)構(gòu)(struct),定義為:
即:通用 左、上、右、下 位置,定義一個(gè)矩形區(qū)域。
三、完整代碼
三、效果示例
