5

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

我知道使用更高级别的 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);
}

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

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

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

原来我误解了 DLL 的工作原理。我的应用程序和托盘区域之间没有共享实例(它们被复制或者每个都有自己的“实例”,如果你可以调用它的话)所以我不能使用任何静态变量或类似的东西来保存回调引用回到我的应用程序。

花了几个小时对此进行调查,唯一的解决方案似乎是共享内存(尝试了#pragma data_seg我在某个论坛中遇到的问题,但无济于事),但对于这样一个“简单”的用例来说,它开始觉得太过分了.

所以百万美元的问题是:

  1. 真的有必要将挂钩卸载到 DLL 吗?
  2. 我真的需要求助于共享内存来完成这个吗?
  3. (奖金问题) WM_DROPFILES 仅适用于文件;如何为文本触发 drop 事件?

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

谢谢。

4

1 回答 1

3

是的,您确实需要做这些事情,因为该窗口归另一个进程所有。全局挂钩需要一个可以注入的 DLL。完整的 D+D 支持需要 RegisterDragDrop 和 COM 代码。恶心的 COM 代码。

不,你真的不应该这样做,因为其他人可能已经和你有同样的想法。并首先发布了他的程序。MSFT 的 appcompat 团队一定是做噩梦了。小心雷蒙德陈,他脾气暴躁。

于 2010-10-13T18:41:04.787 回答