如何将鼠标滚轮信息重定向到其他窗口?

时间:2011-05-05 11:18:40

标签: windows winapi ole mousewheel

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

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

在这种特殊情况下的任何提示?谢谢!

5 个答案:

答案 0 :(得分:7)

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

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

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

答案 1 :(得分:2)

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

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

答案 2 :(得分:0)

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

1)处理WM_MOUSEHOVER消息。

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

答案 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;
}