MFC控件編程之鼠標跟鍵盤消息
在MFC中鼠標消息.鍵盤消息我們很常用.所以說一下.
鼠標消息分為客戶區消息.跟非客戶區消息.
一丶客戶區消息
我們可以處理消息.來進行我們相應的函數即可.
MFC添加消息的話.可以自己在消息映射表中添加 .可以自己使用工具直接添加.
消息映射表添加
學習過MFC原理的應該知道.這里可以添加消息. 自己可以手動添加.我們也可以使用向導來添加.
void CCDCDlg::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息處理程序代碼和/或調用默認值 CString str; str.Format(TEXT("x坐標 = %d,y 坐標 = %d"), point.x, point.y); ::SetWindowText(m_hWnd, str); }
輸出我們的鼠標點擊的時候的坐標位置.調用 ::SetWindowText設置窗口標題.
三丶非客戶區消息
非客戶區消息就指的標題欄啊等等.這些位置.
而他們的消息多了一個NC開頭.
例如我們在消息映射表中添加一個NC開頭的消息.
我們也可以使用向導.看自己喜好了.
代碼:
void CCDCDlg::OnNcLButtonDown(UINT nFlags, CPoint point) { CString str; str.Format(TEXT("非客戶區 x坐標 = %d,y 坐標 = %d"), point.x, point.y); ::SetWindowText(m_hWnd, str); }
點擊標題欄
如果按照上面寫我們點擊關閉按鈕會關閉不了.原因就是NcLBUTTONDown里面包括了點擊關閉按鈕的消息.你沒有進行處理.此時我們交給父類處理即可.
void CCDCDlg::OnNcLButtonDown(UINT nFlags, CPoint point) { CString str; str.Format(TEXT("非客戶區 x坐標 = %d,y 坐標 = %d"), point.x, point.y); ::SetWindowText(m_hWnd, str); CDialogEx::OnNcLButtonDown(nFlags,point); }
其中nflags是一個區域划分嗎.我們可以自己判斷是否是哪個區域會享用.
例如:
if (nflags == HTSYSMENU) 判斷是否是菜單.... 進行你的操作
點擊客戶區
在我們的鼠標消息到來之前.它會先判斷是客戶區域還是非客戶區域.然后進行轉換.才給我們將消息發送過來.
也就是說我們可以吧客戶區轉換為非客戶區. 比如鼠標點擊客戶區.其實是點擊的非客戶區.
代碼如下.
LRESULT CCDCDlg::OnNcHitTest(CPoint point) { // TODO: 在此添加消息處理程序代碼和/或調用默認值 UINT hit = CDialogEx::OnNcHitTest(point); //獲取父類返回的判斷是否是客戶區還是非客戶區 if (hit == HTCLIENT) //如果是客戶區.那么我們轉化為非客戶區 { hit = HTCAPTION; } return hit; }
實現的消息
API: 坐標轉為窗口坐標.
::ScreenToClient(m_hWnd, &point);
四丶捕獲鼠標
捕獲鼠標也很常用. 比如我們鼠標按下畫線.的時候. 鼠標會移動到窗口外邊.那這樣的話畫線就不會成功了.
實現思路:
1.鼠標點擊.保存一下坐標
2.鼠標抬起. 創建CClientDc. 使用MoveTo移動到保存的鼠標位置.
3.使用dc畫線.畫出新的位置.
例如:
鼠標按下.
void CCDCDlg::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息處理程序代碼和/或調用默認值 //保存當前位置. m_Point = point; }
m_point是在類中定義的一個成員.
鼠標抬起 void CCDCDlg::OnLButtonUp(UINT nFlags, CPoint point) { // CClientDC dc(this); dc.MoveTo(m_Point); dc.LineTo(point); }
實現截圖
遇到的問題.當我們鼠標拖動到窗口外面之后.就不會畫線了.所以我們要捕獲鼠標.
用到的三個API:
1.SetCapture(); 捕獲鼠標.在鼠標按下的時候.
2.GetCapture(); 獲取捕獲的鼠標.
3.ReleaseCapture(); 釋放
代碼如下.
void CCDCDlg::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息處理程序代碼和/或調用默認值 //保存當前位置. m_Point = point; SetCapture(); //捕獲鼠標 } void CCDCDlg::OnLButtonUp(UINT nFlags, CPoint point) { // CClientDC dc(this); dc.MoveTo(m_Point); dc.LineTo(point); if (GetCapture() == this) { ReleaseCapture(); } }
這樣我們的鼠標移動到客戶區外面也可以畫線了.
五丶了解鍵盤消息中的各位代表的含義
虛擬鍵代碼 VK_F1... . VK開頭的. 頭文件中有定義.有興趣的可以看一下.
nflgs中的第 14位 為如果先前按下.則為1.否則則為零. 其余的了解即可.
WM_KEYDOWN WM_KEYUP 可以判斷鍵盤是否按下抬起. 通過nChar 可以確定是哪一個鍵.
六丶API 判斷虛擬鍵碼是否按下.
Windows 為我們提供了一個API.用來檢索按鍵是否被按下.
GetKeyState(VK_F2)
如果返回值為負數. 那么代表了按下. 如果返回值為0.則代表沒有按.
所以我們判斷返回值 < 0 則是按下 >0 則是沒有按下.