2010-10-13 89 views
4

我试图允许拖放到我的应用程序上的托盘图标。将文件/文本拖放到托盘图标(C#,WindowsForms)

我知道它是impossible用更高级别的C#WindowsForms API执行此操作,因为NotifyIcon不支持拖动事件。

因此,借助更多经验丰富的Windows朋友的帮助,我着手通过Win32 API来尝试这种方式。这个想法是在托盘窗口处理程序中注册一个钩子(在“SysPager”窗口处理程序上设置DragAcceptFiles(hWnd,TRUE);之后)。

挂接和放置部分正在从托盘工作到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只适用于文件;我怎样才能得到一个文本的下降事件?

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

谢谢。

回答

2

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

不,你真的不应该这样做,因为别人可能已经有了和你一样的想法。并让他的程序首先发货。 MSFT的appcompat团队必须对此产生噩梦。小心Raymond Chen,他有一个坏脾气。

+0

我明白这是一个坏主意,因为你提到的原因 - 别人的应用程序可能会尝试做同样的事情,然后就会变得非常混乱。然而,这个项目(http://www.codeproject.com/KB/cpp/DragnDropOnTrayIcon.aspx)似乎能够找到特定的应用程序图标,如果它没有隐藏。有了这个,它仍然是一个坏主意吗? – biasedbit 2010-10-14 16:06:54

+0

我已经测试过它,它成功检测到你是否在图标上放置了某些东西,但是它总是显示托盘上的允许放置标记......无论如何,UX对于Windows应用程序来说有点奇怪。 。拖东西到托盘上。 – biasedbit 2010-10-14 16:09:42

+0

奇怪的是,你通常不会在那里看到作者承认自己无法实现的项目。很难看出这不仅仅是浪费你的时间。 – 2010-10-14 16:17:17