首先,我想要完成的是:拦截(通过低级鼠标挂钩)WM_MOUSEHWHEEL
消息以在 Windows 的文件浏览器历史记录中来回前进,或者如果无法访问历史记录,至少到父窗口。
这就是一切的开始,并不是说我不知道它是否可能,特别是使用触摸板,但那是我的意图。所以我开始查看更常见的WM_MOUSEWHEEL
(垂直滚动),却发现这些消息大部分时间都没有生成!
根据MSDNWM_MOUSEWHEEL
文档:
当鼠标滚轮旋转时发送到焦点窗口。DefWindowProc 函数将消息传播到窗口的父级。不应该有消息的内部转发,因为 DefWindowProc 将它向上传播到父链,直到它找到一个处理它的窗口。
好的,看起来不错,所以当鼠标滚轮旋转时,该消息将发送到具有焦点的窗口。让我们看看在 Visual Studio 实用程序包中的 Spy++ 的帮助下是否是这种情况,对其进行录制并将其上传到 YouTube,在此 Stack Exchange 中似乎不允许嵌入:https ://youtu.be /YJvjw_BPJf0
总结起来,并没有WM_MOUSEWHEEL
为所有测试的程序生成。Explorer 是我尝试查看的第一个,重点关注窗口具有的不同子窗口,并确保它是可滚动的。
我可以看到它的滚动条部分收到了一些相关消息,但仅此而已,任何地方都没有该消息的迹象(但是,VM_VSCROLL
已发布到滚动条的一个窗口)。
接下来是 Notepad3, nada,它SysListView32
什么都看不到,父窗口会收到一些通知、激活消息等,但与滚动无关。
一切都SysListView32
收到了一些LVS_SCROLL
消息,但它没有对它们采取行动(它的消息循环可能正在寻找 darn WM_MOUSEWHEEL
s)。
最后是一个浏览器,什么都没有,“视图”根本没有注册任何东西,而父窗口通过事件的外观捕获了鼠标。
注意:对于那些看过视频的人,请注意,虽然 Spy++ 处于顶部,但它在所有测试中都没有焦点,它只是被固定了,所以我可以看到消息。
我几乎放弃了,从他们在 Visual Studio 中为您提供的默认示例 Win32 应用程序开始,我添加了一个挂钩过程,如果收到该消息,它将打印一个消息框,以防万一它是外壳以某种方式获取消息.
当我直接在 VS 中运行代码时,我感到惊讶的是,当我滚动浏览代码时会看到消息框。怎么回事?!
再次触发 Spy++(也是 64 位,因为它是我正在运行的 2022 预览版),让我们看看,它们就在那里!
每当我用两根手指用触控板垂直滚动时,代码编辑器子窗口都会收到这些消息。那么发生了什么?
我的意思是,我什至尝试运行提升到更高完整性级别的示例代码,看看这是否会使这些消息出现,但无济于事。
代码很简单,大部分是作为示例 Win32 应用程序自动生成的,但钩子和过程如下:
// The callback procedure:
LRESULT CALLBACK mouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode == 0) {
if (wParam == WM_MOUSEWHEEL)
MessageBox(NULL, L"We got it!", L"Yay!", MB_OK);
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
...
// Setting the mouse hook (at the application's entry point):
HHOOK mouseHook = SetWindowsHookEx(WH_MOUSE_LL, mouseHookProc, hInstance, 0);
if (!mouseHook) {
LPWSTR errorMessage = NULL;
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, (LPWSTR)&errorMessage, 0, NULL) == 0) {
MessageBox(NULL, L"Couldn't format the error message...", L"Error", MB_OK | MB_ICONERROR);
}
MessageBox(NULL, errorMessage, L"Damn", MB_OK | MB_ICONERROR);
LocalFree(errorMessage);
return FALSE;
}
尽管我将其标记为 C,但它确实适用于在 Windows 中运行并且可以访问低级鼠标事件的任何语言,无论是否托管。
PS。顺便说一句,虽然我一开始提到的意图是开始这一切的动机,但我认为这是不可能的。如果即使在可滚动控件中也不总是生成垂直滚动消息,那么当没有可滚动的内容时,我看不到会生成水平滚动消息。它很可能需要在文件资源管理器本身中实现。