Как сохранить модальный диалог поверх динамической созданной формы? (CreateParams — переопределен)

#delphi #modal-dialog #delphi-2010

#delphi #модальный диалог #delphi-2010

Вопрос:

Я динамически создаю форму, которая переопределяет CreateParams, чтобы она отображалась на панели задач. Из динамически созданной формы я вызываю TColorDialog, но как только он отобразится, моя форма перейдет под основную форму с ColorDialog поверх нее.

После закрытия ColorDialog динамическая форма вернется обратно поверх основной формы.

Я вижу, что в методе выполнения ColorDialog есть дескриптор, который можно передать, но я не уверен, что я на правильном пути с этим?

Если я нажму под диалогом в основной форме, он будет мигать, но как я могу заставить динамически созданную форму «владеть» этим диалогом с основной формой сзади?

Я создаю форму следующим образом:

 procedure TMain.Button1Click(Sender: TObject);
var
  SEMArcF: TWriteSEMArcFrm;
begin
  SEMArcF := TWRiteSEMArcFrm.Create(nil);
  SEMArcF.Show;
end; 
  

и он освобождается при событии OnClose:

 procedure TWriteSEMArcFrm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;
  

Я переопределяю CreateParams следующим образом:

 procedure TWriteSEMArcFrm.CreateParams(var Params: TCreateParams);
begin
  inherited;
  if (FormStyle = fsNormal) then begin
    Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
    Params.WndParent := GetDesktopWindow;
  end;
end;
  

и чтобы показать ColorDialog, я либо создаю его, либо просто добавляю компонент TColorDialog в форму, в любом случае результат будет одинаковым. Я хочу, чтобы он принадлежал динамической форме.

РЕДАКТИРОВАТЬ Я теперь добавляю:

 Application.ModalPopupMode := pmAuto;
  

Полный код:

 procedure TWriteSEMArcFrm.btnBackColourClick(Sender: TObject);
var
  ColorDlg: TColorDialog;
begin
  Application.ModalPopupMode := pmAuto;
  ColorDlg := TColorDialog.Create(nil);
  try
    if ColorDlg.Execute then
    re.Color := ColorDlg.Color;
  finally
    ColorDlg.Free;
  end;
end;
  

Это работает нормально, но может ли быть какое-либо необычное поведение при установке этого параметра?

Спасибо

Крис

Комментарии:

1. Не должен ли «SEMArcF := TWRiteSEMArcFrm.Create (nil);» быть «SEMArcF:= TWRiteSEMArcFrm.Create (self);»

2. @mj2008 — Я удостоверяюсь, что форма освобождена с помощью: Action := caFree Основная форма может быть помещена в лоток, поэтому я хочу, чтобы она была освобождена, как только она будет закрыта. Если пользователь похож на меня и оставляет компьютер включенным навсегда, он никогда не освободится!

Ответ №1:

TColorDialog происходит от TCommonDialog , в котором доступны две перегруженные версии Execute() — устаревшая версия без параметров, которая существует годами, и более новая перегрузка, которая принимает родительский HWND параметр в качестве входного параметра. Скорее всего, вы вызываете первое. Эта перегрузка использует Handle свойство текущего активного TForm (только если TApplication.ModalPopupMode для свойства не установлено значение pmNone ), возвращаясь к Handle MainForm значению, если это необходимо. Если вы хотите больше контроля, вам следует вызвать другую перегрузку напрямую, тогда вы можете передать свойство динамической формы Handle в качестве значения параметра.

Комментарии:

1. Большое вам спасибо за ответ. Теперь я вызываю Application.ModalPopupMode := pmAuto; непосредственно перед созданием и отображением ColorDialog, и это работает. Я приму это как ответ, но хотел бы спросить — может ли это вызвать какое-либо необычное поведение в дальнейшем? Я отредактирую вопрос, чтобы показать полный код создания ColorDialog.

2. Вам не нужно устанавливать свойство каждый раз, когда вы вызываете диалоговое окно. Вместо этого вы можете установить его один раз в файле main .dpr. Или просто проигнорируйте свойство и используйте TColorDialog.Execute(HWND) вместо него метод, например: ColorDlg.Execute(Self.Handle); .

3. Спасибо за объяснение этого и за ваше время, потраченное на то, чтобы помочь мне. Это здорово, и я многому здесь учусь 🙂