2010-10-13 74 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