gpt4 book ai didi

delphi - 如何删除 wsNormal 全屏表单标题栏内容偏移?

转载 作者:行者123 更新时间:2023-12-03 15:53:58 26 4
gpt4 key购买 nike

当通过 WindowState:=wsMaximized 最大化表单时,标题栏如下所示:

Maximized form with a "normal" title bar

当将窗体设置为WindowState:=wsNormal并手动将窗体大小设置为全屏状态时,框架的内容相同,但标题栏略有移动。

enter image description here

在800*600屏幕上模拟wsMaxed表单的wsNormal表单矩形为TRect(-8,-8,808,608)。(参见this question why the difference of the size is necessary)

我的问题:我如何修复 wsNormal 窗口的移动标题栏内容,使其看起来像下面的模型一样正确?

enter image description here

带有一个按钮的简单示例表单,可重现两种表单状态。

unit Unit1;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private-Deklarationen }
FState: Integer;
public
{ Public-Deklarationen }
procedure WMGetMinMaxInfo(var Message: TWMGetMinMaxInfo); message WM_GETMINMAXINFO;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
LBRect: TRect;
begin
LBRect := Screen.Monitors[0].BoundsRect;

case FState of
0:
begin
WindowState := wsMaximized;
end;
1:
begin
WindowState := wsNormal;
LBRect := Screen.Monitors[0].WorkareaRect;
LBRect.Inflate(8,8); //offset 8 for a form with bsSizeable
BoundsRect := LBRect;
end;
end;

Inc(FState);
FState := FState mod 2;
end;

procedure TForm1.WMGetMinMaxInfo(var Message: TWMGetMinMaxInfo);
begin
//slightly smaller MaxTrackSize would prevent the wsNormal form the fully cover the screen on the right side
Message.MinMaxInfo.ptMaxTrackSize := Message.MinMaxInfo.ptMaxSize;
end;

end.

编辑1:

为了澄清为什么这可能有用:我们有一个具有相同分辨率屏幕的多显示器设置,并且希望将表单跨越这个非常大的“虚拟屏幕”。桌面无法通过 AMD 的虚拟桌面设置等统一为一个大屏幕。

出现此问题的原因是最大化表单的标题栏矩形的高度比非最大化表单标题栏的高度稍小。

另外,还需要负数位置和放大尺寸,caused by the (backwards compatible) way windows handles the border calculations and positioning.实际的偏移/放大来自所选的边框样式。

最佳答案

经过一些研究,我找到了一种以最小的努力达到所描述场景的目标的方法。这并不能回答问题本身,它只能达到目标。

当创建表单并且最大化表单时(通过用户或将表单 WindowState 设置为 wsMaximized),将发送窗口消息 WM_GETMINMAXINFO

通过发送WM_GETMINMAXINFO,表单将被询问其在最大化情况下所需的位置和大小。

在这里,我们可以覆盖窗口默认定位,例如通过相应地设置值来跨越多个屏幕的最大化 View 。

分析通过 WM_GETMINMAXINFO 消息发送的默认值时,这些值在每个维度上的偏移量为 8。

The offset was necessary on older Windows OS告诉窗口管理器隐藏当前屏幕 View 之外的边框样式,并且还会导致 edge bleeding on multi-monitor setup 。如今,当 WindowState 设置为 wsNormal 时,也会发生边缘出血。

偏移量还会告诉 Windows 窗口管理器在停靠到顶部时减小标题栏大小并正确呈现标题栏内容(这是我们搜索的目标)。

请参阅以下示例:

unit Unit1;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private-Deklarationen }
FState: Integer;
public
{ Public-Deklarationen }
procedure WMGetMinMaxInfo(var Message: TWMGetMinMaxInfo); message WM_GETMINMAXINFO;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
case FState of
0:
begin
WindowState := wsMaximized;
end;
1:
begin
WindowState := wsNormal;
BoundsRect := TRect.Create(100,-8,300,192);
end;
2:
begin
WindowState := wsMaximized;
end;
3:
begin
WindowState := wsNormal;
BoundsRect := TRect.Create(100,0,300,200);
end;
4:
begin
WindowState := wsMaximized;
end;
5:
begin
WindowState := wsNormal;
BoundsRect := TRect.Create(100,100,300,300);
end;
end;

Inc(FState);
FState := FState mod 6;
end;

procedure TForm1.WMGetMinMaxInfo(var Message: TWMGetMinMaxInfo);
begin
case FState of
0, 1:
begin
Message.MinMaxInfo.ptMaxPosition.SetLocation(100,-8);
Message.MinMaxInfo.ptMaxSize.SetLocation(200,200);
Message.MinMaxInfo.ptMaxTrackSize := Message.MinMaxInfo.ptMaxSize;
inherited;
end;
2, 3:
begin
Message.MinMaxInfo.ptMaxPosition.SetLocation(100,0);
Message.MinMaxInfo.ptMaxSize.SetLocation(200,200);
Message.MinMaxInfo.ptMaxTrackSize := Message.MinMaxInfo.ptMaxSize;
inherited;
end;
4, 5:
begin
Message.MinMaxInfo.ptMaxPosition.SetLocation(100,100);
Message.MinMaxInfo.ptMaxSize.SetLocation(200,200);
Message.MinMaxInfo.ptMaxTrackSize := Message.MinMaxInfo.ptMaxSize;
inherited;
end;
end;

end;

end.

仅供引用:var Message:TWMGetMinMaxInfo 似乎在表单生命周期内是持久的。

在状态 0 上,窗体稍微移动到顶部,这告诉窗口管理器将此窗体标题渲染得稍微小一些。这是最大化形式和我搜索的光学结果的默认行为。

状态 1 将显示我遇到的问题,其他状态将向您显示可以在任何地方放置最大化表单,并且标题栏在不切割屏幕边缘时将具有默认大小。

如果您想知道为您的 TForm 选择什么偏移量,您可以使用 AdjustWindowRectEx 询问 Windows以及您选择的样式和主菜单信息。 (参见:VCL.Forms.pas,TCustomForm.GetClientRect 实现)

关于delphi - 如何删除 wsNormal 全屏表单标题栏内容偏移?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38884929/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com