Как мога да преместя формуляр на Delphi пред другия?

Имам приложение, което винаги показва поне два формуляра едновременно.

Обикновено имам списък със задачи в дъщерна форма на главния формуляр със съответните подробности, показани в основния формуляр. Други подробности могат да се управляват с ShowModal.

Текущият проблем е, че потребителите наскоро са поискали основният формуляр да може да се плъзга пред списъка със задачи.

Доколкото мога да видя, тъй като формулярът за списък с длъжности е създаден след основния формуляр и се извиква Показване от основния формуляр, той получава позицията "отпред".

Има ли някакъв начин това да се промени по време на изпълнение, т.е. мога ли да настроя активната форма да бъде отпред?


person Dan Kelly    schedule 01.11.2011    source източник


Отговори (2)


Забележка: В останалата част от този отговор терминологията притежаван приема значението, използвано от документация на 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 върши много работа за вас зад кулисите за притежавания прозорец. Може да се наложи да възпроизведете част от тази работа, ако превключите към непритежаван прозорец.

person David Heffernan    schedule 02.11.2011
comment
Благодаря за това - точно това, което беше необходимо. Поведението изглежда е точно каквото бих очаквал, нека видим какво мисли потребителят, поискал промяната. - person Dan Kelly; 04.11.2011

Докато формулярът за списък със задачи не е дъщерен на друг прозорец (т.е. неговото свойство Parent не е зададено и неговият CreateParams() метод не е заменен, за да зададе полето TCreateParams.WndParent), и се показва, използвайки своя Show() метод вместо своя ShowModal() метод, тогава потребителят трябва да може свободно да превключва между двата прозореца по желание.

person Remy Lebeau    schedule 01.11.2011
comment
Безмоделните прозорци обикновено се притежават от главната форма и затова винаги са над главната форма. Обърнете внимание, че под притежаван имам предвид терминологията на windows, а не VCL терминологията. - person David Heffernan; 02.11.2011
comment
@David: собствеността върху безмоделните прозорци зависи от версията на Delphi. В по-старите версии, преди да бъде въведено свойството PopupMode, те са собственост на прозореца TApplication. В по-новите версии pmNone използва MainForm само ако Application.MainFormOnTaskBar е True, pmAuto използва MainForm само ако няма подходящо ActiveForm и Application.MainFormOnTaskBar е True, а pmExplicit използва MainForm само ако не е присвоено PopupParent. - person Remy Lebeau; 02.11.2011
comment
Ясно е, че в този случай прозорецът със списък със задачи е собственост на главния прозорец. Това става ясно от докладваното поведение на z-ред. - person David Heffernan; 02.11.2011