我正在Windows上开发Word addin for MS Word,这个插件在Word文档窗口的左侧显示和停靠“高级任务窗格”(它的树视图(大纲)显示Word文档列表用于快速编辑项目中的多个文档。
我的问题是,Word文档窗口只有当它聚焦时才会响应鼠标滚轮消息,但我想能够在鼠标光标悬停时用鼠标滚轮滚动文档在它上甚至Word文档窗口没有输入焦点。
在这种特殊情况下的任何提示?谢谢!
答案 0 :(得分:7)
不太确定它会起作用,但我会尝试以下方法:
使用SetWindowsHookEx函数实现全局低级鼠标挂钩。 在钩子过程中,应该在鼠标滚轮滚动事件上调用,检查鼠标光标下的窗口是否是Word文档窗口。如果是这样,请设置一个共享标志,指示所需的滚动操作。 不要直接从钩子程序发送WM_VSCROLL!这个程序必须非常快速和简单。
现在,在加载项的消息循环中检查标志,如果已设置,则将WM_VSCROLL发送到Word文档窗口。
答案 1 :(得分:2)
也许您可以使用SetCapture(hWnd)
Windows API函数。这将导致所有鼠标事件转到您的hWnd 而不是 hWnd通常希望接收它们的任何内容。如果你在鼠标进入Word文档窗口时捕获,当鼠标离开或{Word获得焦点时ReleaseCapture()
捕获它,它应该可以正常工作。
免责声明:之前我曾在C#中使用鼠标捕获,但我从未在C ++中使用它。我不知道它的行为是否完全相同。
答案 2 :(得分:0)
答案 3 :(得分:0)
使用Spy ++我看到获取消息的窗口属于类_Wwg
(至少是2003),它正在响应WM_MOUSEWHEEL
消息。因此,当您希望滚动时,您会向该窗口发送WM_MOUSEWHELL
消息。
答案 4 :(得分:0)
我已经从https://msdn.microsoft.com/en-us/library/windows/desktop/ms645617(v=vs.85).aspx
中的评论中剪下了C ++代码我成功地使用了它(及其变体)。
编写它的用户声称它的灵感来自Windows Vista最佳实践指南中的ms推荐,将鼠标滚轮事件转发到鼠标光标悬停的任何窗口。他/她实现的优点是它完全没有侵入性,你只需删除它并设置钩子,引用你的主线程。它避免将事件转发到属于其他进程的窗口,但也许这实际上可能是一件好事。
namespace {
LRESULT CALLBACK mouseInputHook(int nCode, WPARAM wParam, LPARAM lParam) {
//"if nCode is less than zero, the hook procedure must pass the message to the CallNextHookEx function
//without further processing and should return the value returned by CallNextHookEx"
if (nCode >= 0) {
MSG& msgInfo = *reinterpret_cast<MSG*>(lParam);
if (msgInfo.message == WM_MOUSEWHEEL ||
msgInfo.message == WM_MOUSEHWHEEL) {
POINT pt = {};
pt.x = ((int)(short)LOWORD(msgInfo.lParam)); //yes, there's also msgInfo.pt, but let's not take chances
pt.y = ((int)(short)HIWORD(msgInfo.lParam)); //
//visible child window directly under cursor; attention: not necessarily from our process!
//http://blogs.msdn.com/b/oldnewthing/archive/2010/12/30/10110077.aspx
if (HWND hWin = ::WindowFromPoint(pt))
if (msgInfo.hwnd != hWin && ::GetCapture() == nullptr) {
DWORD winProcessId = 0;
::GetWindowThreadProcessId(//no-fail!
hWin, //_In_ HWND hWnd,
&winProcessId); //_Out_opt_ LPDWORD lpdwProcessId
if (winProcessId == ::GetCurrentProcessId()) //no-fail!
msgInfo.hwnd = hWin; //it would be a bug to set handle from another process here
}
}
}
return ::CallNextHookEx(nullptr, nCode, wParam, lParam);
}
struct Dummy {
Dummy() {
hHook = ::SetWindowsHookEx(WH_GETMESSAGE, //__in int idHook,
mouseInputHook, //__in HOOKPROC lpfn,
nullptr, //__in HINSTANCE hMod,
::GetCurrentThreadId()); //__in DWORD dwThreadId
assert(hHook);
}
~Dummy() {
if (hHook)
::UnhookWindowsHookEx(hHook);
}
private:
HHOOK hHook;
} dummy;
}