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的窗口进行文件拖放。但是有一个问题,控件还没有父级。当它要成为父级时,本机控件将被销毁,然后在其新父级中重新创建,当然会获得不同的句柄,从而使注册状态无效。

A control might get recreated for various other reasons too. For this reason, it is better to put our code in overriden CreateWnd and DestroyWnd methods, whenever the handle changes or the window is about to be destroyed, our code will run.

于 2013-01-18T20:09:33.767 回答
3

正如@SertacAkyuz 所说,您问题的解决方案是覆盖CreateWnd()要调用的方法,DragAcceptFiles()而不是在构造函数中这样做。我只想提一下,在 Windows Vista 及更高版本下,用户界面特权隔离 (UIPI) 生效,因此如果您的应用程序在 UAC 下以提升状态运行,那么您还需要调用ChangeWindowMessageFilter()允许WM_COPYGLOBALDATA($0049) 和WM_DROPFILES消息从较低权限的进程(如 Windows 资源管理器)传递到您的应用程序,否则拖放将无法正常工作。

WM_DROPFILES已经弃用了很长时间,取而代之的IDropTarget是更强大、更灵活的新界面。新代码应该使用IDropTarget而不是WM_DROPFILES. 有关详细信息,请参阅 MSDN:

使用拖放和剪贴板传输壳对象

IDropTarget提供的灵活功能之一WM_DROPFILES是能够使用单个IDropTarget对象接受拖放,不仅在特定HWND的 .exe 文件上,而且在应用程序的 .exe 文件本身上,以及在 Shell 弹出菜单中使用它,甚至允许其他应用程序直接将数据传递给您的应用程序,而无需使用窗口消息或其他 IPC 机制。

于 2013-01-18T19:31:29.657 回答