天天看點

VS2010 MFC中設定HotKey

       1.首先建立一個基于對話框的MFC程式,我這裡建立的項目名為“Testlili”。

  2.然後“項目”--“類向導”--“消息”,選擇類名為“CTestliliDlg”,找到WM_HOTKEY消息添加,添加後“現有處理程式”的框框下就會多出一個“OnHotKey”。

  3.在“BOOL ×××::OnInitDialog()”函數中加入注冊熱鍵的代碼,比如注冊一個Ctrl+X的熱鍵:

      ATOM HotKeyId=GlobalAddAtom(L"Chun_ge")- 0xC000; //取得熱鍵唯一辨別符

      //GetSafeHwnd();取得本程式的視窗句柄  

      RegisterHotKey(GetSafeHwnd(),HotKeyId,MOD_ALT①,'X'②);   

       RegisterHotKey(GetSafeHwnd(),HotKeyId,NULL,VK_F10);       

        當然還可以像上面這樣把①中的參數NULL掉,②中的參數用虛拟鍵代碼比如此處的按鍵是F10。這樣設定後實作的就是單熱鍵。順帶一提RegisterHotKey()函數是系統API這樣設定後的熱鍵是全局熱鍵,也就是當我們的窗戶最小化或者處于未激活狀态下按下設定的熱鍵也會執行回調函數中的代碼,而不是像下面的方法設定的那樣是局部熱鍵,一旦我們的程式處于未激活狀态按下熱鍵就不會有反應。

①:參數3可以疊加,比如MOD_CONTROL|MOD_ALT,加上②處的參數4組合起來就是熱鍵Ctrl+Alt+X

  注冊熱鍵的函數:

  BOOL WINAPI RegisterHotKey(

  __in_opt HWND hWnd,

  __in int id,

  __in UINT fsModifiers,

  __in UINT vk

  );

  參數1:為視窗的句柄

  參數2:定義熱鍵的辨別符。調用線程中的其他熱鍵,不能使用同樣的辨別符。應用程式必須定義一個0X0000-0xBFFF範圍的值。一個共享的動态連結庫(DLL)必須定義一個範圍為0xC000-0xFFFF的值(GlobalAddAtom函數傳回該範圍)。為了避免與其他動态連結庫定義的熱鍵沖突,一個DLL必須使用GlobalAddAtom函數獲得熱鍵的辨別符。

  參數3:定義為了産生WM_HOTKEY消息而必須與由nVirtKey參數定義的鍵一起按下的鍵。

  該參數可以是如下值的組合:

  鍵                               值                 含意

      MOD_ALT                0x0001         按下的可以是任一(左邊或者右邊的)Alt鍵。

    MOD_SHIFT            0x0004         按下的可以是任一(左邊或者右邊的)Shift鍵。

  MOD_WIN              0x0008         按下的可以是任一(左邊或者右邊的)Windows徽标鍵。

  MOD_NOREPEAT   0x4000         更改熱鍵行為,以便鍵盤自動重複不會産生多個熱鍵通知。

  MOD_CONTROL     0x0002          按下的可以是任意一個Ctrl鍵(左邊或者右邊的)。

  參數4:定義熱鍵的虛拟鍵碼。

  4.在OnHotKey函數中添加觸發熱鍵後要執行的代碼:

void CEternityDlg::OnHotKey(UINT nHotKeyId, UINT nKey1, UINT nKey2)
{
	// TODO: 在此添加消息處理程式代碼和/或調用預設值

	if (nHotKeyId==HotKeyId) //這個If不加也行
	{
	MessageBox(L"春哥純爺們");
	}

	CDialogEx::OnHotKey(nHotKeyId, nKey1, nKey2);
}
           

          5.如果有2個以上熱鍵:

BOOL ×××::OnInitDialog()
{

	HotKeyId=GlobalAddAtom(L"Chun_ge")- 0xC000; //取得熱鍵唯一辨別符

	HotKeyId2=GlobalAddAtom(L"Zeng_ge")- 0xC000;

	RegisterHotKey(GetSafeHwnd(),HotKeyId,NULL,VK_F10);  //熱鍵F10

	RegisterHotKey(GetSafeHwnd(),HotKeyId2,NULL,VK_F11); //再注冊一個F11

}


