Question

My application can load DLLs which basically hold another windowed applications.

It can only open one DLL window at any time.

I have encountered a situation when DLL window shows a Message box and/or my main app shows a message box or a modal form, and by deactivating the application (switching to another one) and then activating it, moves all the windows in random(?) z-order, thus making DLL form with it's message box go behind the main form. Main forms message box goes behind the main form.

This results in a non-responsive application. Can't click anything, can't close, can't minimize. Have to kill through Task manager.

In Delphi, i see there is Screen object and it has a list Forms. I checked it and saw that it holds all the forms my application has currently open (Even the message box, which is the result of ShowMessage(), it has no name, but i can see the ClassName).

So far it was good, i could iterate through forms and use SetWindowPos to tell them the correct z-order, however, i cannot do this for the DLL application. Screen does not have this form in the list.

How do i control z-order of the DLL forms?
The DLLs are built using either Delphi, C++, WPF.

Was it helpful?

Solution

You must follow the OS way of ordering the windows (with the use of a handle). A DLL's application handle is zero by default, so you need to define it when showing modal dialogs.

According to documentation Vcl.Forms.TApplication.Handle:

Note: When writing a DLL that uses VCL forms, assign the window handle of the host EXE's main window to the Handle property of the DLL's global Application variable. This makes the DLL's form part of the host application. Never assign to the Handle property in an EXE.

To maintain the Z-order of the dll modal forms, do as Peter Below suggests:

// In the dll
var
  oldWnd: HWND;
begin
  oldWnd := Application.Handle;
  Application.Handle := HandleOfHostform; // <-- Pass the exe host form handle
  try
    .... create and show the DLL form
  finally
    Application.Handle := oldWnd;
  end;
end;

The modal form should be created without an owner, TMyDllForm.Create(nil).


I'm not 100% sure Delphi-7 correctly resolves the handle in a DLL this way. Another approach would be to override CreateParams for the form object, as suggested here.

procedure TMyDLLForm.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.WndParent := HandleOfHostForm;
end;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top