Как я могу активировать / сфокусировать модальную форму

У меня есть приложение с TTrayIcon Компонентом, который я использую для «Скрытия» и «Восстановления» моей MainForm. Вот что я использую для «Скрытия» (OnTrayClick)

procedure TMainWindow.TrayIcon1Click(Sender: TObject);
var
  I : Integer;
begin
  if Application.MainForm.Visible then begin
    { Hide }
    Application.MainForm.Visible := FALSE;
  end else begin
    { Restore }
    Application.MainForm.Visible := TRUE;
    WindowState := wsNormal;
    Application.BringToFront();
    { Workaround for ModalForms }
    for I := 0 to Screen.FormCount-1 do begin
      if (fsModal in Screen.Forms[I].FormState) then begin
        Screen.Forms[I].BringToFront;
        Screen.Forms[I].SetFocus;
        break; // Stop looking for more ModalForms
      end;
    end;
  end;
end;

Этот пример отлично работает, если нет других открытых (модальных) форм. Но если есть ModalForm, открытый и восстанавливающий мою MainForm, ModalForm, кажется, находится за MainForm, и я не могу до него добраться. Как я могу активировать / сфокусировать ModalForm и поместить его перед моей MainForm после того, как моя MainForm была восстановлена? Мой Application.MainFormOnTaskbar установлен на False

РЕДАКТИРОВАТЬ: если ModalForm открыт, и я восстанавливаю свою MainForm, обе формы вообще не будут фокусироваться.


person Benjamin Weiss    schedule 08.08.2013    source источник
comment
@KenWhite Мне очень жаль. Я изменил свой вопрос. Restore был неправильным термином. Я не скрываю никаких модальных форм.   -  person Benjamin Weiss    schedule 08.08.2013
comment
Бенджамин, это намного яснее. Я удалю свои комментарии, так как они больше не актуальны. :-)   -  person Ken White    schedule 08.08.2013
comment
Почему MainFormOnTaskbar имеет значение false?   -  person David Heffernan    schedule 08.08.2013
comment
@DavidHeffernan Итак, я могу удалить его с панели задач, когда он свернут в лоток.   -  person Benjamin Weiss    schedule 08.08.2013
comment
Нет. Вы устанавливаете для MainFormOnTaskbar значение True и удаляете кнопку с панели задач, делая форму скрытой. Как мы сделали в прошлом вопросе.   -  person David Heffernan    schedule 08.08.2013
comment
Теперь вы открываете из modalform1, modalform2, теперь и mainform, и modalform1 недоступны. Вам снова нужно вывести modulform2 на передний план. Для цикла и выберите первый появившийся fmodal, а break неверен. Вы должны проверить, является ли он modalform2.   -  person moskito-x    schedule 08.08.2013


Ответы (1)


Настройка MainFormOnTaskbar, похоже, вызывает проблему. Вам действительно нужно оставить это значение true.

Вы можете не скрывать формы, если есть модальные окна. В этом случае проверьте Application.ModalLevel> 0 в коде скрытия. Вы даже можете показать всплывающую подсказку о том, что приложение нельзя свернуть, пока сообщения не будут закрыты.

В противном случае, если вы действительно хотите свернуть все окна, приведенный ниже код мне подходит. Скройте все открытые окна, включая модальное окно. Это приведет к тому, что главный значок панели задач исчезнет, ​​и все будет за пределами экрана. Единственное, что вам нужно сделать, это отслеживать, какие окна были только что открыты. Я сделал это ниже, установив значение Tag для форм, которые были только что скрыты. Затем в коде восстановления вы можете вернуть для этих окон значение true.

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

procedure TForm1.TrayIcon1Click(Sender: TObject);
var
  I : Integer;
begin

  if Application.MainForm.Visible then
  begin
    //  Hide
    for I := 0 to Screen.FormCount-1 do
    begin
      if Screen.Forms[i].Visible = true then
      begin
        Screen.Forms[i].Visible := false;
        Screen.Forms[i].Tag := 1;
      end;
    end;

  end
  else
  begin
    // Restore
    for I := 0 to Screen.FormCount-1 do
    begin
      if Screen.Forms[i].Tag = 1 then
      begin
        Screen.Forms[i].Visible := true;
        Screen.Forms[i].Tag := 0;
      end;
    end;

    Application.BringToFront();

  end;
end;

Возможно, вам потребуется установить свойство PopupParent в модальной форме в качестве основной формы. Для новых форм установлено pmAuto, но если это старый проект, это может быть pmNone.

Вот ссылка на сообщение в блоге Аллена на PopupMode и PopupParent и вот еще один вопрос Stackoverflow, посвященный теме Новое модальное окно теряет фокус и становится недоступным в Windows Vista

Обычно я использую что-то вроде этого:

MyPopupForm := TMyForm.Create(Owner);
MyPopupForm.PopupMode := pmAuto;
MyPopupForm.PopupParent := Owner;
MyPopupForm.ShowModal;
person Mark Elder    schedule 08.08.2013
comment
Я пробовал, но, похоже, не работает. Воссоздайте мой пример. Может это недоработка XE4 ?! - person Benjamin Weiss; 08.08.2013
comment
Было бы удивительно, если бы проблема заключалась в этом. Несомненно, pmAuto даст такой же чистый результат. - person David Heffernan; 08.08.2013
comment
@Mark Удалите кнопку на панели задач, сделав форму скрытой. Изменение стиля окна - это не способ сделать это. - person David Heffernan; 08.08.2013
comment
@DavidHeffernan Поскольку Бенджамин устанавливал для Application.MainFormOnTaskbar значение False, я предполагаю, что ему не нужен значок на панели задач, даже когда форма видна. - person Mark Elder; 09.08.2013
comment
@Mark Это свойство не для этого. Он определяет, связана ли кнопка на панели задач с основной формой или со скрытым окном приложения. - person David Heffernan; 09.08.2013
comment
Я перечитал комментарии и неправильно понял, что он искал. Я обновил свой ответ новым подходом. - person Mark Elder; 09.08.2013