void CNeverDlg::OnHotKey(UINT nHotKeyId, UINT nKey1, UINT nKey2)
{
	// TODO: 在此添加消息處理程式代碼和/或調用預設值


	if (nHotKeyId==HotKeyId) //如果有1個以上熱鍵可以用這個方法來選擇  
	{  //F10熱鍵
		MessageBox(L"春哥純爺們");  
	} 

	else if (nHotKeyId==HotKeyId2)
	{ //F11熱鍵
		MessageBox(L"鐵血真漢子");

	}

	CDialogEx::OnHotKey(nHotKeyId, nKey1, nKey2);
}
           

  然後編譯運作,當按下Alt+X組合鍵時就會彈出一個消息框。當然為了嚴謹還可以用類向導添加OnDestroy()消息:

void CGhostDlg::OnDestroy()
{
	CDialogEx::OnDestroy();

	// TODO: 在此處添加消息處理程式代碼

	UnregisterHotKey(GetSafeHwnd(),HotKeyId);

}
           

這樣在MFC程式退出時就會登出熱鍵

關于MFC對話框程式不能響應OnKeyDown和OnChar函數的一些說明

(1)現象

  在MFC的對話框中,映射了WM_CHAR和WM_KEYDOWN消息響應函數後,還是不能響應OnKeyDown和OnChar。需要說明的是WM_CHAR消息響應的是鍵盤上的數字鍵和A~Z的字母鍵,WM_KEYDOWN消息響應的是除了數字鍵和字母鍵以外的那些鍵盤按鍵比如Esc鍵,Enter鍵,空格鍵什麼的。

(2)原因

  因為MFC在進行設計的時候,這兩個消息被對話框上的控件截獲了,不能到達這兩個消息響應函數,對于OnKeyDown來說,隻要把對話框上的控件都删除了,就可以接收到WM_KEYDOWN消息,但是還是接收不到WM_CHAR消息。

(3)解決

  方法1:重載PreTranslateMessage這個虛函數;在裡面加上SendMessage(pMsg->message,pMsg->wParam,pMsg->lParam);這一句後,對話框的OnKeyDown和OnChar函數就生效了。

  方法2:在PreTranslateMessage虛函數裡直接處理WM_KEYDOWN或WM_CHAR。

    eg:對話框屏蔽esc鍵

    BOOL Cmfc_testDlg::PreTranslateMessage(MSG* pMsg)

    {

      // TODO: 在此添加專用代碼和/或調用基類

      if(pMsg->message == WM_KEYDOWN)

      {

        if(pMsg->wParam == VK_ESCAPE)

          return TRUE;

      }

return CDialogEx::PreTranslateMessage(pMsg);

}

(4)執行順序

  三個消息的執行順序為WM_KEYDOWN、WM_CHAR、WM_KEYUP

(5)關于PreTranslateMessage()函數

  PreTranslateMessage是消息在送給TranslateMessage函數之前被調用的,絕大多數視窗的消息都要通過這裡,比較常用,當你需要在 MFC之前處理某些消息時,常常要在這裡添加代碼。通過重載這個函數,我們可以改變MFC的消息控制流程,甚至可以作一個全新的控制流出來。

  前面說了絕大多數視窗的消息都可以通過這個虛函數進行控制,這個絕大數其實是隻有穿過消息隊列的消息才受PreTranslateMessage ()影響,采用SendMessage()或其他類似的方式向視窗直接發送的而不經過消息隊列的消息根本不會理睬PreTranslateMessage()的存在,故切記SendMessage 發送的消息是不能用PreTranslate來截取的,應該重寫WindowProc視窗過程來響應消息!

(6)SendMessage()和PostMessage()

  SendMessage函數發送的消息會直接發送到視窗過程而不經過消息隊列,且直到消息處理完成後,SendMessage才傳回。函數傳回值指定 消息處理的結果,依賴于所發送的消息。

  PostMessage函數将一個消息寄送到指定視窗的消息隊列裡,不等待線程處理消息就立刻傳回。函數執行成功傳回TRUE,否則傳回 FALSE。

LRESULT WINAPI SendMessage( 

HWND hWnd, //視窗句柄

UINT Msg, //消息值

WPARAM wParam,//消息附加資訊 

LPARAM lParam //消息附加資訊 

);

BOOL WINAPI PostMessage( 

HWND hWnd, 

UINT Msg, 

WPARAM wParam, 

LPARAM lParam 

); 

