Delphi - когда вызывать DragAcceptFiles - PullRequest
5 голосов
/ 14 октября 2010

У меня есть

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 ;

Кажется, что весь найденный мной пример кода вызывает DragAccept во время OnCreate.Мои эксперименты показывают, что это слишком рано, так как это первый пожар OnShow.Я уверен, что что-то не так с моим кодом в другом месте, но что может быть причиной этого?

Ответы [ 3 ]

8 голосов
/ 14 октября 2010

Любой HWND TWinControl может быть создан и воссоздан несколько раз в течение своей жизни.Лучшее место для вызова DragAcceptFiles () - переопределить методы CreateWnd () и DestroyWnd (), чтобы вы могли (пере) зарегистрироваться во всех (пере) созданиях и отменить регистрацию при всех деструкциях, например:

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

procedure TMainForm.DestroyWnd;
begin 
  DragAcceptFiles(Handle, False);
  inherited;
end;
1 голос
/ 14 октября 2010

Я обнаружил, что подобные проблемы легко решаются с помощью специального сообщения, которое вы отправляете себе в 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.

1 голос
/ 14 октября 2010

Событие FormShow, запускаемое более одного раза в вашем приложении, является признаком того, что дескриптор формы уничтожен и воссоздан хотя бы один раз, скорее всего потому, что вы изменили одно из свойств, для которого требуется воссоздать дескриптор окна. Изменение стойкости - один из примеров.

Если дескриптор воссоздается, то новый, разумеется, не будет получать сообщений, для которых был зарегистрирован предыдущий дескриптор.

Что вам нужно сделать, это позвонить DragAcceptFiles() после того, как окончательный дескриптор был создан, или (как это может быть трудно сделать) действительно несколько раз.

...