簡體   English   中英

處理TShellListView后代中的文件丟棄

[英]Handle file drop in TShellListView descendant

我正在嘗試創建一個TShellListView的后代,它接受從Windows資源管理器中刪除的文件。 我想處理組件定義中的拖放操作,而不必在任何使用該組件的應用程序中實現它(我已經找到了從Windows資源管理器中刪除文件的示例,但所有這些都在應用程序/ TForm級別)。

我在構造函數中調用DragAcceptFiles(),並為WM_DROPFILES定義了一個消息處理程序。 但是,當我在示例項目中使用此組件並從Windows資源管理器中拖動文件時:

  1. 我看到“未接受”圖標(帶斜線的圓圈),而不是我可以刪除文件的指示。

  2. 如果我確實試圖刪除文件,我聽不到Beep()。

我認為我沒有正確警告Windows我的控件想要接受拖動文件的事實。 任何人都可以建議我缺少什么?

這是我的組件代碼刪除了不感興趣的位:

    unit LJLShellListView;

    interface

    type

      TLJLShellListView = class(TShellListView)
      private
        procedure WMDropFiles(var Msg: TWMDropFiles); message WM_DROPFILES;
      published
        constructor Create(AOwner: TComponent);
      end;

    implementation

    uses ShellAPI;

    constructor TLJLShellListView.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      DragAcceptFiles(self.Handle, True);
    end;

    procedure TLJLShellListView.WMDropFiles(var Msg: TWMDropFiles);
    begin
      Beep();  // I never hear this.
    end;

    end.

在問題的代碼中, DragAcceptFiles調用需要ShellListView的窗口句柄。 當代碼訪問wincontrol的句柄時,VCL檢查窗口是否已創建,如果沒有,VCL調用CreateHandle並繼續創建窗口並返回其句柄。 在這個階段,問題中的代碼成功注冊了ShellListView的文件拖放窗口。 但是有一個問題,控制還沒有成為父級。 當它將成為父級時,本機控件將被銷毀,然后在其新父級中重新創建,當然將獲得不同的句柄,使注冊狀態無效。

控件可能會因各種其他原因而重新創建。 出於這個原因,最好將我們的代碼放在重寫的CreateWndDestroyWnd方法中,每當句柄改變或窗口即將被銷毀時,我們的代碼就會運行。

正如@SertacAkyuz所說,你的問題的解決方案是覆蓋CreateWnd()方法來調用DragAcceptFiles()而不是在構造函數中這樣做。 我只想提一下,在Windows Vista及更高版本中,用戶界面權限隔離(UIPI)生效,因此如果您的應用程序在UAC下以提升狀態運行,那么您還需要調用ChangeWindowMessageFilter()以允許WM_COPYGLOBALDATA ($ 0049)和WM_DROPFILES消息將從較低權限的進程(如Windows資源管理器)傳遞到您的應用程序,否則拖放操作將無法正常工作。

WM_DROPFILES已經被棄用了很長時間,轉而使用更新的IDropTarget接口,它更強大,更靈活。 新代碼應該使用IDropTarget而不是WM_DROPFILES 有關更多詳細信息,請參閱MSDN:

使用拖放和剪貼板傳輸Shell對象

IDropTarget提供的靈活功能之一WM_DROPFILES不能使用單個IDropTarget對象來接受拖放操作,不僅可以在特定的HWND ,還可以在應用程序的.exe文件本身上進行拖放,以及使用它在Shell彈出菜單中,甚至允許其他應用程序直接將數據傳遞到您的應用程序,而無需使用窗口消息或其他IPC機制。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM