为什么我的表单在文件被删除时不会收到WM_DropFiles?

use*_*419 6 delphi drag-and-drop

我正在使用Embarcadero RAD Studio XE来开发应用程序.我正在尝试使用以下代码将文件拖放到应用程序中

TMainForm = class(TForm)
public:
  procedure WMDropFiles(var Msg: TWMDropFiles); message WM_DROPFILES;
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  DragAcceptFiles(Self.Handle, True);
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
  DragAcceptFiles(Self.Handle, False);
end;

procedure TMainForm.WMDropFiles(var Msg: TWMDropFiles);
begin
  inherited;
  showmessage('catch here');
  // some code to handle the drop files here
  Msg.Result := 0;
end;
Run Code Online (Sandbox Code Playgroud)

这段代码没有问题.此外,当我拖放文件时,光标显示状态已更改为拖放,但在删除后,没有任何反应(也未显示任何消息).这有什么不对吗?

Dav*_*nan 8

在普通的vanilla应用程序中,问题中的代码会导致在WMDropFiles表单上删除对象时执行.所以,显然还有其他事情可以阻止它发挥作用.最明显的潜在原因是:

  1. 初始调用后,将重新创建主窗体的窗口句柄DragAcceptFiles.
  2. 您的进程运行的完整性级别高于删除其上的文件的进程.例如,您是否以管理员身份运行流程?请注意,以IDE身份运行Delphi IDE会导致您的进程在从IDE启动时以管理员身份运行.
  3. 您的过程中的其他任何东西都会干扰拖放.不知道你的应用程序中有什么,很难猜出这可能是什么.开始删除部分应用,直到除了问题中的代码之外什么都没有留下.

方案2似乎很合理.要了解更多信息,请参阅:问:当我的应用程序运行高架时,为什么不拖放工作? - 答:强制完整性控制和UIPI

  • 要解决#1,重写表单的`CreateWnd()`和`DestroyWnd()`方法来调用`DragAcceptFiles()`,不要使用`OnCreate`和`OnDestroy`事件.要解决#2,使用`ChangeWindowMessageFilter/Ex()`来允许来自较低特权进程的`WM_DROPFILES`消息. (3认同)

小智 7

TForm.Create使用两条线

ChangeWindowMessageFilter (WM_DROPFILES, MSGFLT_ADD);

ChangeWindowMessageFilter (WM_COPYGLOBALDATA, MSGFLT_ADD);
Run Code Online (Sandbox Code Playgroud)

就这样