【问题标题】:How to redirect mouse wheel message to other windows?如何将鼠标滚轮消息重定向到其他窗口?
【发布时间】:2011-05-05 11:18:40
【问题描述】:

我正在 Windows 上开发一个Word addin for MS Word,这个插件作为“高级任务窗格”显示和停靠在 Word 文档窗口的左侧(它的树视图(大纲)显示 Word 文档的列表以便快速在一个项目中编辑多个文档)。

我的问题是,Word 文档窗口只有在聚焦时才会响应鼠标滚轮消息,但我希望能够在鼠标光标悬停时用鼠标滚轮滚动文档在它上面,甚至 Word 文档窗口也没有输入焦点。

在这种特殊情况下有什么提示吗?谢谢!

【问题讨论】:

    标签: windows winapi ole mousewheel


    【解决方案1】:

    不太确定它会起作用,但我会尝试以下方法:

    使用SetWindowsHookEx 函数实现全局低级鼠标挂钩。 在鼠标滚轮滚动事件应该调用的钩子程序中,检查鼠标光标下的窗口是否是Word文档窗口。如果是这样,请设置一个共享标志来指示所需的滚动操作。 不要直接从挂钩过程中发送 WM_VSCROLL! 这个过程必须非常快速和简单。

    现在,在加载项的消息循环中检查标志,如果已设置,则将 WM_VSCROLL 发送到 Word 文档窗口。

    【讨论】:

    • 谢谢你的想法,亚历克斯!看起来是一种可行的方法。
    • @Alex,很抱歉没有早点接受答案,因为我当时放弃实现这个功能,然后忘记了这个问题......刚刚回顾了所有答案,我猜你的会工作的。对不起,赏金......
    • 这似乎是 MSDN 文档中描述的 WM_MOUSEWHEEL 消息的确切系统。 MSDN:WM_MOUSEWHEEL ...只需使用鼠标滚轮一直到底部!
    【解决方案2】:

    也许您可以使用SetCapture(hWnd) Windows API 函数。这将导致所有鼠标事件转到您的 hWnd 而不是 任何 hWnd 通常期望接收它们。如果您在鼠标进入 Word 文档窗口时捕获,并且在鼠标离开或 Word 获得焦点时捕获ReleaseCapture(),它应该可以正常工作。

    免责声明:我以前在 C# 中使用过鼠标捕获,但我从未在 C++ 中使用过。我不知道它的行为是否完全相同。

    【讨论】:

      【解决方案3】:

      尝试以下方法,这可能会对您有所帮助。

      1) 处理WM_MOUSEHOVER 消息。

      2) 在处理程序中,使用 SendMessage,以 WM_VSCROLL 作为消息参数。

      【讨论】:

        【解决方案4】:

        使用 Spy++ 我看到获取消息的窗口属于 _Wwg 类(至少是 2003 年),它正在响应 WM_MOUSEWHEEL 消息。因此,当您希望该窗口滚动时,您可以向该窗口发送WM_MOUSEWHELL 消息。

        【讨论】:

          【解决方案5】:

          我从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;
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-01-16
            • 2010-09-25
            • 2014-08-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-06-25
            相关资源
            最近更新 更多