【问题标题】:Win32 API 2 child buttons of the main window are not getting the WM_MOUSEMOVE message主窗口的 Win32 API 2 子按钮未收到 WM_MOUSEMOVE 消息
【发布时间】:2010-07-30 00:41:12
【问题描述】:

我有一个带有 2 个子按钮的窗口,当我将鼠标悬停在上方时,我最初试图让它们的文本改变颜色,但是当我将 MessageBox () 放在 WM_MOUSEMOVE 消息中时,我发现我停止收到消息当我的光标位于任一按钮上时框。 MSDN 说 WM_MOUSEMOVE 被发送到包含光标的窗口,所以..我一定是做错了什么。

HWND hparent;
HWND hplaybtt;
HWND hexitbtt;
HINSTANCE hinstance;

LRESULT CALLBACK MainProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

void MakeWindow () {
 WNDCLASSEX wc;
 wc.cbSize        = sizeof (WNDCLASSEX);
 wc.style         = CS_HREDRAW | CS_VREDRAW;
 wc.lpfnWndProc   = MainProc;
 wc.cbClsExtra    = 0;
 wc.cbWndExtra    = 0;
 wc.hCursor       = LoadCursor( NULL, IDC_ARROW);
 wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
 wc.lpszMenuName  = NULL;
 wc.lpszClassName = L"Window";
 wc.hInstance     = hinstance;
 wc.hIcon         = NULL;
 wc.hIconSm       = NULL;
 RegisterClassEx (&wc);

 hparent = CreateWindowEx (0, L"Window", L"Slot Machine", WS_OVERLAPPEDWINDOW, 0, 0, 300, 300,
  NULL, NULL, hinstance, NULL);
 hplaybtt = CreateWindowEx (0, L"Button", L"Play", WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, 110, 125, 80, 50,
  hparent, (HMENU) 101, hinstance, NULL);
 hexitbtt = CreateWindowEx (0, L"Button", L"Exit", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 110, 175, 80, 50,
  hparent, (HMENU) 102, hinstance, NULL);

 ShowWindow (hparent, SW_SHOW);
}

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
 hinstance = hInstance;
 MSG Msg;

 MakeWindow (); 

 while (GetMessage (&Msg, NULL, 0, 0)) {
  TranslateMessage(&Msg);
        DispatchMessage(&Msg);
 }     

 return Msg.wParam;
}

LRESULT CALLBACK MainProc (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
 PAINTSTRUCT ps;
 COLORREF cr = RGB (255, 0, 0);
 COLORREF white = RGB (255, 255, 255);
 HDC hdc;
 LPDRAWITEMSTRUCT dis;

    switch(Msg) {
  case WM_DRAWITEM:
   dis = (LPDRAWITEMSTRUCT) lParam;
   FillRect (dis->hDC, &dis->rcItem, (HBRUSH) GetStockObject (BLACK_BRUSH));
   SetBkMode (dis->hDC, TRANSPARENT);
   SetTextColor (dis->hDC, white);
   TextOut (dis->hDC, 25, 15, L"Play", 4);
   MessageBox (hWnd, L"hi", NULL, MB_OK);
   break;
  case WM_PAINT:
   hdc = BeginPaint (hparent, &ps);
   SetTextColor (hdc, cr);
   TextOut (hdc, 105, 50, L"Slot Machine", 12);
   EndPaint (hparent, &ps);
   break;
  case WM_MOUSEMOVE:
   POINT p;
   p.x = LOWORD (lParam);
   p.y = HIWORD (lParam);

   MessageBox (hWnd, L"This is the slot machine game.", L"About", MB_OK);

   break;
  case WM_DESTROY:
   PostQuitMessage(WM_QUIT);
   break;
  default:
   return DefWindowProc(hWnd, Msg, wParam, lParam);
 }
 return 0;
}

【问题讨论】:

  • WM_MOUSEMOVE 发布到按钮窗口,而不是您的主窗口;如果你想拦截这个消息,你可以子类化按钮窗口。

标签: winapi


【解决方案1】:

正如 Luke 所说,您需要对按钮的 wndproc 进行“子类化”。

http://msdn.microsoft.com/en-us/library/ms633570%28VS.85%29.aspx#subclassing_window

【讨论】:

    【解决方案2】:

    每当您在窗口上有控件时(例如按钮),如果您想正确支持键盘焦点,则需要将消息循环调整为更像这样:

    while (GetMessage (&Msg, NULL, 0, 0) >0)
    {
      if(!IsDialogMessage(hwnd,&msg))
      {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
      }
    }
    

    这提供了如何处理对主窗口有意义的键盘(和鼠标)消息的示例,而不是它们通常被分派到的控件。 在消息循环中处理它们。

    在这种情况下,将 IsDialogMessage() 替换为对处理鼠标悬停效果的函数的调用(并调用 IsDialogMessage() 以确保 TAB 和 ENTER 将在控件之间切换并激活默认按钮)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-07
      • 2010-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多