Форма скрыта за другими формами, когда вызывается ShowModal
Мое приложение основано на модальных формах. Основная форма открывает одну форму с помощью ShowModal, эта форма открывает другой с помощью ShowModal, поэтому у нас есть сложные модальные формы. Иногда возникает проблема, что, когда мы вызываем ShowModal в новой форме, он скрывается за предыдущими формами, вместо того, чтобы показывать сверху. После нажатия alt + tab форма возвращается к вершине, но это нехорошее решение. Вы столкнулись с этой проблемой и как вы справились с ней?
ИЗМЕНИТЬ
Я использую Delphi 7.
Ответы
Ответ 1
Вы не указали, какую версию Delphi...
Новые версии Delphi добавили два новых свойства в TCustomForm: PopupMode и PopupParent. Настройка PopupParent вашего модального диалога в форме, создающей этот диалог, гарантирует, что дочерняя форма останется на вершине родителя. Обычно это исправляет проблему, которую вы описываете.
Я думаю, что эта пара свойств была добавлена в Delphi 2006, но, возможно, это было в 2005 году. Они определенно существуют в Delphi 2007 и выше.
EDIT: увидев, что вы используете Delphi 7, единственное, что у меня есть, это то, что в коде, который отображает вашу модальную форму, вы отключите форму, создав ее, и снова включите при возврате. Это должно препятствовать тому, чтобы окно создания получало вход, что может помочь правильному правилу Z.
Что-то вроде этого может работать (непроверено, поскольку я больше не использую D7):
procedure TForm1.ShowForm2;
begin
Self.Enabled := False;
try
with TForm2.Create(nil) do
begin
try
if ShowModal = mrOk then
// Returned OK. Do something;
finally
Free;
end;
end;
finally
Self.Enabled := True;
end;
end;
Если Form2 создает модальное окно (как вы уже упоминали), просто повторите процесс - отключите Form2, создайте Form3 и покажите его по-разному и снова включите Form2, когда он вернется. Обязательно используйте try..finally, как я показал, так что если что-то пойдет не так в модальной форме, форма создания всегда будет снова включена.
Ответ 2
Извините за добавление отдельного ответа, но я провел немного больше исследований, и некоторые из них указывают, что мой предыдущий ответ (DisableProcessWindowsGhosting) не помогает. Поскольку я не всегда могу воспроизвести эту проблему, я не могу сказать точно.
Я нашел подходящее решение. Я ссылался на код в Delphi 2007 для метода CreateParams, и он довольно близок (без использования всего другого кода, который обрабатывает PopupMode).
Я создал блок, ниже которого подклассы TForm
.
unit uModalForms;
interface
uses Forms, Controls, Windows;
type
TModalForm = class(TForm)
protected
procedure CreateParams(var params: TCreateParams); override;
end;
implementation
procedure TModalForm.CreateParams(var params: TCreateParams);
begin
inherited;
params.WndParent := Screen.ActiveForm.Handle;
if (params.WndParent <> 0) and (IsIconic(params.WndParent)
or not IsWindowVisible(params.WndParent)
or not IsWindowEnabled(params.WndParent)) then
params.WndParent := 0;
if params.WndParent = 0 then
params.WndParent := Application.Handle;
end;
То, что я делаю тогда, это включить этот блок с модулем формы, а затем изменить класс формы (в файле кода .pas) от class(TForm)
до class(TModalForm)
Он работает для меня, кажется, близок к решению CodeGear.
Ответ 3
Из этой ссылка кажется, что проблема связана с "окном Ghosting", который был введен в 2000/XP. Вы можете отключить функцию ореола, вызвав следующий код при запуске.
procedure DisableProcessWindowsGhosting;
var
DisableProcessWindowsGhostingProc: procedure;
begin
DisableProcessWindowsGhostingProc := GetProcAddress(
GetModuleHandle('user32.dll'),
'DisableProcessWindowsGhosting');
if Assigned(DisableProcessWindowsGhostingProc) then
DisableProcessWindowsGhostingProc;
end;
Единственная проблема, которую я вижу, заключается в том, что это вызовет проблемы с функцией, которая позволяет пользователю минимизировать, перемещать или закрывать главное окно приложения, которое не отвечает. Но таким образом вам не нужно покрывать каждый вызов кодом Self.Enabled := False
.
Ответ 4
Просто установите свойство Visible
формы, которую вы хотите открыть модальным, до False
. Затем вы можете открыть его с помощью .ShowModal();
, и он будет работать.
Ответ 5
попробуйте
OnShowForm:
PostMessage(Self.Handle, WM_USER_SET_FOCUS_AT_START, 0, 0);
Ответ 6
Я обнаружил, что использование флага "Всегда поверх" более чем в одной форме вызывает проблемы с порядком Z. И вы также можете найти функцию BringWindowToTop
.
При запуске окна сообщений с использованием встроенного WinAPI (MessageBox
) я обнаружил, что передача дескриптора вызывающего окна необходима, чтобы убедиться, что приглашение отображается сверху все время.