C++ 在鼠标下滚动窗口
如果查看Visual Studio 2012,您会注意到,如果使用鼠标滚轮,鼠标下的窗口将滚动,而不是聚焦窗口。也就是说,如果您将光标放在代码编辑器中,并将鼠标移动到解决方案资源管理器窗口上并滚动,则解决方案资源管理器将滚动,而不是代码编辑器。然而,WM_mouseweel消息只发送到聚焦窗口,因此在本例中,代码编辑器。我们如何实现我们的程序,使WM_鼠标滚轮消息在鼠标下滚动窗口,这是直观的,而不是聚焦窗口?显然,我们可以在程序的核心解决这个问题。查看消息循环的代码,它应该在WinMain方法中:C++ 在鼠标下滚动窗口,c++,windows,winapi,mouseevent,messages,C++,Windows,Winapi,Mouseevent,Messages,如果查看Visual Studio 2012,您会注意到,如果使用鼠标滚轮,鼠标下的窗口将滚动,而不是聚焦窗口。也就是说,如果您将光标放在代码编辑器中,并将鼠标移动到解决方案资源管理器窗口上并滚动,则解决方案资源管理器将滚动,而不是代码编辑器。然而,WM_mouseweel消息只发送到聚焦窗口,因此在本例中,代码编辑器。我们如何实现我们的程序,使WM_鼠标滚轮消息在鼠标下滚动窗口,这是直观的,而不是聚焦窗口?显然,我们可以在程序的核心解决这个问题。查看消息循环的代码,它应该在WinMain方法中
while (GetMessage (&msg, NULL, 0, 0) > 0)
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
这里,我们只需要说,如果消息是WM_MOUSEWHEEL消息,我们希望将其传递到鼠标下的窗口,而不是焦点窗口:
POINT mouse;
while (GetMessage (&msg, NULL, 0, 0) > 0)
{
//Any other message.
if (msg.message != WM_MOUSEWHEEL)
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
//Send the message to the window over which the mouse is hovering.
else
{
GetCursorPos (&mouse);
msg.hwnd = WindowFromPoint (mouse);
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
现在,鼠标下的窗口将始终显示滚动消息,而不是聚焦窗口。显然,我们可以在程序的核心解决这个问题。查看消息循环的代码,它应该在WinMain方法中:
while (GetMessage (&msg, NULL, 0, 0) > 0)
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
这里,我们只需要说,如果消息是WM_MOUSEWHEEL消息,我们希望将其传递到鼠标下的窗口,而不是焦点窗口:
POINT mouse;
while (GetMessage (&msg, NULL, 0, 0) > 0)
{
//Any other message.
if (msg.message != WM_MOUSEWHEEL)
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
//Send the message to the window over which the mouse is hovering.
else
{
GetCursorPos (&mouse);
msg.hwnd = WindowFromPoint (mouse);
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
现在,鼠标下的窗口将始终获得滚动消息,而不是聚焦窗口。在应接收消息的父窗口和子窗口中处理WM_MOUSEWHEEL消息 在子窗口的WM_鼠标滚轮处理程序中执行以下操作:
POINT mouse;
GetCursorPos(&mouse);
if (WindowFromPoint(mouse) != windowHandle)
{
// Sends the WM_MOUSEWHEEL message to your parent window
return DefWindowProc(windowHandle, message, wParam, lParam);
}
然后在父窗口的WM_鼠标滚轮处理程序中执行以下操作:
POINT mouse;
GetCursorPos(&mouse);
HWND hwnd = WindowFromPoint(mouse);
SendMessage(hwnd, message, wParam, lParam);
这样,如果子窗口具有焦点,另一个实际有鼠标指针悬停在其上的窗口将接收WM_MOUSEWHEEL消息。在应接收消息的父窗口和子窗口中处理WM_MOUSEWHEEL消息 在子窗口的WM_鼠标滚轮处理程序中执行以下操作:
POINT mouse;
GetCursorPos(&mouse);
if (WindowFromPoint(mouse) != windowHandle)
{
// Sends the WM_MOUSEWHEEL message to your parent window
return DefWindowProc(windowHandle, message, wParam, lParam);
}
然后在父窗口的WM_鼠标滚轮处理程序中执行以下操作:
POINT mouse;
GetCursorPos(&mouse);
HWND hwnd = WindowFromPoint(mouse);
SendMessage(hwnd, message, wParam, lParam);
这样,如果子窗口具有焦点,另一个实际有鼠标指针悬停在其上的窗口将接收WM_MOUSEWHEEL消息。我发现在应用程序类中重写PreTranslateMessage函数要简单得多
BOOL MyApp::PreTranslateMessage(MSG* pMsg)
{
POINT mouse;
CWnd* windowUnderMouse;
if (pMsg->message == WM_MOUSEWHEEL)
{
GetCursorPos(&mouse);
pMsg->hwnd = WindowFromPoint(mouse);
}
return CWinApp::PreTranslateMessage(pMsg);
}
希望它能帮助别人。我发现在应用程序类中重写PreTranslateMessage函数要简单得多
BOOL MyApp::PreTranslateMessage(MSG* pMsg)
{
POINT mouse;
CWnd* windowUnderMouse;
if (pMsg->message == WM_MOUSEWHEEL)
{
GetCursorPos(&mouse);
pMsg->hwnd = WindowFromPoint(mouse);
}
return CWinApp::PreTranslateMessage(pMsg);
}
希望它能帮助别人。只是对前面答案的修改。 应使用嵌入在消息中的鼠标坐标,而不是当前坐标,如果消息处理延迟,它们可能会有所不同
BOOL CMyApp::PreTranslateMessage (MSG* pMsg)
{
if (pMsg -> message == WM_MOUSEWHEEL)
pMsg -> hwnd = WindowFromPoint (CPoint (GET_X_LPARAM (pMsg -> lParam), GET_Y_LPARAM (pMsg -> lParam)));
return CWinAppEx::PreTranslateMessage (pMsg);
}
只是对先前答案的修改。 应使用嵌入在消息中的鼠标坐标,而不是当前坐标,如果消息处理延迟,它们可能会有所不同
BOOL CMyApp::PreTranslateMessage (MSG* pMsg)
{
if (pMsg -> message == WM_MOUSEWHEEL)
pMsg -> hwnd = WindowFromPoint (CPoint (GET_X_LPARAM (pMsg -> lParam), GET_Y_LPARAM (pMsg -> lParam)));
return CWinAppEx::PreTranslateMessage (pMsg);
}
这是一个很好的想法,但不幸的是,
WM_mouseweel
被直接发送到具有焦点的窗口,因此它不会显示在GetMessage
循环中。嗯,它似乎可以工作。我认为GetMessage仅在消息由SendMessage、SendMessageCallback、SendMessageTimeout或SendNotifyMessage(MSDN)发布时直接向windows发送消息,并为TranslateMessage和DispatchMessage检索所有其他消息,WM_MOUSEWHEEL就是其中之一。这很好地模拟了Windows 10中鼠标滚轮的新默认行为。对的调用仅对键盘输入消息有意义。您不需要在WM\u mouseweel
处理程序中调用它。还请注意,当应用程序进入模式循环时(最明显的是在打开模式对话框时),此代码就会失败。这是一个不错的想法,但不幸的是,WM_mouseweel
会直接发送到具有焦点的窗口,因此它不会显示在GetMessage
循环中。嗯,它似乎可以工作。我认为GetMessage仅在消息由SendMessage、SendMessageCallback、SendMessageTimeout或SendNotifyMessage(MSDN)发布时直接向windows发送消息,并为TranslateMessage和DispatchMessage检索所有其他消息,WM_MOUSEWHEEL就是其中之一。这很好地模拟了Windows 10中鼠标滚轮的新默认行为。对的调用仅对键盘输入消息有意义。您不需要在WM\u mouseweel
处理程序中调用它。还请注意,当应用程序进入模式循环时(最明显的是,打开模式对话框时),此代码就会失败。如果您没有自己的消息泵(即,如果您使用DialogBoxParam),此解决方案会容易得多。@DavidGausmann:这几乎不容易。您必须为每个子控件创建子类,才能使其正常工作。你错过了一个,它以非常微妙的方式断裂。并不是说你会有很多选择,但这肯定不容易。如果你没有自己的消息泵(即,如果你使用DialogBoxParam),这个解决方案会容易得多。@DavidGausmann:这几乎不容易。您必须为每个子控件创建子类,才能使其正常工作。你错过了一个,它以非常微妙的方式断裂。并不是说你会有很多选择,但这肯定不容易。感谢发布此解决方案-正如你所说,这比以前发布的解决方案简单得多。感谢发布此解决方案-正如你所说,这比以前发布的解决方案简单得多。