Delphi - when to call DragAcceptFiles
I have
procedure TMainForm.FormCreate(Sender: TObject);
begin
DragAcceptFiles (Handle, True ) ;
end ;
but the form does not accept dragged files - no drop cursor, no firing of WM_DROPFILES message.
I had the following construct in my FormShow event (for a different reason - there was code I wanted to execute only once after the form was created, and FormShow was firing more than once during initialisation) :
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 ) in the position shown still doesn't work. If I move it to the top of the routine (so it executes twice), it does work:
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 ;
All the example code I have found seems to call DragAccept during OnCreate. My experiments suggest this is too early, as is the first fire of OnShow. I'm sure something is wrong with my code elsewhere but what might be causing this?
Any TWinControl's HWND can be created and recreated multiple times during its lifetime. The best place to call DragAcceptFiles() is in overriden CreateWnd() and DestroyWnd() methods so that you can (re)register during all (re)creations and unregister during all destructions, eg:
procedure TMainForm.CreateWnd;
begin
inherited;
DragAcceptFiles(Handle, True);
end;
procedure TMainForm.DestroyWnd;
begin
DragAcceptFiles(Handle, False);
inherited;
end;
The FormShow
event firing more than once in your application is a sign that the handle of the form is destroyed and recreated at least once, most probably because you change one of the properties that requires the window handle to be recreated. Changing the stay-on-topness is one example.
If the handle is recreated then the new one will of course not receive any messages the previous handle was registered to receive.
What you need to do is to call DragAcceptFiles()
after the final handle has been created, or (as that may be hard to do) indeed multiple times.
I have found that issues like this are easily handled by a custom message that you post to yourself in the FormCreate. For example:
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;
The trigger mechanism is the PostMessage
, so whenever you invoke that command it will invoke your custom message routine. Of course if that is the case then I would call it something other than wmFirstRun.
精彩评论