Сделать 2 формы способными перекрывать друг друга?

Я хотел бы иметь отдельную форму, которая отображается «вместе» с моей основной формой, поэтому она не перекрывает основную форму.

Вот пример: Пример

Заметили, как основная программа перекрывает журнал? Я не могу понять, как это сделать в Delphi.

Спасибо!


person Jeff    schedule 22.03.2011    source источник
comment
+1, чтобы компенсировать анонимное голосование против.   -  person Sertac Akyuz    schedule 22.03.2011
comment
+1 также, это самый отличный вопрос   -  person David Heffernan    schedule 22.03.2011
comment
Боюсь, я не понимаю, с чем вы боретесь? Если вы создадите совершенно новое приложение и добавите вторую форму, это именно то, что вы получите. Вам не нужно делать ничего особенного. Возможно, будет полезно, если вы объясните, что ваше приложение делает и что вас не устраивает.   -  person Disillusioned    schedule 22.03.2011
comment
@Craig: Нет, ты не понимаешь. Создайте новое приложение форм VCL и сделайте главное окно синим. Теперь добавьте в приложение новую форму; сделать это меньше и красный. Наконец, создайте обработчик OnClick в главной форме и выполните Form2.Show. Вы заметите, что новая красная форма никогда не будет отображаться позади основной, синей формы. Так что вам действительно нужно нужно что-то особенное.   -  person Andreas Rejbrand    schedule 22.03.2011


Ответы (2)


Ответы на этот вопрос содержатся в очень полезном функциях окна раздел MSDN.

Соответствующая информация:

Перекрывающееся или всплывающее окно может принадлежать другому перекрывающемуся или всплывающему окну. Владение накладывает на окно несколько ограничений.

  • Принадлежащее окно всегда выше своего владельца в z-порядке.
  • Система автоматически уничтожает принадлежащее окно, когда уничтожается его владелец.
  • Принадлежащее окно скрыто, когда его владелец свернут.

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

Попробуйте создать приложение с 3 формами и показать их все. .dpr будет выглядеть так:

program OwnedWindows;

uses
  Forms,
  Main in 'Main.pas' {MainForm},
  Popup1 in 'Popup1.pas' {PopupForm1},
  Popup2 in 'Popup2.pas' {PopupForm2};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TMainForm, Main);
  Application.CreateForm(TPopupForm1, PopupForm1);
  Application.CreateForm(TPopupForm2, PopupForm2);
  PopupForm1.Show;
  PopupForm2.Show;
  Application.Run;
end.

Вы увидите, что основная форма всегда находится под двумя другими формами, но эти другие собственные формы могут быть выше или ниже друг друга. Когда вы сворачиваете основную форму, они все исчезают.

Вы могли бы, если хотите, сделать все свои формы не принадлежащими окнами верхнего уровня:

procedure TPopupForm1.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.WndParent := 0;
end;

И то же самое для TPopupForm2 в моем примере. Это приведет к тому, что все 3 окна будут иметь кнопки на панели задач.

Еще один подход состоит в том, чтобы вернуться к тому, что было до Vista, и сделать скрытое окно приложения окном владельца верхнего уровня. Для этого убедитесь, что Application.MainFormOnTaskbar имеет значение False. Пропустите весь код CreateParams, и теперь у вас будет одно окно на панели задач, и любое из ваших окон может быть выше любого другого, потому что окном владельца верхнего уровня является скрытое окно Application.Handle. Конечно, недостатком является то, что вы теряете свой Aero Peek.

Итак, я предполагаю, что вам нужно сделать так, чтобы основная форма отображалась на панели задач, как обычно, но убедитесь, что другие формы не принадлежат (в смысле Windows) основной форме. Но ими нужно владеть, чтобы они не отображались на панели задач. Таким образом, вы можете сделать скрытое окно приложения владельцем, используя метод CreateParams, например:

procedure TOverlappedPopupForm.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.WndParent := Application.Handle;
end;

Хотя вы утверждаете обратное в комментариях, когда я это делаю, я обнаруживаю, что всплывающая форма действительно скрыта, когда я сворачиваю основную форму. И снова показывается при восстановлении основной формы. Таким образом, я думаю, что это полностью решает вашу проблему.

