将文件/文本拖放到托盘图标(C#,WindowsForms)

bia*_*bit 5 dll hook winapi drag-and-drop system-tray

我正在尝试允许拖放到我的应用程序上的托盘图标.

我知道用更高级别的C#WindowsForms API做这件事是不可能的,因为NotifyIcon它不支持拖动事件.

所以在一位经验丰富的Windows朋友的帮助下,我开始尝试通过Win32 API.想法是在托盘窗口处理程序中注册一个钩子(在DragAcceptFiles(hWnd,TRUE);"SysPager"窗口处理程序上设置之后).

挂钩和下降部分正在从托盘到DLL工作.

LRESULT CALLBACK myHookProc (int code, WPARAM wParam, LPARAM lParam){
  if (code == HC_ACTION)
  {
    PMSG msg = (PMSG) lParam;
    switch(msg->message){
      case WM_DROPFILES:
        ::MessageBox(NULL, L"Dropped files!", L"Test", MB_OK);
        // call my app's registered hook
        break;
  }
  return CallNextHookEx(oldHookProc, code, wParam, lParam);
}
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,我弹出了消息框.

问题是我现在需要在我的C#(WindowsForms)应用程序上调用一个函数来通知这个事件.这是我遇到砖墙的地方.

当我从DLL中的应用程序注册回调时,我存储它; 但是当myHookProc被调用时,它的值为NULL.

事实证明我误解了DLL是如何工作的; 没有我的应用程序和托盘区(他们复制或每个人都有自己的"实例",如果你可以调用它的),所以我不能使用任何静态变量或类似的东西,以保持之间的共享实例回调参考回到我的应用程序.

花了几个小时研究这一点,唯一的解决办法似乎是共享内存(试过#pragma data_seg我跑进一些论坛,但都无济于事),但它开始觉得太矫枉过正的这种"简单"的用例.

所以百万美元的问题是:

  1. 是否真的有必要将挂钩卸载到DLL?
  2. 我真的需要求助于共享内存才能实现这一目标吗?
  3. (奖金问题)WM_DROPFILES仅适用于文件; 如何为文本触发drop事件?

请记住这是我第一次使用.NET,C#和Win32(不到一周); 解释原因的详细解答 - 而不仅仅是陈述 - 将不胜感激!

谢谢.

Han*_*ant 3

是的,您确实需要做这些事情,因为窗口由另一个进程拥有。全局钩子需要一个可以注入的 DLL。完整的 D+D 支持需要 RegisterDragDrop 和 COM 代码。令人讨厌的 COM 代码。

不,你真的不应该这样做,因为其他人可能已经有与你相同的想法。并首先交付了他的程序。MSFT 的 appcompat 团队肯定对此做了一场噩梦。小心雷蒙·陈,他脾气很坏。