在我的Windows 7桌面上,我将Windows任务栏连接到屏幕的左侧(而不是默认位于底部),并在屏幕顶部附加一个自定义桌面工具栏(“True Launch Bar”)。
在Delphi XE8 VCL项目中,我将主窗口位置值(formMain.Top
和formMain.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);
(如果窗口是最大化的,我不保存和恢复窗口位置,但只保存并恢复最大化窗口状态。)
答案 0 :(得分:1)
当窗口最小化时,它会记住最后一个标准化边界,并在恢复窗口时将自己恢复。这些边界通过GetWindowPlacement
提供给您。此API返回工作区相对坐标。这样做是因为它允许窗口最小化并恢复到相同工作区域的相对位置,即使工作区域在中间时间内发生了变化。
当您要求最小化窗口的GetWindowPlacement
和Left
时,VCL显然会调用Top
。它怎么会得到它返回的坐标?当然,它会返回工作区相对坐标,这让您感到困惑。有人可能认为这些属性有时是屏幕相对的,有时是工作区相对的错误。
但你的解决方案很明显。通过调用GetWindowPlacement
获取工作区相对坐标。当您需要重新应用这些坐标时,请拨打SetWindowPlacement
。
你说不能使用SetWindowPlacement
,因为这会强制窗口最小化。但事实并非如此。将showCmd
成员设置为SW_SHOWNORMAL
或SW_RESTORE
。
我们多年来一直使用这些API来存储和恢复窗口位置。众所周知,它们运作良好。