(6)對話框特殊按鍵消息的處理

  預設情況下對話框響應Enter鍵的處理是調用基類的OnOK()函數,Esc鍵會調用基類的OnCancel()函數,這兩個函數都是虛函數,故要 對Enter或Esc鍵做相應處理的話可以重寫這兩個函數。

  單擊對話框标題欄上的關閉按鈕時會先後産生WM_CLOSE消息,故需要對标題欄關閉按鈕按下做處理的時候可以在WM_CLOSE消息的消息響應函數中進行。

鍵盤消息介紹

系統消息:

    ALT,F1,——F24等,是由系統内部處理的,程式本身就存在,比如F1是幫助鍵。

    WM_SYSKEYDOWN

    WM_SYSKEYUP

    WM_SYSCHAR

非系統消息:

    是由我們自己加上去的,

    WM_KEYDOWN

    WM_KEYUP

    WM_CHAR

虛拟鍵代碼

符号形式             十六進制形式        說明

VK_LBUTTON           01             滑鼠左鍵

VK_RBUTTON            02             滑鼠右鍵

VK_CANCEL             03          Control-break 過程

VK_MBUTTON          04                  滑鼠中鍵

VK_BACK                 08           BACKSPACE 鍵

VK_TAB                    09              TAB 鍵

VK_CLEAR               0C                CLEAR 鍵

VK_RETURN              0D            ENTER 鍵

VK_SHIFT                 10                 SHIFT 鍵

VK_CONTROL         11                 CTRL 鍵

VK_MENU                 12                   ALT 鍵

VK_PAUSE               13                PAUSE 鍵

VK_CAPITAL             14                CAPS LOCK 鍵

VK_ESCAPE            1B            ESC 鍵

VK_SPACE               20                SPACEBAR

VK_PRIOR                21                PAGE UP 鍵

VK_NEXT                 22                PAGE DOWN 鍵

VK_END                   23                  END 鍵

VK_HOME                24             HOME 鍵

VK_LEFT                 25               LEFT ARROW 鍵

VK_UP                      26               UP ARROW 鍵

VK_RIGHT                27               RIGHT ARROW 鍵

VK_DOWN                28               DOWN ARROW 鍵

VK_SELECT              29              SELECT 鍵

VK_EXECUTE          2B                 EXECUTE 鍵

VK_SNAPSHOT        2C                    PRINT SCREEN鍵(用于Windows 3.0及以後版本)

VK_INSERT              2D                   INS 鍵

VK_DELETE            2E                         DEL 鍵

VK_HELP                 2F                         HELP鍵

VK_LWIN                 5B                  Left Windows 鍵 (Microsoft自然鍵盤)

VK_RWIN                 5C                Right Windows 鍵 (Microsoft自然鍵盤)

VK_APPS                5D                  Applications 鍵 (Microsoft自然鍵盤)

VK_NUMPAD0         60                 數字小鍵盤上的 0 鍵

VK_NUMPAD1         61                    數字小鍵盤上的 1 鍵

VK_NUMPAD2         62                 數字小鍵盤上的 2 鍵

VK_NUMPAD3         63                 數字小鍵盤上的 3 鍵

VK_NUMPAD4         64                 數字小鍵盤上的 4 鍵

VK_NUMPAD5         65                   數字小鍵盤上的 5 鍵

VK_NUMPAD6        66                數字小鍵盤上的 6 鍵

VK_NUMPAD7        67               數字小鍵盤上的 7 鍵

VK_NUMPAD8          68               數字小鍵盤上的 8 鍵

VK_NUMPAD9         69               數字小鍵盤上的 9 鍵

VK_MULTIPLY          6A              Multiply 鍵

VK_ADD                   6B                 Add鍵

VK_SEPARATOR           6C           Separator 鍵

VK_SUBTRACT             6D              Subtract 鍵

VK_DECIMAL              6E               Decimal 鍵

VK_DIVIDE               6F               數字小鍵盤 / 鍵

VK_F1                    70               F1 鍵

VK_F2                    71                  F2 鍵

VK_F3                    72                   F3 鍵

VK_F4                    73                   F4 鍵

VK_F5                     74               F5 鍵

VK_F6                    75                  F6 鍵

VK_F7                    76                 F7 鍵

VK_F8                    77                  F8 鍵

VK_F9                    78                  F9 鍵

