Новое созданное модальное окно теряет фокус и становится недоступным в Windows Vista

Иногда, когда я открываю модальное окно в своем приложении Delphi, требуется некоторое время, чтобы показать его, и я заметил, что приложение вроде бы заблокировано, и произошло то, что модальная форма была открыта с помощью ShowModal, но не отображалась и приложение стало заблокировано, как если бы Модальное окно было в первом слое.

Обычно, когда это происходит, я должен использовать Alt + Tab или Windows + Tab, чтобы найти "скрытое" модальное окно, но это не работает каждый раз.

Такое поведение происходит только в Vista, но его довольно раздражает.

Есть ли способ предотвратить эту "странность фокуса"?

Спасибо.

* РЕДАКТИРОВАТЬ *

Очевидно, установка Application.MainFormOnTaskbar: = True решила проблему, но пока еще слишком рано делать выводы, потому что это происходит случайным образом.

* РЕДАКТИРОВАТЬ 2 *

ModalFormOnTaskbar не решила проблему, после чего я попытался установить PopupMode = pmAuto, но это только что сделало проблему наихудшей.

Сейчас я пытаюсь установить PopupParent явно и сообщит вам, если проблема будет решена.

Ответ 1

Взгляните на свойство PopupParent. Вы можете установить его явно для своей модальной формы до вызова ShowModal. Когда PopupParent равен нулю (по умолчанию), VCL ведет себя несколько иначе, в зависимости от значения связанного свойства PopupMode.

Если вы установите модальную форму PopupParent в форму, активную непосредственно перед вызовом ShowModal, это может помочь.

Ответ 2

Проблема, с которой вы начали, когда в Windows XP появилась концепция оконного ореола. Из-за необычной архитектуры, используемой Delphi (все формы - это дети скрытого окна - TApplication), многие приложения Delphi испытывают ту же проблему.

Один из способов быстро решить это: отключить гашение окна при инициализации приложения:

var 
  User32: HMODULE; 
  DisableProcessWindowsGhosting: TProcedure; 
begin 
  User32 := GetModuleHandle('USER32'); 
  if User32 <> 0 then 
  begin 
    DisableProcessWindowsGhosting := GetProcAddress(User32, 'DisableProcessWindowsGhosting'); 
    if Assigned(DisableProcessWindowsGhosting) then 
      DisableProcessWindowsGhosting; 
  end; 
end;

Другим возможным (более элегантным, но трудоемким) решением является нормализовать приложение Delphi.

Третий вариант: переход на Delphi 2006 (Delphi 10.0).

Помимо проблемы, о которой вы сообщаете, архитектура Delphi представляет больше странностей, среди которых меню различных меню задач и невозможность flash.

Ответ 3

Мне удалось сократить количество этих случаев, удалив любые вызовы Application.ProcessMessages, которые у меня есть в моем коде, где бы я ни был.

Ответ 4

Alt+P+V (.dpr) имеет Application.MainFormOnTaskbar := True; по умолчанию, я не знаю почему, но если я положил Application.MainFormOnTaskbar := False;, проблема будет решена.

Ответ 5

Вы можете попробовать отредактировать Forms.pas, чтобы добавить код ниже в TCustomForm.ShowModal(), перед вызовом Application.ModalStarted():

if Assigned(Application) then begin
  while PeekMessage(msg, Application.Handle, CM_ACTIVATE, CM_DEACTIVATE, PM_REMOVE) do begin
    TranslateMessage(msg);
    DispatchMessage(msg);
  end;
end;

Ответ 6

У меня была такая же проблема в Windows 10, и я решил ее, заменив в файле dpr/dproj:

… Application.CreateForm(TFrmMain, FrmMain);

Application.run;...

От

… Application.CreateForm(TFrmMain, FrmMain);

Попробуйте FrmMain.ShowModal; Наконец FrmMain.Free; Конец;