我正在尝试允许拖放到我的应用程序上的托盘图标。
我知道使用更高级别的C#WindowsForms API执行此操作impossible,因为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
我在某个论坛遇到过,但无济于事),但它开始觉得太过分了对于这样一个“简单”的用例。
所以百万美元的问题是:
请记住,这是我第一次使用.NET,C#和Win32(不到一周);详细解答为什么 - 而不仅仅是陈述 - 将非常感谢!
感谢。
答案 0 :(得分:3)
是的,你真的需要做那些事情,因为窗口是由另一个进程拥有的。全局钩子需要一个可以注入的DLL。完整的D + D支持需要RegisterDragDrop和COM代码。 Icky COM代码。
不,你真的不应该这样做,因为其他人可能已经有了和你一样的想法。并让他的程序先发货。 MSFT的appcompat团队必须对其进行噩梦。小心翼翼的Raymond Chen,他有一个坏脾气。