person David Heffernan    schedule 22.03.2011
comment
Спасибо за это, +1! Есть ли способ иметь только 1 значок на панели задач (без скрытого окна, потому что, по моему опыту, Windows 7 Thumb Preview пуст)? - person Jeff; 22.03.2011
comment
@Jeff Основной формой обычно является панель задач. Это тот, для которого вам нужен предварительный просмотр Aero Peek. Другие всплывающие окна будут принадлежать окнам и поэтому всегда будут находиться поверх главного окна. Разве это не то, чего ты хочешь? - person David Heffernan; 22.03.2011
comment
@David - мы приближаемся! :) Когда я сворачиваю MainForm ImgBurn, лог тоже сворачивается! Тогда это будет полное решение :) - person Jeff; 22.03.2011
comment
@ Джефф, тебе придется сделать это самому. Определите, что основная форма сворачивается, и вызовите Minimize для остальных. Вы хотели бы сделать обратное, когда окно будет восстановлено. Это то, что вы получаете бесплатно, когда создаете окна, принадлежащие всплывающим окнам. - person David Heffernan; 22.03.2011
comment
@Jeff, в TApplication есть код для решения такого рода проблем, когда скрытое окно приложения является окном панели задач. На самом деле вы можете захотеть скрыть всплывающие окна, а не свернуть их, поскольку, если вы сделаете последнее, их свернутые окна появятся над панелью задач. - person David Heffernan; 22.03.2011
comment
@Jeff Джефф, это может быть немного сложно, чтобы преуспеть и охватить все случаи. Если у вас возникли проблемы, опубликуйте еще один вопрос! - person David Heffernan; 22.03.2011
comment
@David - я попробую это и отчитаюсь :) - сначала я должен решить более важную проблему, я уже отправил вопрос об этом ;) Ребята, вам нравится, когда люди задают вопросы, а? Это здорово, потому что у меня их много! :П - person Jeff; 22.03.2011
comment
@Jeff Я думаю, что мое самое последнее обновление показывает, что в другом вопросе нет необходимости. Я могу получить именно то, что вы описываете, просто сделав всплывающее окно принадлежащим (с точки зрения Windows) скрытому окну приложения. - person David Heffernan; 22.03.2011
comment
@David - Это забавно - когда я делаю Aero Peek, когда моя основная форма находится в фокусе, я вижу всплывающую форму. Когда у меня в фокусе всплывающая форма, я вижу основную форму? - person Jeff; 23.03.2011
comment
@Джефф, как и ожидалось. Aero Peek показывает окно, которое представлено на панели задач, и это главная форма, независимо от того, какая из них находится в фокусе. - person David Heffernan; 23.03.2011
comment
@David - как и ожидалось. Aero Peek показывает окно, представленное на панели задач, и это главная форма, независимо от того, какая из них находится в фокусе. Ну, я сказал так: пока моя основная форма находится в фокусе, я вижу Всплывающее окно form, так что, видимо, нет. В противном случае, это только я сделал что-то не так, что весьма вероятно :P - person Jeff; 23.03.2011
comment
@Jeff странно, не то, что я ожидал! - person David Heffernan; 23.03.2011
comment
@David - Ну, я могу заверить вас, что это не так. - person Jeff; 23.03.2011
comment
@Джефф, я в тебе не сомневаюсь. Мы должны делать что-то другое. - person David Heffernan; 23.03.2011
comment
@David - у меня было MainFormOnTaskBar = False, но когда я установил для него значение True, CreateParams не кажутся эффективными - person Jeff; 24.03.2011
comment
@Jeff У вас есть CreateParams в правильной форме? Это должно перейти на всплывающую форму. - person David Heffernan; 24.03.2011
comment
@David, да, во всплывающей форме. - person Jeff; 24.03.2011
comment
@David — еще один пользователь Dropbox, милый! Ваш пример работает отлично! Может быть, это потому, что я не делаю Form.Show в исходном коде проекта? - person Jeff; 24.03.2011
comment
Пользователь @Jeff Dropbox уже 20 минут. Не знаю, почему ваша версия не работает. Но у вас есть неопровержимое доказательство того, что принцип верен. - person David Heffernan; 24.03.2011
comment
@David - Dropbox спасал меня много раз, например, когда я хотел добавить функцию, которую я удалил месяц назад, я мог вернуть свой файл pas! В любом случае, да, я вижу, что это работает :) Спасибо! - person Jeff; 24.03.2011
comment
@David - Да, я такой... Эй, я знаю этого чувака! :П - person Jeff; 24.03.2011

У меня еще не открыт Delphi, но я бы установил

mainform.formstyle := fsStayOnTop 

и покажите дочернюю форму с помощью

childform.show;

Работа?

или попробуйте использовать SetWindowPos() и установите свойство hWndInsertAfter на что-то вроде HWND_TOPMOST в основной форме

person Christopher Chase    schedule 22.03.2011
comment
Это, безусловно, возможно, не делая окно самым верхним. - person David Heffernan; 22.03.2011
comment
Возможно, установка дочерней формы на HWND_BOTTOM - person Christopher Chase; 22.03.2011
comment
-1 Установка стиля как fsStayOnTop будет иметь другие эффекты в приложении и за его пределами, которые вы не упомянули в своем ответе. - person jachguate; 22.03.2011
comment
@jachguate был ли это виртуальный -1? - person David Heffernan; 22.03.2011
comment
@ Дэвид, хахахаха ... не сейчас. :) - person jachguate; 22.03.2011