VC中鍵盤事件處理主要是通過對相應的消息的響應,這些事件有如:WM_CHAR、
WM_KEYDOWN、WM_KEYUP等他們分别對應OnChar、OnKeyDown、OnKeyUp消息處
理函數;當然在有些時候我們也可能需要用到對PreTranslateMessage函數的重載。
從這些事件的名稱我們可以看出WM_CHAR表示字元事件,WM_KEYDOWN表示鍵
盤的鍵被按下時事件,而WM_KEYUP則表示鍵盤的鍵被放開時的事件;我們在鍵盤上按
下某個鍵時系統先調用OnKeyDown函數接着調用OnChar函數最後調用OnKeyUp函數;
這些消息函數的原形如下:
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
nChar代表虛拟鍵,nRepCnt代表重複次數;而對于nFlags則有點麻煩但大多數時候我們不
管這個參數,nFlags的具體意義請參考MSDN相關文檔。
在大多數時候我們隻要用到OnChar、OnKeyDown、OnKeyUp這些消息處理函數就夠
了,但有時候我們會發理這些函數并不會被調用(特别是對話框程式)這時我們就必需去重
載PreTranslateMessage函數;些函數的使用也比較簡單但在處理組合按鍵時我們必需用到相
鍵盤消息被攔截而得不到正常響應,其中的關鍵就是Run函數對消息的預處理。在Run
函數中,調用了函數CWinThread::PumpMessage,就是利用這一函數,MFC實作了對消息
的分流,使得消息沿着MFC對各種消息規定的路線流動,直到被正确響應。函數PumpMessage調用了函數CWinThread::PreTranslateMessage對消息進行處理,如
果該函數不對消息進行處理,則調用API函數TranslateMessage函數将虛拟鍵消息轉換為字
符消息并調用DispatchMessage分發消息給視窗處理程式。在對話框中,程式用
CWinThread::PreTranslateMessage函數處理了鍵盤消息,是以對話框程式是否要響應鍵盤消
息,将完全由CWinThread::PreTranslateMessage函數來決定了。
在CWnd及其派生類的成員函數PreTranslateMessage函數是一個虛函數,可以通過重
載來改變其處理過程。在預設情況下,沒有重載這一函數。
例子1:
在VC6中建立基于對話框的工程,在Class view中找到相應的對話框類單擊右鍵,在右鍵
菜單中選擇Add Virtual Fuction...項,然後找到PreTranslateMessage虛函數進行加載。相應的
代碼中如下:
BOOL CTestDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
//判斷是否是按鍵消息
if( pMsg->message == WM_KEYDOWN )
{
MessageBox("有鍵被按下");
//判斷具體鍵
switch( pMsg->wParam )
{
case VK_LEFT://按下左鍵
MessageBox(_T("左"));
return TRUE;
break;
case VK_RIGHT://按下右鍵
MessageBox(_T("右"));
return TRUE;
break;
case VK_UP://按下上鍵
MessageBox(_T("上"));
return TRUE;
break;
case VK_DOWN://按下下鍵
MessageBox(_T("下"));
return TRUE;
break;
default:
return TRUE;
break;
}
return CDialog::PreTranslateMessage(pMsg);
}
}
///
将return CDialog::PreTranslateMessage(pMsg);放在if裡将導緻程式無法正常關閉!
最起碼應該放到if的外面去。
下面是一個用WASD這幾個按鍵控制滑塊的代碼:(用→這樣的按鈕控制時老是出問題)
其中m_X,和m_Y為滑塊的控制變量
BOOL CTestDlg::PreTranslateMessage(MSG *pMsg)
{
if (pMsg->wParam == 'W')
{
Y = m_Y.GetPos();
Y++;
m_Y.SetPos(Y);
}
else if (pMsg->wParam == 'S')
{
Y = m_Y.GetPos();
Y--;
m_Y.SetPos(Y);
}
else if (pMsg->wParam == 'A')
{
X = m_X.GetPos();
X--;
m_X.SetPos(X);
}
else if (pMsg->wParam == 'D')
{
X = m_X.GetPos();
X++;
m_X.SetPos(X);
}
return CDialog::PreTranslateMessage(pMsg);
}
當然也可以分開寫:
1.先添加PreTranslateMessage(pMsg);裡面隻加入:
return CDialog::PreTranslateMessage(pMsg);
即:
BOOL CKEYDlg::PreTranslateMessage(MSG *pMsg)
{
// TODO: Add your specialized code here and/or call the base class
return CDialog::PreTranslateMessage(pMsg);
}
2.然後添加單獨添加WM_KEYDOWN等消息:
void CKEYDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
if (nChar == VK_SPACE)
{
MessageBox("空格鍵被按下","提示!");
}
CDialog::OnKeyDown(nChar, nRepCnt, nFlags);
}
另附上 虛拟碼:
後面括号的是對應的ASCII碼
ESC鍵 VK_ESCAPE (27)
Enter鍵: VK_RETURN (13)
TAB鍵: VK_TAB (9)
Caps Lock鍵: VK_CAPITAL (20)
Shift鍵: VK_SHIFT ($10)
Ctrl鍵: VK_CONTROL (17)
Alt鍵: VK_MENU (18)
空格鍵: VK_SPACE ($20/32)
倒退鍵: VK_BACK (8)
左徽标鍵: VK_LWIN (91)
右徽标鍵: VK_LWIN (92)
滑鼠右鍵快捷鍵:VK_APPS (93)
Insert鍵: VK_INSERT (45)
Home鍵: VK_HOME (36)
Page Up: VK_PRIOR (33)
PageDown: VK_NEXT (34)
End鍵: VK_END (35)
Delete鍵: VK_DELETE (46)
方向鍵(←): VK_LEFT (37)
方向鍵(↑): VK_UP (38)
方向鍵(→): VK_RIGHT (39)
方向鍵(↓): VK_DOWN (40)
F1鍵: VK_F1 (112)
F2鍵: VK_F2 (113)
F3鍵: VK_F3 (114)
F4鍵: VK_F4 (115)
F5鍵: VK_F5 (116)
F6鍵: VK_F6 (117)
F7鍵: VK_F7 (118)
F8鍵: VK_F8 (119)
F9鍵: VK_F9 (120)
F10鍵: VK_F10 (121)
F11鍵: VK_F11 (122)
F12鍵: VK_F12 (123)
Num Lock鍵: VK_NUMLOCK (144)
小鍵盤0: VK_NUMPAD0 (96)
小鍵盤1: VK_NUMPAD0 (97)
小鍵盤2: VK_NUMPAD0 (98)
小鍵盤3: VK_NUMPAD0 (99)
小鍵盤4: VK_NUMPAD0 (100)
小鍵盤5: VK_NUMPAD0 (101)
小鍵盤6: VK_NUMPAD0 (102)
小鍵盤7: VK_NUMPAD0 (103)
小鍵盤8: VK_NUMPAD0 (104)
小鍵盤9: VK_NUMPAD0 (105)
小鍵盤.: VK_DECIMAL (110)
小鍵盤*: VK_MULTIPLY (106)
小鍵盤+: VK_MULTIPLY (107)
小鍵盤-: VK_SUBTRACT (109)
小鍵盤/: VK_DIVIDE (111)
Pause Break鍵: VK_PAUSE (19)
Scroll Lock鍵: VK_SCROLL (145)
字母的虛拟碼直接使用ASCII碼即可
另外需要注意:
VK_?? 定義在 winuser.h 中,而對于字母123...,ABC..卻沒有VK_A,VK_B...
MFC中恰恰沒有VK_0 -- VK_9,VK_A --VK_Z ,倒是有VK_NUMPAD0 --VK_NUMPAD9
在delphi,BCB,JAVA中都有。
當然,你可以直接定義,但是打開winuser.h會找到:
是以直接用'A'就行了!