Подтвердить что ты не робот

Форма скрыта за другими формами, когда вызывается ShowModal

Мое приложение основано на модальных формах. Основная форма открывает одну форму с помощью ShowModal, эта форма открывает другой с помощью ShowModal, поэтому у нас есть сложные модальные формы. Иногда возникает проблема, что, когда мы вызываем ShowModal в новой форме, он скрывается за предыдущими формами, вместо того, чтобы показывать сверху. После нажатия alt + tab форма возвращается к вершине, но это нехорошее решение. Вы столкнулись с этой проблемой и как вы справились с ней?

ИЗМЕНИТЬ

Я использую Delphi 7.

4b9b3361

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