應用程式通常會定義鍵盤快捷方式,例如 [檔案開啟] 命令的 CTRL+O。 您可以藉由處理個別的 WM_KEYDOWN 訊息來實作鍵盤快捷方式,但快捷鍵表格提供更好的解決方案:
- 需要較少的程式代碼撰寫。
- 將所有快捷方式合併成一個數據檔。
- 支援將當地語系化為其他語言。
- 啟用快捷方式和功能表命令,以使用相同的應用程式邏輯。
快速鍵數據表 是一種數據資源,會將鍵盤組合,例如 CTRL+O 對應至應用程式命令。 在瞭解如何使用快速鍵數據表之前,我們需要資源的快速簡介。 資源 是應用程式二進位檔 (EXE 或 DLL) 內建的數據 Blob。 資源會儲存應用程式所需的數據,例如功能表、游標、圖示、影像、文字字串或任何自定義應用程式數據。 應用程式會在運行時間從二進位檔載入資源數據。 若要在二進位檔中包含資源,請執行下列動作:
- 建立資源定義 (.rc) 檔案。 此檔案會定義資源類型及其識別碼。 資源定義檔可能包含其他檔案的參考。 例如,圖標資源會在 .rc 檔案中宣告,但圖示影像會儲存在個別的檔案中。
- 使用 Microsoft Windows 資源編譯程式 (RC) 將資源定義檔編譯成已編譯的資源 (.res) 檔案。 RC 編譯程序隨附於 Visual Studio 和 Windows SDK。
- 將編譯的資源文件連結至二進位檔。
這些步驟大致相當於程式代碼檔案的編譯/鏈接程式。 Visual Studio 提供一組資源編輯器,可讓您輕鬆地建立和修改資源。 (這些工具不適用於 Visual Studio 的 Express 版本。但 .rc 檔案只是文本檔,而且語法記載於 MSDN 上,因此可以使用任何文本編輯器建立 .rc 檔案。 如需詳細資訊,請參閱 關於資源檔案。
定義快速鍵數據表
快速鍵表格是鍵盤快捷方式的表格。 每個快捷方式的定義方式如下:
- 數值識別碼。 這個數位會識別快捷方式所叫用的應用程式命令。
- 快捷方式的 ASCII 字元或虛擬按鍵碼。
- 選擇性修飾詞鍵:ALT、SHIFT 或 CTRL。
快速鍵數據表本身具有數值識別碼,可識別應用程式資源清單中的數據表。 讓我們為簡單的繪圖程式建立快速鍵數據表。 此程式會有兩種模式:繪製模式和選取模式。 在繪製模式中,用戶可以繪製圖形。 在選取模式中,用戶可以選取圖形。 針對此程序,我們想要定義下列鍵盤快捷方式。
| 捷徑 | 命令 |
|---|---|
| CTRL+M | 在模式之間切換。 |
| F1 | 切換至繪製模式。 |
| F2 | 切換至選取模式。 |
首先,定義數據表和應用程式命令的數值標識碼。 這些值是任意的。 您可以在頭檔中定義識別碼的符號常數。 例如:
#define IDR_ACCEL1 101
#define ID_TOGGLE_MODE 40002
#define ID_DRAW_MODE 40003
#define ID_SELECT_MODE 40004
在此範例中,值 IDR_ACCEL1 識別快速鍵數據表,而接下來的三個常數會定義應用程式命令。 依照慣例,定義資源常數的頭檔通常會命名為 resource.h。 下一個清單會顯示資源定義檔。
#include "resource.h"
IDR_ACCEL1 ACCELERATORS
{
0x4D, ID_TOGGLE_MODE, VIRTKEY, CONTROL // ctrl-M
0x70, ID_DRAW_MODE, VIRTKEY // F1
0x71, ID_SELECT_MODE, VIRTKEY // F2
}
快捷鍵快捷方式定義於大括弧內。 每個快捷方式都包含下列專案。
- 叫用快捷方式的虛擬索引鍵程式代碼或 ASCII 字元。
- 應用程式命令。 請注意,範例中會使用符號常數。 資源定義檔包含 resource.h,其中會定義這些常數。
- 關鍵詞 VIRTKEY 表示第一個專案是虛擬密鑰程式代碼。 另一個選項是使用 ASCII 字元。
- 選擇性修飾詞:ALT、CONTROL 或 SHIFT。
如果您使用 ASCII 字元進行快捷方式,則小寫字元會與大寫字元不同。 (例如,輸入 'a' 可能會叫用與輸入 'A' 不同的命令。這可能會混淆使用者,因此通常最好針對快捷方式使用虛擬密鑰碼,而不是 ASCII 字元。
載入快速鍵數據表
必須先載入快速鍵數據表的資源,程式才能使用它。 若要載入快捷鍵數據表,請呼叫 LoadAccelerators 函式。
HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCEL1));
輸入訊息迴圈之前,請先呼叫此函式。 第一個參數是模組的句柄。 (此參數會傳遞至您的 WinMain 函式。如需詳細資訊,請參閱 WinMain:應用程式進入點。)第二個參數是資源標識碼。 函式會傳回資源的句柄。 回想一下,句柄是一種不透明類型,該類型是指由系統管理的物件。 如果函式失敗,它會 NULL傳回 。
您可以呼叫 DestroyAcceleratorTable來釋放快捷鍵數據表。 不過,當程序結束時,系統會自動釋放數據表,因此只有在您將某個數據表取代為另一個數據表時,才需要呼叫此函式。 本主題中有一個有趣的範例,建立用戶可編輯加速器。
將按鍵筆劃轉譯成命令
快捷鍵數據表的運作方式是將按鍵筆劃轉譯成 WM_COMMAND 訊息。
WM_COMMAND 的 wParam 參數包含命令的數值識別碼。 例如,使用先前顯示的數據表,按鍵筆劃 CTRL+M 會轉譯成具有 值 ID_TOGGLE_MODE的 WM_COMMAND 訊息。 若要發生這種情況,請將您的訊息循環變更為下列專案:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(win.Window(), hAccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
此程式代碼會將呼叫新增至訊息迴圈內的 TranslateAccelerator 函式。 TranslateAccelerator 函式會檢查每個視窗訊息,並尋找向下鍵訊息。 如果使用者按下快捷鍵數據表中列出的其中一個按鍵組合,TranslateAccelerator 將 WM_COMMAND 訊息傳送至視窗。 函式會藉由直接叫用視窗程序來傳送 WM_COMMAND。 TranslateAccelerator 成功轉譯按鍵筆劃時,函式會傳回非零值,這表示您應該略過訊息的一般處理。 否則,TranslateAccelerator 會傳回零。 在此情況下,將視窗訊息傳遞至 TranslateMessage 和 DispatchMessage正常。
以下是繪圖程式如何處理 WM_COMMAND 訊息:
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_DRAW_MODE:
SetMode(DrawMode);
break;
case ID_SELECT_MODE:
SetMode(SelectMode);
break;
case ID_TOGGLE_MODE:
if (mode == DrawMode)
{
SetMode(SelectMode);
}
else
{
SetMode(DrawMode);
}
break;
}
return 0;
此程式代碼假設 SetMode 是由應用程式定義的函式,以在兩種模式之間切換。 處理每個命令的詳細數據顯然取決於您的程式。
下一個