0

在我的 Windows 7 桌面上,我将 Windows 任务栏附加在屏幕的左侧(而不是底部的默认设置),并将自定义桌面工具栏(“True Launch Bar”)附加在屏幕的顶部。

在 Delphi XE8 VCL 项目中,我将主窗口位置值 (formMain.TopformMain.Left) 保存在FormClose事件中,然后在程序启动时使用FormCreate事件中的这些值恢复主窗口位置。

这通常运作良好。但是,当程序在 MINIMIZED ( formMain.WindowState= wsMinimized) 时关闭时,窗体位置值是错误的(即被工具栏的宽度/高度减小),因此窗口在程序启动时恢复到错误的位置。

那么我该如何解决这个问题呢?

编辑:我尝试了大卫提到的其他解决方案:

var
  WindowPlacement: TWindowPlacement;
  R: TRect;
....
  WindowPlacement.Length := SizeOf(WindowPlacement);
  Win32Check(GetWindowPlacement(formMain.Handle, @WindowPlacement));
  R := WindowPlacement.rcNormalPosition;
  CodeSite.Send('formMainLeft by WinAPI', R.Left);        // normal: 323 minimized: 323
  CodeSite.Send('VCL formMain.Left',      formMain.Left); // normal: 423 minimized: 323

但是,这会产生相同的问题,因为它没有考虑工具栏占用的空间,因为它只获取 WORK AREA 值。

此外,这不是大卫提到的重复问题,而是类似问题。这个问题源于最小化状态下的错误屏幕值,而另一个问题是关于整体恢复状态和大小。

另请注意:我不想恢复窗口状态(例如最小化)和位置,但只有窗口位置,所以我不能SetWindowPlacement像大卫在另一个问题中提到的那样使用。

EDIT2:我现在已经用这段代码解决了这个问题:

  if formMain.WindowState = wsMinimized then
  begin
    MinimizedOffsetTop  := Screen.WorkAreaTop;
    MinimizedOffsetLeft := Screen.WorkAreaLeft;
  end
  else if formMain.WindowState = wsNormal then
  begin
    MinimizedOffsetTop  := 0;
    MinimizedOffsetLeft := 0;
  end;
  SettingsIni.WriteInteger('Persistence', 'Top',  formMain.Top  + MinimizedOffsetTop);
  SettingsIni.WriteInteger('Persistence', 'Left', formMain.Left + MinimizedOffsetLeft);

(在窗口最大化的情况下,我不保存和恢复窗口位置,而只保存和恢复最大化窗口状态)。

4

1 回答 1

1

当一个窗口被最小化时,它会记住最后的标准化边界,并在您恢复窗口时将自己恢复到那里。您可以通过GetWindowPlacement. 此 API 返回工作区相对坐标。这样做是因为这允许窗口最小化并恢复到相同的工作区相对位置,即使工作区在中间时间发生了变化。

显然,GetWindowPlacement当您要求最小LeftTop窗口时,VCL 会调用。否则它将如何获得它返回的坐标?当然,它会返回让您感到困惑的工作区相对坐标。人们可能会认为这是一个错误,这些属性有时是相对于屏幕的,而有时是相对于工作区的。

您的解决方案很明显。调用获取工作区相对坐标GetWindowPlacement。当您需要重新应用这些坐标时,请调用SetWindowPlacement.

你说你不能使用SetWindowPlacement,因为这会强制窗口最小化。但事实并非如此。将showCmd成员设置为SW_SHOWNORMALSW_RESTORE

多年来,我们一直在使用这些 API 来存储和恢复窗口位置。众所周知,它们运作良好。

于 2015-07-21T14:49:41.190 回答