Delphi Multiple MDI Children вызывает изменение состояния окна

Я ищу, чтобы предотвратить изменение дочернего MDI WindowState при создании второго дочернего MDI ...

У меня есть приложение, которое я разрабатываю, написанное на Delphi. Благодаря небольшой магии Delphi / Windows у приложения есть несколько родительских MDI и несколько дочерних MDI.

Я могу создать форму (дочерний элемент A1) и развернуть ее в родительском элементе MDI (родительский элемент A). Я могу создать вторую форму (Child B1) и развернуть ее во втором родителе MDI (Parent B). Обе формы будут преобразованы в отдельные родительские элементы MDI. Все идет нормально. У меня это работает.

Однако, когда я создаю второго дочернего элемента MDI (Child A2) в первом родительском элементе MDI (Parent A), WindowState (wsMaximized) первого дочернего элемента (Child A1) изменяется при создании второго дочернего элемента (Child A2). Я хочу, чтобы первый дочерний элемент (Child A1) оставался развернутым, а второй дочерний элемент (Child A2) был создан и помещен поверх первого ребенка ...

Как я могу предотвратить изменение состояния первого дочернего элемента MDI, но также создать второго дочернего элемента MDI? Какие-нибудь намеки?

Хорошо - Теперь я немного пообедал, может, я смогу объяснить это лучше ... вот вторая попытка ...

Описанное поведение можно воспроизвести в простом приложении MDI (магия, которую я использовал для создания нескольких родителей MDI, не влияет на мою проблему)

Создайте новое приложение форм, изменив стиль формы на fsMdiForm Создайте вторую форму, измените ее стиль на fsMDIChild Создайте третью форму, измените ее стиль на fsMDIChild

Запустите приложение. Создайте экземпляр второй формы, затем разверните (работает, как ожидалось - максимизирует в MDI Parent). Создайте экземпляр третьей формы, третья форма открывается с состоянием окна wsNormal. Но когда создается третья форма, состояние окна второй формы меняется - оно перестает разворачиваться и становится wsNormal, как если бы вы нажали восстановить!

