主窗口的Win32 API 2子按钮没有得到WM_MOUSEMOVE消息

问题描述:

我有一个带有2个子按钮的窗口,当我将鼠标悬停在外面时我最初试图使它们的文本颜色改变,但是当我把WM_MOUSEMOVE消息中的MessageBox()我发现当光标位于任一按钮上时,我停止收到消息框。 MSDN说,WM_MOUSEMOVE被发送到包含光标的窗口,所以..我一定是做错了什么。主窗口的Win32 API 2子按钮没有得到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; 
} 
+1

WM_MOUSEMOVE被张贴到按钮窗口,而不是你的主窗口;如果要截取此消息,您可以继承按钮窗口的子类。 – Luke 2010-07-30 01:12:41

正如卢克所说,你需要“子类化”按钮的wndproc。

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

只要你有一个窗口上的控件 - 比如按钮 - 如果你要正确地支持键盘焦点,您需要调整您的消息循环,以更多的东西是这样的:

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

这提供了如何处理键盘(和鼠标)消息的例子,这些消息对主窗口有意义,而不是通常分派给它们的控件。 在消息循环中处理它们。在这种情况下,将IsDialogMessage()替换为将处理鼠标悬停效果的函数(并调用IsDialogMessage()以确保TAB和ENTER将在控件之间选中并激活默认按钮)来替换该对话框。