Calling ShowModal with PopupParent setting is a good idea and is it necessary in newer Delphi versions?
To prevent new modals from appearing under their modal parent window, I am used to always setting PopupParent
on call ShowModal
(as recommended here , here and here ):
function TMyForm.ShowModal(ParentForm: TCustomForm): Integer;
begin
PopupParent := ParentForm;
Result := inherited ShowModal;
end;
But on debugging (Lost Form placement issue set in FormCreate) I figured out that setting PopupParent
results in a call ReCreateWindow
, thereby destroying and recreating the underlying Windows display object.
My questions:
- Is it always good to install
PopupParent
- what could be the problems that arise? Are there viable alternatives? - Is this still needed in newer versions of Delphi (I'm using D2006 at the moment, but plan to upgrade)?
EDIT:
I think all related questions are about the same problem, which is best described by the third link :
[Form opens] with ShowModal, this form opens another with ShowModal, so we have complex modal forms. Sometimes the problem arises when we call ShowModal on a new form, it hides behind the previous forms, instead of showing at the top. After pressing alt + tab, the form returns to the top [...]
This question is quite old, but still relevant. The best source of information on this is from Allen Bauer himself: http://blog.therealoracleatdelphi.com/2004/02/popupmode-and-popupparent_10.html
(Vaybak: https://web.archive.org/web/20160324062228/http://blogs.embarcadero.com/abauer/2004/02/10/295 )
And there you will find this: "If you explicitly set the PopupMode pmAuto property before ShowModal, for example at design time, then no re-creation is required."
Thus, your code should be:
function TMyForm.ShowModal(ParentForm: TCustomForm): Integer;
begin
PopupMode := pmAuto;
PopupParent := ParentForm;
Result := inherited ShowModal;
end;
After 2 hours of debugging and reading the VCL code, I'll add my findings to this thread. In Delphi 10 Seattle, the behavior looks like this:
-
window forms are processed when the form is created by its constructor, because the
TCustomForm.ReadState(Reader: TReader)
width of the form client is set, which leads to a callCreateWnd
-
so even if you put
pmAuto
upShowModal
, the window needs to be recreated
Finally, the documentation mentions:
The PopupMode property is automatically set to
pmAuto
when the method is calledShowModal
.
So these lines in ShowModal
:
if (PopupMode = pmNone) and (Application.ModalPopupMode <> pmNone) then
begin
RecreateWnd;
//..
To make this work, you also need to modify Application.ModalPopupMode
, but this will recreate the window as well.
So my advice is:
-
set a value for
PopupMode
(pmAuto
) directly in your form (dfm
file) -
setting both
PopupParent
andPopupMode
makes little sense because they are relatedPopupParent
setspmExplicit
andpmAuto
resets the pop-up parent tonil