To prevent newly created modal windows to become hidden under their modal parent window I got used to always set PopupParent
when calling ShowModal
(as adviced here, here and here):
function TMyForm.ShowModal(ParentForm: TCustomForm): Integer;
begin
PopupParent := ParentForm;
Result := inherited ShowModal;
end;
But when debugging (a problem of lost form placement, set in FormCreate) I realized that setting PopupParent
leads to a call to ReCreateWindow
, thus destroying and recreating the underlying Windows screen object.
My questions:
PopupParent
- what might be
resulting problems? Do viable alternatives exist?EDIT:
I think all the linked questions above tackle the same problem, which is best described by the 3rd link:
[A form is opened] with ShowModal, this form opens another with ShowModal, so we have stacked modal forms. There is sometimes a problem that when we call ShowModal in new form, it hides behind previous forms, instead of showing on top. After pressing alt+tab, form comes back to the top [...]
This question is quite old, but still relevant. The best source of information about this is from Allen Bauer himself: http://blog.therealoracleatdelphi.com/2004/02/popupmode-and-popupparent_10.html
(wayback: https://web.archive.org/web/20160324062228/http://blogs.embarcadero.com/abauer/2004/02/10/295 )
And there you find this: "If you explicitly set the PopupMode property to pmAuto prior to ShowModal, like at design-time, then the recreate isn’t necessary."
This way your code should be:
function TMyForm.ShowModal(ParentForm: TCustomForm): Integer;
begin
PopupMode := pmAuto;
PopupParent := ParentForm;
Result := inherited ShowModal;
end;
After having spent 2 hours debugging and reading VCL code, I'll append my findings to this topic. In Delphi 10 Seattle, the behaviour is like this:
form window handles are allocated while creating the form by its constructor, because in TCustomForm.ReadState(Reader: TReader)
the client width of the form is set which leads to the call to CreateWnd
so even if you put pmAuto
prior ShowModal
the window has to be recreated
Finally, the documentation mentions:
The PopupMode property is automatically set to
pmAuto
when theShowModal
method is called.
So there are these lines in ShowModal
:
if (PopupMode = pmNone) and (Application.ModalPopupMode <> pmNone) then
begin
RecreateWnd;
//..
So to make this work, you have to change Application.ModalPopupMode
as well, but this also recreates the window.
So my advice is:
set the value for PopupMode
(pmAuto
) directly in your form (dfm
file)
setting both PopupParent
and PopupMode
makes little sense because they are tied together PopupParent
sets pmExplicit
, and pmAuto
resets the popup parent to nil
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With