Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is calling ShowModal with setting PopupParent a good idea and is it necessary in newer Delphi versions?

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:

  1. Is it a good idea to always set PopupParent - what might be resulting problems? Do viable alternatives exist?
  2. Is this still necessary in newer versions of Delphi (I am using D2006 at the moment but plan to update)?

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 [...]

like image 391
Alois Heimer Avatar asked Jan 09 '15 16:01

Alois Heimer


2 Answers

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;
like image 83
Alexandre M Avatar answered Oct 18 '22 17:10

Alexandre M


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 the ShowModal 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

like image 26
ventiseis Avatar answered Oct 18 '22 18:10

ventiseis