2009-12-26 115 views
1

我已经使用C和Windows API创建了一个Windows GUI程序,并且我希望程序能够使用键盘快捷键。我设置了一些正在正常工作的加速器,但是当焦点转到我的程序主窗口的子窗口(例如列表视图控件或状态栏控件)时,看起来键盘加速器正在转换为WM_COMMAND消息为孩子的窗口,而不是主窗口。因此,当焦点位于子控件上时,我在主窗口的WndProc中处理适当的WM_COMMAND消息时将被忽略。Windows键盘快捷键和子窗口

我应该如何解决这个问题?

回答

2

我找到了答案。主窗口的子窗口必须进行子类化,以便可以拦截由键盘快捷键生成的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); 
    } 
} 
0

另一种方法是避免使用TranslateAccelerator智为LD窗口,示例代码:

if (mainWidget() && msg.hwnd == mainWidget()->hwnd()) { 
      if (TranslateAccelerator(msg.hwnd, hMainAccelTable, &msg)) { 
       continue; 
      } 
     } 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 

如果消息是不是mainWidget的,我们不使用它的主要部件的加速表translateaccelerator。