Я хочу избежать восстановления второй формы, когда я открываю третью форму ... (Все формы имеют начальное WindowState wsNormal ...

Любые подсказки приветствуются!


person 0909EM    schedule 20.12.2011    source источник
comment
Windows (и Delphi) не поддерживают несколько родительских MDI в одном приложении. Это противоречит конструкции MDI в целом. Если вы каким-то образом получаете более одного родителя MDI, это больше не приложение MDI, и поведение IMO совершенно непредсказуемо.   -  person Ken White    schedule 20.12.2011
comment
С помощью небольшой магии Delphi / Windows Нужно ли нам знать, что это за магия, чтобы помочь?   -  person David Heffernan    schedule 20.12.2011
comment
Извините, требуется небольшой прыжок веры. Магия Delphi / Windows в основном позволяет мне создавать несколько родителей MDI и отбрасывать дочерние элементы MDI в родителей - это работает и очень предсказуемо / стабильно - я бы вставил код, но я бы скопировал весь свой репозиторий в ... (тоже много дженериков :) Я изменил свой первоначальный вопрос ....   -  person 0909EM    schedule 20.12.2011
comment
Я не могу воспроизвести поведение, которое вы описываете. Правильно ли я, что вы максимизируете дочерний элемент MDI, а не родительский элемент MDI? Что вы используете в качестве триггера для создания новых форм?   -  person David Heffernan    schedule 20.12.2011
comment
Нормальным поведением дочерних элементов Windows / MDI является то, что все они имеют одинаковое состояние в развернутом или нормальном состоянии. Сделайте один MDI-дочерний элемент максимальным, а все остальные также развернуты, и наоборот. Это стандарт Windows.   -  person Andreas    schedule 20.12.2011
comment
@Andreas 0909EM говорит не об этом. Очевидно, создание второй дочерней формы MDI изменяет состояние окна первого дочернего элемента. Второй дочерний элемент MDI должен быть создан в максимальном размере. Это то, что я увидел, когда попытался воспроизвести проблему.   -  person David Heffernan    schedule 20.12.2011
comment
Вы уверены в том, что ваша магия не задействована? Я могу представить, что, возможно, волшебство потребовало, чтобы вы изменили источник VCL, чтобы дочерние элементы MDI не были так связаны друг с другом, что заставляет новую форму не приобретать состояние существующей формы (поскольку у нее может быть другой родительский элемент), но поскольку это потребовало изменения VCL, вы неосознанно создаете волшебные программы, даже когда думаете, что делаете простую стандартную тестовую программу.   -  person Rob Kennedy    schedule 20.12.2011
comment
Спасибо за всю помощь, которую я заархивировал здесь ... Надеюсь, это поможет объяснить это ... В основном в моем заархивированном проекте Form3 должен быть поверх Form2, а Form2 должен быть развернут (где Form1 является родительским) ... Роб простой пример не содержит никакой магии и не делает то, что я надеюсь / ожидаю. Полагаю, мне может понадобиться сильная магия, чтобы добиться желаемого поведения ... dl.dropbox .com / u / 17951654 / MultiMDI.zip   -  person 0909EM    schedule 20.12.2011


Ответы (3)


В своем приложении я также использую несколько родителей MDI. Ниже приведен мой волшебный код, в котором разные дочерние элементы имеют разные состояния в каждом родительском элементе.

Этот код взят из: ID: 23574, несколько родительских форм MDI в одном приложении

//Add multiple MDIForm support
TFormMDIEnhance = class(TForm)
  private
    _mdiClientHandle: HWND;
    function GetMDIClientHandle: HWND;
  protected
    procedure CreateWindowHandle(const Params: TCreateParams); override;
    procedure DestroyWindowHandle; override;
  end;

procedure TFormMDIEnhance.CreateWindowHandle(const Params: TCreateParams);
var
  mdiStruct: MDICREATESTRUCT;
begin
  _mdiClientHandle := GetMDIClientHandle;

  if (FormStyle = fsMDIChild) then
  begin
    mdiStruct.szClass := Params.WinClassName;
    mdiStruct.szTitle := Params.Caption;
    mdiStruct.hOwner := HInstance;
    mdiStruct.x := Params.X;
    mdiStruct.y := Params.Y;
    mdiStruct.cx := Params.Width;
    mdiStruct.cy := Params.Height;
    mdiStruct.style := Params.Style;
    mdiStruct.lParam := LPARAM(Params.Param);

    WindowHandle := SendStructMessage(_mdiClientHandle, WM_MDICREATE, 0, mdiStruct);
    Include(FFormState, fsCreatedMDIChild);
  end
  else
    inherited CreateWindowHandle(Params);
end;

procedure TFormMDIEnhance.DestroyWindowHandle;
begin
  if fsCreatedMDIChild in FFormState then
    SendMessage(_mdiClientHandle, WM_MDIDESTROY, Handle, 0)
  else
    inherited DestroyWindowHandle;

  _mdiClientHandle := 0;
end;

function TFormMDIEnhance.GetMDIClientHandle: HWND;
var
  fm: TForm;
begin
  result := 0;

  if Owner is TForm then
  begin
    fm := Owner as TForm;
    if Assigned(fm) then
      Result := fm.ClientHandle;
  end;

  if (Result = 0) and Assigned(Application.MainForm) then
    Result := Application.MainForm.ClientHandle;

  if Result = 0 then
    raise EInvalidOperation.Create(SNoMDIForm);

end;

Унаследовав свои формы от этой базовой формы, вы можете создать несколько родительских MDI. Может быть, это поможет.

person markus_ja    schedule 20.12.2011
comment
Да, у меня несколько родителей MDI. Я хочу, чтобы поведение WindowState дочерних элементов MDI отличалось от родительского. Итак, первый MDI Child - это wsMax'd, а второй - wsNormal ... Я опубликовал код, см. Мой комментарий выше ... Любые мысли приветствуются! - person 0909EM; 20.12.2011
comment
Вы не можете сделать это с MDI. Это ограничение Microsoft. Если один дочерний элемент максимизирован, то все остальные дочерние элементы также должны быть максимизированы. именно так работает MDI. - person Remy Lebeau; 20.12.2011

Мне потребовалось время, чтобы понять, о чем вы на самом деле спрашиваете, но я думаю, что все сводится к этому комментарию.

Я хочу, чтобы поведение WindowState дочерних элементов MDI отличалось от родительского. Итак, первый MDI Child - это wsMax'd, а второй - wsNormal.

Это невозможно в MDI. Когда дочерний элемент MDI развернут, это единственное дочернее окно, которое отображается.

person David Heffernan    schedule 20.12.2011

Реми и Дэвид правы в том, что это ограничение MDI.

В конце концов, мое решение, которое действительно работает, заключалось в том, чтобы поддерживать ChildWindowState (который является просто WindowState) в каждой дочерней форме, а затем обрабатывать изменение размера / позиционирования дочерних окон при изменении ChildWindowState ... Это не красивый ответ, но он предоставляет функциональность, которая мне нужна в моем приложении.

Спасибо за ответы на все вопросы :)

person 0909EM    schedule 29.12.2011