Jump to content
Dave Nottage

Implementing "desktops" using MDI, "broken" in D12

Recommended Posts

A client has well established products that are based around the MDI model, and are using the concept of "desktops" by hiding/showing MDI children so that the state of the forms is maintained. The concept of hiding MDI children is actually not officially supported in Delphi, so to work around this, ShowWindow is called thus:

    ShowWindow(FormHandle, SW_SHOW);
// or
    ShowWindow(FormHandle, SW_HIDE);

..where FormHandle is the handle of the MDI child being shown/hidden. This worked well, up until Delphi 12, when the message handling for forms was reimplemented, using TChildFormMessageHandler (in Vcl.Forms). The new (undesired) behaviour is that once a child form has ShowWindow called on it, then that form becomes active, the last form that was hidden becomes visible again. This can be reproduced using the attached project by using the following steps:

 

  1. Run the app
  2. Click File | Show Desktop 1
  3. Click File | Show Desktop 2
  4. Click File | Show Desktop 1 again
  5. Set focus to the visible form - the form that "belongs" to Desktop 2 becomes visible again 

 

As described above, this works OK in Delphi 11.3. At this point, reimplementing the app away from MDI is a non-option. I'm aware that whatever measures are needed will be a "hacky" workaround - it started out that way anyway.

Now for the kicker: this is a package-based application, so I can't even "hack" the Vcl.Forms source. Using a "detours"-like solution might be an option.

Any help with how to resolve this would be greatly appreciated.

MDIIssue.zip

Share this post


Link to post

Could free the forms instead of hiding. Has other issues like losing state but they can be overcome. Adding saving/loading form state is useful between program runs as well so work can be resumed quicker. 

MDIIssue2.zip

 

Share this post


Link to post

Insert in every child forms this line in the OnCLose Event may be resolve the Issue ?

 

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := TCloseAction.caHide;
end;

 

Edited by DelphiUdIT

Share this post


Link to post
5 hours ago, Brian Evans said:

Could free the forms instead of hiding. Has other issues like losing state but they can be overcome. Adding saving/loading form state is useful between program runs as well so work can be resumed quicker. 

MDIIssue2.zip

 

I used to loose Form states (or better don't care about them anymore) every time it is closed or hidden. These because all the states of the Form (like input datas, charts, state of the controls) will be resumed from a structure (typ. record or advanced record) when the Form is "reshow".

Normally I "deep divide" all data values from graphic controls and save them to records, since these values may be (normally ARE) used and modified by other means.

 

Only when I have DBAware controls I normally maintain the state of the Form (never destroy it or resume data when the Show methods are called).

Edited by DelphiUdIT

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×