Delphi - 何时调用DragAcceptFiles

5

I have

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

但是表单不接受拖放的文件——没有拖放光标,也没有触发WM_DROPFILES消息。
我在FormShow事件中使用了以下结构(出于其他原因——有些代码只想在表单创建后执行一次,而FormShow在初始化期间会多次触发):
procedure TMainForm.FormShow(Sender: TObject);

begin
if (not FRunOnce) then  // as FormShow can be called twice - if Form.Position assigned to
    begin
    DragAcceptFiles (Handle, True ) ; 
    FRunOnce := True ;
    end ;
end ;

DragAcceptFiles (Handle, True ) 在如图所示的位置仍然无法正常工作。如果我将其移动到程序的顶部(使其执行两次),它就可以正常工作:

procedure TMainForm.FormShow(Sender: TObject);

begin
DragAcceptFiles (Handle, True ) ; 
if (not FRunOnce) then  // as FormShow can be called twice - if Form.Position assigned to
    begin
    FRunOnce := True ;
    end ;
end ;

我找到的所有示例代码似乎都在OnCreate期间调用DragAccept。 我的实验表明这太早了,就像OnShow的第一次触发一样。 我确定我的其他代码有问题,但可能是什么原因?
3个回答

8

在TWinControl的生命周期中,它的HWND可以被创建和重新创建多次。最好的调用DragAcceptFiles()方法的地方是重写CreateWnd()和DestroyWnd()方法,这样你就可以在所有(重新)创建时注册并在所有销毁时注销,例如:

procedure TMainForm.CreateWnd;
begin 
  inherited;
  DragAcceptFiles(Handle, True);  
end;

procedure TMainForm.DestroyWnd;
begin 
  DragAcceptFiles(Handle, False);
  inherited;
end;

1
我发现像这样的问题可以通过在FormCreate中发布自定义消息来轻松处理。例如:
CONST
  wm_FirstRun = WM_USER + 101;


TYPE
  TForm1 = class(TForm)
  :
    Procedure wmFirstRun(var Msg:tMessage); message wm_FirstRun;
    procedure FormCreate(Sender: TObject); 
  :
  end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // other initialization code
  PostMessage(handle,wm_FirstRun,0,0);
end;

Procedure TForm1.wmFirstRun(var Msg:tMessage);
begin
  // handle the code here that will run once the form is processing messages
end;

触发机制是 PostMessage,因此每当您调用该命令时,它将调用您的自定义消息例程。当然,如果是这种情况,我会将其称为其他名称而不是 wmFirstRun。

那么你的意思是将dragacceptFiles放在这个消息处理程序中,可以确保它在oncreate和onshow事件之后被调用? - rossmcm
1
是的...但只有一次,因为它在onCreate中被请求。 - skamradt
我注意到一些答案已经消失了。是谁做的,为什么? - rossmcm
有些人会删除他们的答案,如果他们认为这些答案与问题不再相关,以避免被踩。 - skamradt

1

FormShow 事件在您的应用程序中触发多次是表明窗体句柄被销毁并重新创建至少一次的迹象,最可能是因为您更改了需要重新创建窗口句柄的属性之一。改变置顶性就是一个例子。

如果句柄被重新创建,则新句柄当然不会接收到先前注册要接收的任何消息。

您需要做的是在最终句柄创建后调用 DragAcceptFiles(),或者(由于这可能很难做到)确实多次调用。


我认为这是关键。我之前没有意识到句柄在表单的整个生命周期中可能会不同。 - rossmcm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接