VK_F10                 79                 F10 鍵

VK_F11                 7A                 F11 鍵

VK_F12                 7B                 F12 鍵

VK_F13                 7C               F13 鍵

VK_F14                 7D               F14 鍵

VK_F15                 7 E                   F15 鍵

VK_F16                 7F                F16 鍵

VK_F17                80H               F17 鍵

VK_F18                81H              F18 鍵

VK_F19                82H               F19 鍵

VK_F20               83H            F20 鍵

VK_F21               84H             F21 鍵

VK_F22                85H             F22 鍵

VK_F23               86H            F23 鍵

VK_F24                 87H            F24 鍵

VK_NUMLOCK         90            NUM LOCK 鍵

VK_SCROLL         91             SCROLL LOCK 鍵

VK_ATTN              F6              Attn 鍵

VK_CRSEL          F7               CrSel 鍵

VK_EXSEL           F8             ExSel 鍵

VK_EREOF          F9              Erase EOF 鍵

VK_PLAY            FA           Play 鍵

VK_ZOOM           FB             Zoom 鍵

VK_OEM_CLEAR     FE         Clear 鍵

如何設定單鍵快捷鍵(熱鍵)

下面為這個按鈕添加快捷鍵ctrl+o。左下角切換到“資源視圖”,然後項目名上右鍵>添加>資源

VS2010 MFC中設定HotKey
VS2010 MFC中設定HotKey
VS2010 MFC中設定HotKey

其中IDR_ACCELERATOR1 為加速鍵資源ID,在它上面右鍵>屬性,打開“快捷鍵節點”視窗,可以在這個視窗中修改這個ID,這個ID在後面的代碼中會用到

VS2010 MFC中設定HotKey

此時視窗中間是快捷鍵編輯視窗,點選其中一行則右側顯示這一行響應的編輯器,注意右側視窗的标題

VS2010 MFC中設定HotKey

切換到“類視圖”,在CTestDlg上右鍵>添加>添加變量

VS2010 MFC中設定HotKey

CTestDlg的構造函數中添加加速鍵初始化代碼,注意LoadAccelerators()參數中的IDR_ACCELERATOR1要和之前提到的加速鍵資源ID要一樣

CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)  
    : CDialogEx(CTestDlg::IDD, pParent)  
{  
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);  
    //加速鍵初始化  
    hAccKey=LoadAccelerators(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_ACCELERATOR1));  
}  
           

為CTestDlg類添加PreTranslateMessage虛函數,項目>類向導

VS2010 MFC中設定HotKey

BOOL CTestDlg::PreTranslateMessage(MSG* pMsg)

{  
    if(TranslateAccelerator(m_hWnd,hAccKey,pMsg)){  
        return true;  
    }  
  
    return CDialogEx::PreTranslateMessage(pMsg);  
} 
           

Ctrl+F5,程式運作起來之後點選Ctrl+o就會彈出對話框,和點選“打開”效果一樣。

下面通過響應鍵盤消息的方式讓這個程式對按下字母a也響應“打開”事件。

項目>類向導

VS2010 MFC中設定HotKey
void CTestDlg::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)  
{  
    if('a' == nChar){  
        MessageBox(L"春哥純爺們");  
    }  
    CDialogEx::OnChar(nChar, nRepCnt, nFlags);  
}  
           

但是這樣是不能響應按鍵消息的,因為對話框程式中鍵盤消息會被攔截。還需要在剛才的PreTranslateMessage(MSG*pMsg)函數中用SendMessage重新發送鍵盤消息。修改之後的PreTranslateMessage(MSG*pMsg)函數如下:

BOOL CkeysDlg::PreTranslateMessage(MSG* pMsg)
{
	// TODO: 在此添加專用代碼和/或調用基類

	SendMessage(pMsg->message,pMsg->wParam,pMsg->lParam);

	return 0;


	//return CDialogEx::PreTranslateMessage(pMsg);
}
           

編譯後啟動,我們按下a鍵就會彈出:

VS2010 MFC中設定HotKey

參考文章:http://blog.csdn.net/xing_yufei/article/details/8573774

參考文章:http://blog.csdn.net/whereyougo/article/details/38407339

示例工程: http://download.csdn.net/download/l198738655/9986530

單熱鍵示例工程:http://download.csdn.net/download/l198738655/10265598