问题描述
我正在尝试创建TShellListView的后代,以接受从Windows资源管理器中删除的文件。我想处理组件定义中的拖放操作,而不必在使用该组件的任何应用程序中实现它(我已经找到了接受从Windows资源管理器中删除文件的示例,但都在应用程序/ TForm级别)。
我在构造函数中调用DragAcceptFiles(),并且为WM_DROPFILES定义了一个消息处理程序。但是,当我在示例项目中使用此组件并从Windows资源管理器中拖动文件时:
-
我看到未接受图标(带斜线的圆圈),而不是表明我可以删除该文件。
-
如果我确实尝试删除该文件,则不会听到Beep()。
我认为我没有适当地向Windows警告我控件会接受拖动的文件。任何人都可以建议我所缺少的东西吗?
这是我的组件代码,其中删除了无趣的位:
单位LJLShellListView;
接口
类型
TLJLShellListView = class(TShellListView)
private
过程WMDropFiles(var Msg:TWMDropFiles);消息WM_DROPFILES;
发布的
构造函数Create(AOwner:TComponent);
结尾;
实现
使用ShellAPI;
构造函数TLJLShellListView.Create(AOwner:TComponent);
开始
继承Create(AOwner);
DragAcceptFiles(self.Handle,True);
结尾;
过程TLJLShellListView.WMDropFiles(var Msg:TWMDropFiles);
开始
Beep(); //我从没听到过。
结尾;
结尾。
DragAcceptFiles $在问题代码中,c $ c>调用需要ShellListView的窗口句柄。当代码访问wincontrol的句柄时,VCL检查是否已创建窗口,如果没有,则VCL调用
CreateHandle
并继续创建窗口并返回它的句柄。在此阶段,问题中的代码已成功注册ShellListView的窗口以进行文件拖放。但是有一个问题,该控件尚未成为父项。当要成为父对象时,本机控件将被销毁,然后在其新的父对象中重新创建,并且当然将获得不同的句柄,从而使注册状态无效。
I am attempting to create a descendant of TShellListView that accepts files dropped from Windows Explorer. I want to handle the drag/drop in my component definition without having to implement it in any of the applications that use the component (I've found examples of accepting files dropped from Windows Explorer, but all at the application / TForm level).
I'm calling DragAcceptFiles() in my constructor, and I've defined a message handler for WM_DROPFILES. However, when I use this component in a sample project and drag a file from Windows Explorer:
I see the "not accepted" icon (circle w/ slash) rather than an indication that I can drop the file.
If I do attempt to drop the file, I do not hear the Beep().
I presume that I'm not properly alerting Windows to the fact that my control would like to accept dragged files. Can anyone suggest what I'm missing?
Here's my component code with the uninteresting bits removed:
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.
The DragAcceptFiles
call, in the code in the question, requires the window handle of the ShellListView. When code accesses the handle of a wincontrol, the VCL checks if the window has been created or not, and if not, VCL calls CreateHandle
and proceeds with creating the window and giving back its handle. At this stage, the code in the question successfully registers the ShellListView's window for file drag and drop. But there's a problem, the control is not parented yet. When it is going to be parented, the native control will be destroyed and then created anew in its new parent and of course will acquire a different handle, invalidating the registered state.
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.
这篇关于处理TShellListView后代中的文件删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!