Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drag and drop files/text to tray icon (C#, WindowsForms)

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.

like image 462
biasedbit Avatar asked Oct 25 '22 04:10

biasedbit


1 Answers

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.

like image 50
Hans Passant Avatar answered Oct 30 '22 22:10

Hans Passant