主窗口的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;
}
答
正如卢克所说,你需要“子类化”按钮的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将在控件之间选中并激活默认按钮)来替换该对话框。
WM_MOUSEMOVE被张贴到按钮窗口,而不是你的主窗口;如果要截取此消息,您可以继承按钮窗口的子类。 – Luke 2010-07-30 01:12:41