c++ DoDragDrop期间的WM_MOUSEWHEEL?

i7uaboj4  于 2023-04-01  发布在  其他
关注(0)|答案(1)|浏览(132)

我们有一个遗留的C++ Win32应用程序,它使用OLE DoDragDrop来处理拖放。在拖放过程中是否可以接收鼠标滚轮消息?
我的IDropTarget示例实现了以下回调:

virtual HRESULT STDMETHODCALLTYPE DragEnter(IDataObject *pDataObj, DWORD dwGrfKeyState, 
    POINTL pt, DWORD *pdwEffect) override;
virtual HRESULT STDMETHODCALLTYPE DragOver(DWORD dwGrfKeyState, POINTL pt, 
    DWORD *pdwEffect) override;
virtual HRESULT STDMETHODCALLTYPE DragLeave() override;
virtual HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObj, DWORD dwGrfKeyState, POINTL pt,
    DWORD *pdwEffect) override;

没有鼠标滚轮信息的回调。WM_MOUSEWHEEL事件被分派到我的窗口proc,而 * 不 * 拖动东西。在拖放过程中,我没有收到任何WM_MOUSEWHEEL事件。

w1jd8yoj

w1jd8yoj1#

事实证明,用钩子是可能的,但这并不漂亮。
我在DoDragDrop之前安装了两个钩子,并在DoDragDrop返回时再次删除它们。

HHOOK hHook = ::SetWindowsHookEx(
    WH_MOUSE, // high-level mouse events
    ::MouseHookProc,
    nullptr,
    ::GetCurrentThreadId() // we're interested in our own events only
);

HHOOK hHook2 = ::SetWindowsHookEx(
    WH_MOUSE_LL, // low-level mouse events
    ::MouseLLHookProc,
    ::GetModuleHandle(nullptr), // WH_MOUSE_LL can only be watched globally
    0
);

HRESULT hResult = ::DoDragDrop(
    pData,
    pSrc,
    DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK,
    &dwEffect
);

if (hHook) ::UnhookWindowsHookEx(hHook);
if (hHook2) ::UnhookWindowsHookEx(hHook2);

低级钩子可以访问鼠标滚轮增量,但它不知道鼠标经过的HWND。高级钩子可以访问HWND,但它不知道鼠标滚轮增量。看起来低级钩子首先被调用,所以我只是将增量存储在一个全局变量中,并从高级钩子使用它:

int g_nLastMouseWheelDelta = 0;

LRESULT CALLBACK MouseLLHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
   if (nCode == HC_ACTION)
   {
      if (wParam == WM_MOUSEWHEEL && lParam != 0)
      {
         auto pDetails = (MSLLHOOKSTRUCT *) lParam;
         g_nLastMouseWheelDelta = GET_WHEEL_DELTA_WPARAM(pDetails->mouseData);
      }
   }

   // Always pass the event on through the hook chain.    
   return ::CallNextHookEx(nullptr, nCode, wParam, lParam);
}

LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
   if (nCode == HC_ACTION)
   {
      if (wParam == WM_MOUSEWHEEL && lParam != 0)
      {
         if (g_nLastMouseWheelDelta != 0)
         {
            auto pDetails = (MOUSEHOOKSTRUCT *) lParam;

            // Since we pass our threadId to SetWindowsHookEx, we can safely 
            // assume that the hwnd belongs to us.
            MyWin *pWin = /* determine MyWin structure */(pDetails->hwnd);

            if (pWin)
            {
               // Posting a Windows message during drag & drop may lead to 
               // problems, so we handle the mouse wheel directly!
               WPARAM newWP = MAKELONG(0, g_nLastMouseWheelDelta);
               LPARAM newLP = MAKELONG(pDetails->pt.x, pDetails->pt.y);
               pWin->handleEvent(WM_MOUSEWHEEL, newWP, newLP);
            }
         }
      }
   }

   // Always pass the event on through the hook chain.    
   return ::CallNextHookEx(nullptr, nCode, wParam, lParam);
}

相关问题