Jun 02 2006

Take control of Delphi forms in your multimonitor application

Published by at 2:01 pm under Technology   

The authors of the the VCL helpfully added multi monitor “support” a few versions back. Somewhat less helpfully, this support is very limited – it has no way to say “create form X on monitor 3″, which is a very useful thing to do in some kinds of applications – those intended to run on a multimon system in a specific configuration.

You can readily move forms around (with .Left, .Top, etc.) on to specific monitors after a Form is open, but not while it is opening (in OnShow or OnCreate), because a fine method TCustomForm.SetWindowToMonitor will jump in and undo your work.

Not surprisingly, most of the obvious methods to override to fix this, are not virtual. (An aside – I think the bias toward final methods in Delphi, C#, and some other languages, is a poor idea, and I think the guideline of “design for overriding, or prevent it” is even worse.) With some looking, I found a workaround, shown here somewhat mangled by WordPress:

private

FSetBoundsEnabled: boolean;

public

procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;

…..

procedure TSomeForm.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);

begin if FSetBoundsEnabled then inherited;

end;

FSetBoundsEnabled will be False by default. Sometime after your form is loaded (use a Timer or a windows message to signal this), set FSetBoundsEnabled := True then set your .Left and .Top to put your form whereever it needs to be.

If you found this post useful, please link to it from your web site, mention it online, or mention it to a colleague.

3 responses so far

3 Responses to “Take control of Delphi forms in your multimonitor application”

  1. Simon says:

    I realise this is fairly old but being as it’s still published I thought I’d share my experience.

    The way I handle this in D7 is to set the form to be Position=poDefault and then use this code in FormShow

    Self.Top := Screen.Monitors[ScreenNo].Top + ((Screen.Monitors[ScreenNo].Height div 2) – (Self.Height div 2));
    Self.Left := Screen.Monitors[ScreenNo].Left + ((Screen.Monitors[ScreenNo].Width div 2) – (Self.Width div 2));

    Where “ScreenNo” is an integer that is pre-checked in the dpr to make sure it’s valid or it gets set to 0.

  2. wilmsoft says:

    yes, old as it may be, thanks for leaving it up!! This is what I was looking for! (and cannot find elsewher)

  3. Manoj says:

    Even I was looking for it. Thanks a lot !