Delphi - open form on the second monitor

6.9k views Asked by At

I need help with this solution. There is application with several forms. One of this forms need to be opened on selected monitor. For example: Solution 1. OnCreate form cheks if there are more than one monitor used, and open on the last one. I try this code, but with no luck:

  Application.CreateForm(TfrmDashboard, frmDashboard);
  for I := 0 to Screen.MonitorCount -1 do
  begin
    // Checking Screen Position
    ShowMessageFmt('%d, %d, %d, %d',
              [Screen.Monitors[i].BoundsRect.Left,
              Screen.Monitors[i].BoundsRect.Top,
              Screen.Monitors[i].BoundsRect.Right,
              Screen.Monitors[i].BoundsRect.Bottom]);
  end;

  if Screen.MonitorCount > 1 then
  begin
      frmDashboard.Top:= Screen.Monitors[i].BoundsRect.Top;
      frmDashboard.Top:= Screen.Monitors[i].BoundsRect.Left;
  end;

Solution 2. Form is dragged to the selected monitor and OnDestroy event Top and Left position are written to the INI file. Next time form opens on the same monitor and same position. I try this code, but also with no luck:

procedure TfrmDashboard.FormCreate(Sender: TObject);
var
    ini: TIniFile;
begin
    ini:= TIniFile.Create(extractfilepath(paramstr(0))+'Dashboard.ini');
    Left:= StrToInt(ini.ReadString('Left', 'Form_Left', '0'));
    Top:= StrToInt(ini.ReadString('Top', 'Form_Top', '0'));
    ini.Free;
end;

procedure TfrmDashboard.FormDestroy(Sender: TObject);
var
    ini: TIniFile;
begin
    ini:= TIniFile.Create(extractfilepath(paramstr(0))+'Dashboard.ini');
    ini.WriteString('Left', 'Form_Left', IntToStr(Left));
    ini.WriteString('Top', 'Form_Top', IntToStr(Top));
    ini.Free;
end;
1

There are 1 answers

6
David Heffernan On
frmDashboard.Top:= ...
frmDashboard.Top:= ...

This appears to be a simple copy paste error. You set Top both times. Presumably you mean:

frmDashboard.Top:= ...
frmDashboard.Left:= ...

This code makes the same mistake:

if Screen.MonitorCount > 1 then
begin
  frmDashboard.Top:= Screen.Monitors[i].BoundsRect.Top;
  frmDashboard.Top:= Screen.Monitors[i].BoundsRect.Left;
end;

Furthermore, it refers to i when it is ill-defined. The compiler will warn about this. I hope you have compiler warnings and hints enabled, and do take heed of them.


Your OnCreate event handler will raise an exception if the INI file contains invalid data. For instance, if the user edits the position values to be non-numeric, then StrToInt will raise an exception. Your program should be resilient to that.

Both the OnCreate and OnDestroy event handlers don't manage the lifetime of the INI file object correctly. If the INI file access fails, or the calls to StrToInt fail (see above) then you will leak the object. This is the pattern to be followed:

obj := TMyObject.Create;
try
  // do things with obj
finally
  obj.Free;
end;