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

发布于 2024-09-27 07:27:41 字数 1398 浏览 5 评论 0原文

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

我知道用更高的版本不可能做到这一点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(不到一周);解释原因的详细答案 - 而不仅仅是陈述 - 将不胜感激!

谢谢。

I'm trying allow drag and drop to the tray icon on my application.

I know it's impossible to do this with the higher level C# WindowsForms API, since NotifyIcon doesn't support drag events.

So with a little help of a more windows-experienced friend I set out to try this via Win32 API. The idea was registering a hook in the tray window handler (after setting DragAcceptFiles(hWnd,TRUE); on the "SysPager" window handler).

The hooking and dropping part is working from the tray to the 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);
}

As expected I get the message box popping up.

The problem is that I now need to call a function on my C# (WindowsForms) application to notify of this event. Here's where I ran into brick wall.

When I register the callback from my application in the DLL, I store it; but when myHookProc is called, it's value is NULL.

Turns out I was misunderstanding how DLLs work; there isn't a shared instance between my application and the tray area (they're copied or each has its own "instance" if you could call it that) so I can't use any static variables or anything like that to hold the callback reference back to my application.

Spent a couple of hours investigating this and the only solution seems to be shared memory (tried the #pragma data_seg I ran into in some forum, but to no avail), but it starts to feel too much of an overkill for such a "simple" use case.

So the million dollar questions are:

  1. Is it really necessary to offload the hooking to a DLL?
  2. Do I really need to resort to shared memory to accomplish this?
  3. (Bonus question) WM_DROPFILES only works for files; how can I get a drop event fired for text?

Please keep in mind this is my first shot with .NET, C# and Win32 (less than a week); detailed answers explaining why - rather than just stating - will be greatly appreciated!

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

九公里浅绿 2024-10-04 07:27:41

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

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

Yes, you really need to do those things because the window is owned by another process. Global hooks require a DLL that can be injected. Full D+D support requires RegisterDragDrop and COM code. Icky COM code.

And no, you really should not do this because somebody else might have already had the same idea as you. And got his program shipped first. The appcompat team at MSFT must have a nightmare with it. Careful with Raymond Chen, he's got a Bad Temper.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文