#forms #delphi #delphi-2010
#формы #delphi #delphi-2010
Вопрос:
У меня есть приложение, которое всегда показывает по крайней мере две формы одновременно.
Обычно у меня есть список заданий в дочерней форме основной формы с соответствующими деталями, отображаемыми в основной форме. Другие детали могут управляться с помощью ShowModal .
Текущая проблема заключается в том, что пользователи недавно запросили, чтобы основную форму можно было перетащить перед списком заданий.
Насколько я вижу, поскольку форма списка заданий создается после основной формы и вызывается для отображения из основной формы, она получает «переднюю» позицию.
Есть ли какой-либо способ изменить это во время выполнения, т. Е. Могу ли я установить активную форму впереди?
Ответ №1:
Примечание: В остальной части этого ответа терминология, которой владеет, принимает значение, используемое документацией Windows. Это отличается от значения того же термина в VCL.
Происходит то, что ваше окно списка заданий является принадлежащим окном верхнего уровня.
Принадлежность накладывает несколько ограничений на окно.
- Принадлежащее окно всегда находится выше своего владельца в z-порядке.
- Система автоматически уничтожает принадлежащее окно, когда его владелец уничтожается.
- Принадлежащее окно скрыто, когда его владелец свернут.
Если вы хотите, чтобы окно списка заданий могло находиться ниже главного окна в порядке z, оно не может принадлежать главному окну. Вы можете добиться этого следующим образом:
class TJobListForm = class(...)
protected
procedure CreateParams(var Params: TCreateParams); override;
...
procedure TJobListForm.CreateParams(var Params: TCreateParams);
begin
inherited;
Params.WndParent := Application.Handle;
end;
Это делает окно списка заданий окном верхнего уровня, принадлежащим скрытому окну приложения. Или, альтернативно, как это:
procedure TJobListForm.CreateParams(var Params: TCreateParams);
begin
inherited;
Params.WndParent := 0;
end;
Это делает окно списка заданий недоступным окном верхнего уровня. Таким образом, теперь он получает кнопку на панели задач.
Внесение таких изменений будет иметь далеко идущие последствия для вашего приложения. Второй и третий пункты списка в приведенном выше списке являются очевидными последствиями. Поведение ваших окон при минимизации и их взаимодействие с панелью задач также будут затронуты. Здесь я только поцарапал поверхность. Вероятно, вы обнаружите, что если сделать так, чтобы окно списка заданий больше не принадлежало главному окну, это сильно повлияет на вашу программу. Вы обнаружите, что Windows выполняет за вас большую работу за кулисами для собственного окна. Возможно, вам потребуется воспроизвести часть этой работы, если вы переключитесь на неизвестное окно.
Комментарии:
1. Спасибо за это — именно то, что было нужно. Поведение, похоже, именно то, что я ожидал, давайте посмотрим, что думает пользователь, который запросил изменение.
Ответ №2:
Пока форма списка заданий не является дочерней для любого другого окна (т.Е. Ее Parent
свойство не задано, а ее CreateParams()
метод не переопределен для установки TCreateParams.WndParent
поля), и она отображается с использованием своего Show()
метода вместо своего ShowModal()
метода, пользователь должен иметь возможность свободно переключаться между двумя окнамипо желанию.
Комментарии:
1. Немодальные окна обычно принадлежат основной форме и поэтому всегда находятся над основной формой. Обратите внимание, что под собственным я подразумеваю терминологию Windows, а не терминологию VCL.
2. @David: владение немодальными окнами зависит от версии Delphi. В более старых версиях до введения
PopupMode
свойства они принадлежатTApplication
окну. В более новых версияхpmNone
используетсяMainForm
только, еслиApplication.MainFormOnTaskBar
естьTrue
,pmAuto
используетMainForm
только, если нет подходящегоActiveForm
иApplication.MainFormOnTaskBar
естьTrue
, иpmExplicit
используетMainForm
только, если неPopupParent
назначено.3. Очевидно, что в этом случае окно списка заданий принадлежит главному окну. Это ясно из сообщенного поведения z-порядка.