程序关闭时的窗口位置值错误,同时最小化

时间:2015-07-21 10:07:43

标签: delphi desktop-application delphi-xe8 window-position

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

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

这通常很有效。 然而,当程序在MINIMIZED(formMain.WindowState = wsMinimized)时关闭时,表单位置值错误(即工具栏的宽度/高度减少)等等程序启动时窗口将在错误的位置恢复。

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

编辑:我尝试了David提到的other solution

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

但是,这会产生同样的问题,因为它没有考虑工具栏占用的空间,因为它只获得了工作区域值。

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

请注意:我不想恢复窗口状态(例如最小化)和位置,但仅限于窗口位置,因此我不能使用David在其他问题中提到的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);

(如果窗口是最大化的,我不保存和恢复窗口位置,但只保存并恢复最大化窗口状态。)

1 个答案:

答案 0 :(得分:1)

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

当您要求最小化窗口的GetWindowPlacementLeft时,VCL显然会调用Top。它怎么会得到它返回的坐标?当然,它会返回工作区相对坐标,这让您感到困惑。有人可能认为这些属性有时是屏幕相对的,有时是工作区相对的错误。

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

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

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