【问题标题】:Delphi - open form on the second monitorDelphi - 在第二台显示器上打开表单
【发布时间】:2016-12-20 10:09:32
【问题描述】:

我需要有关此解决方案的帮助。 有几种形式的申请。需要在选定的监视器上打开其中一个表单。例如: 解决方案 1. 如果使用了多个监视器,则 OnCreate 表单检查,并在最后一个上打开。我尝试了这段代码,但没有运气:

  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;

解决方案 2. 将窗体拖动到选定的监视器,并将 OnDestroy 事件的顶部和左侧位置写入 INI 文件。下次表格在同一显示器和同一位置打开。我尝试了这段代码,但也没有运气:

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;

【问题讨论】:

  • 在与应用程序相同的目录中创建INI文件时需要小心。例如,如果应用程序位于 \program 文件中,某些版本的 Windows 会创建一个临时目录来存储 ini 文件,然后在程序退出时将其删除,这意味着它每次看起来都像是一个处女实现。例如,最好使用注册表或存储数据或使用文档目录。我可能有错误的技术细节,但这就是效果。
  • 在“if”语句中的第一段代码中,您的意思是 Screen[1] 而不是 screen[i]。在你使用它时,我没有定义,可能包含任何垃圾。

标签: forms delphi multiple-monitors


【解决方案1】:
frmDashboard.Top:= ...
frmDashboard.Top:= ...

这似乎是一个简单的复制粘贴错误。您两次都设置了Top。大概你的意思是:

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

这段代码犯了同样的错误:

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

此外,当它定义不明确时,它指的是i。编译器会对此发出警告。我希望您启用了编译器警告和提示,并注意它们。


如果 INI 文件包含无效数据,您的 OnCreate 事件处理程序将引发异常。例如,如果用户将位置值编辑为非数字,则StrToInt 将引发异常。您的程序应该对此具有弹性。

OnCreateOnDestroy 事件处理程序都不能正确管理 INI 文件对象的生命周期。如果 INI 文件访问失败,或者对 StrToInt 的调用失败(见上文),那么您将泄漏对象。这是要遵循的模式:

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

【讨论】:

  • 感谢您的评论。我已经更正了代码,但它并没有解决问题。
  • 表单仍会在主屏幕/监视器上打开。
  • @Mindaugas,不,你错过了循环结束后使用i
  • 您的问题编辑使我的回答无效。这不酷。您能否还原更改,以便我的回答有意义
  • 明白。完成。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-03
  • 1970-01-01
  • 2012-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多