【发布时间】:2013-01-18 17:57:45
【问题描述】:
我正在尝试创建一个接受从 Windows 资源管理器中删除的文件的 TShellListView 的后代。我想在我的组件定义中处理拖放,而不必在任何使用该组件的应用程序中实现它(我找到了接受从 Windows 资源管理器中删除的文件的示例,但都是在应用程序/TForm 级别)。
我在构造函数中调用 DragAcceptFiles(),并为 WM_DROPFILES 定义了一个消息处理程序。但是,当我在示例项目中使用此组件并从 Windows 资源管理器中拖动文件时:
我看到“不接受”图标(带斜线的圆圈),而不是我可以删除文件的指示。
如果我尝试删除文件,我不会听到 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.
【问题讨论】:
-
也许控件正在重新创建并且句柄正在改变?
-
@Sertac:HandleNeeded 调用会阻止这种情况吗?
-
@jachguate - 不,访问句柄会产生完全相同的效果。在继承后调用“DragAcceptFiles”行到覆盖的 CreateWnd 将是解决方案。
-
@LarryLustig:
TWinControl.Handle属性提供的HWND不是持久的。它可以在组件的生命周期内被销毁和重新创建,甚至多次。每次TShellListView分配一个新的HWND时,您都必须再次调用DragAcceptFiles(TRUE)。覆盖CreateWnd()允许您这样做。为了更好地衡量,您还应该在HWND被销毁之前覆盖DestroyWnd()以调用DragAcceptFiles(FALSE)。 -
@jachguate:更准确地说,
CreateHandle()被首先调用,它调用CreateWnd(),它调用CreateWindowHandle()来创建实际的HWND。稍后,DestroyHandle()被调用,它调用DestroyWnd(),它调用DestroyWindowHandle()来销毁HWND。还有一些情况是直接调用DestroyWindowHandle()而不调用DestroyWnd(),比如TWinControl析构函数。
标签: delphi drag-and-drop delphi-2010 windows-shell