我已經使用C和Windows API創建了一個Windows GUI程序,並且我希望程序能夠使用鍵盤快捷鍵。我設置了一些正在正常工作的加速器,但是當焦點轉到我的程序主窗口的子窗口(例如列表視圖控件或狀態欄控件)時,看起來鍵盤加速器正在轉換爲WM_COMMAND消息爲孩子的窗口,而不是主窗口。因此,當焦點位於子控件上時,我在主窗口的WndProc中處理適當的WM_COMMAND消息時將被忽略。Windows鍵盤快捷鍵和子窗口
我應該如何解決這個問題?
我已經使用C和Windows API創建了一個Windows GUI程序,並且我希望程序能夠使用鍵盤快捷鍵。我設置了一些正在正常工作的加速器,但是當焦點轉到我的程序主窗口的子窗口(例如列表視圖控件或狀態欄控件)時,看起來鍵盤加速器正在轉換爲WM_COMMAND消息爲孩子的窗口,而不是主窗口。因此,當焦點位於子控件上時,我在主窗口的WndProc中處理適當的WM_COMMAND消息時將被忽略。Windows鍵盤快捷鍵和子窗口
我應該如何解決這個問題?
我找到了答案。主窗口的子窗口必須進行子類化,以便可以攔截由鍵盤快捷鍵生成的WM_COMMAND消息並將其傳遞給父窗口。
這涉及將控件的窗口過程更改爲不同的窗口過程。備用過程處理應通過將消息發送到父窗口來攔截的消息。指向原始窗口過程的指針也必須存儲在某處,以便控件可以正常工作。
窗口過程可以使用SetWindowLongPtr和GWLP_WNDPROC進行更改。
下面是如何通過存儲的指針到原來的窗口過程中的控制的用戶數據值(GWLP_USERDATA)做一個簡單的例子:
的代碼來改變窗口過程,並存儲在所述原程序GWLP_USERDATA:
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)WndProc));
的攔截窗口過程:
static LRESULT CALLBACK WndProc(const HWND hWnd, const UINT message, const WPARAM wParam, const LPARAM lParam)
{
switch(message)
{
case WM_COMMAND:
SendMessage(GetParent(hWnd), message, wParam, lParam);
return 0;
default:
//Assume that GWLP_USERDATA has been set to the original window procedure.
return CallWindowProc((WNDPROC)GetWindowLongPtr(hWnd, GWLP_USERDATA), hWnd, message, wParam, lParam);
}
}
另一種方法是避免使用TranslateAccelerator智爲LD窗口,示例代碼:
if (mainWidget() && msg.hwnd == mainWidget()->hwnd()) {
if (TranslateAccelerator(msg.hwnd, hMainAccelTable, &msg)) {
continue;
}
}
TranslateMessage(&msg);
DispatchMessage(&msg);
如果消息是不是mainWidget的,我們不使用它的主要部件的加速表translateaccelerator。