7

Windows エクスプローラーからドロップされたファイルを受け入れる TShellListView の子孫を作成しようとしています。コンポーネントを使用するアプリケーションにドラッグ アンド ドロップを実装せずに、コンポーネント定義でドラッグ アンド ドロップを処理したい (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.
4

2 に答える 2

8

質問のコードでのDragAcceptFiles呼び出しには、ShellListViewのウィンドウハンドルが必要です。コードがwincontrolのハンドルにアクセスすると、VCLはウィンドウが作成されたかどうかを確認し、作成されていない場合は、VCLが呼び出しCreateHandleてウィンドウの作成とハンドルの返送を続行します。この段階で、質問のコードは、ファイルのドラッグアンドドロップ用にShellListViewのウィンドウを正常に登録します。しかし、問題があります。コントロールはまだペアレント化されていません。親になると、ネイティブコントロールは破棄され、新しい親で新しく作成されます。もちろん、別のハンドルを取得して、登録された状態を無効にします。

コントロールは、他のさまざまな理由でも再作成される可能性があります。このため、コードをオーバーライドさCreateWndれたDestroyWndメソッドに配置することをお勧めします。ハンドルが変更されたり、ウィンドウが破棄されようとしているときはいつでも、コードが実行されます。

于 2013-01-18T20:09:33.767 に答える
3

@SertacAkyuzが言ったように、あなたの質問に対する解決策は、コンストラクターでCreateWnd()呼び出すDragAcceptFiles()代わりにメソッドをオーバーライドすることです。Windows Vista 以降では、User Interface Privilege Isolation (UIPI) が有効になるため、アプリが UAC の下で昇格された状態で実行されている場合は、ChangeWindowMessageFilter()許可WM_COPYGLOBALDATA($0049) とWM_DROPFILESメッセージを呼び出す必要があります。 Windows エクスプローラーなどの権限の低いプロセスからアプリに配信されない場合、ドラッグ アンド ドロップが正しく機能しません。

WM_DROPFILESIDropTargetは、はるかに強力で柔軟な新しいインターフェイスを支持して、長い間廃止されてきました。IDropTargetの代わりに新しいコードを使用する必要がありWM_DROPFILESます。詳細については、MSDN を参照してください。

ドラッグ アンド ドロップとクリップボードによるシェル オブジェクトの転送

IDropTarget提供されていない柔軟な機能の 1 つはWM_DROPFILES、単一のIDropTargetオブジェクトを使用して、特定の だけでなく、アプリの .exe ファイル自体でもドラッグ アンド ドロップを受け入れHWND、シェル ポップアップ メニューで使用できることです。 、さらにはウィンドウ メッセージやその他の IPC メカニズムを使用せずに、他のアプリがアプリにデータを直接渡すことができるようにします。

于 2013-01-18T19:31:29.657 に答える