Delphi 如何删除wsNormal全屏表单标题栏内容偏移?
通过WindowsState:=wsMaximized最大化窗体时,标题栏如下所示: 将窗体设置为WindowsState:=wsNormal并手动将窗体大小设置为全屏状态时,框架的内容相同,但标题栏稍微移动 800*600屏幕上模拟Delphi 如何删除wsNormal全屏表单标题栏内容偏移?,delphi,windows-10,vcl,titlebar,Delphi,Windows 10,Vcl,Titlebar,通过WindowsState:=wsMaximized最大化窗体时,标题栏如下所示: 将窗体设置为WindowsState:=wsNormal并手动将窗体大小设置为全屏状态时,框架的内容相同,但标题栏稍微移动 800*600屏幕上模拟wsMaxed表单的wsNormal表单为TRect(-8,-8808608)。 (见附件) 我的问题: 如何修复wsNormal窗口中移动的标题栏内容,使其看起来像下面的模型一样正确 带有一个按钮的简单示例表单,可复制两种表单状态 unit Unit1;
wsMaxed
表单的wsNormal
表单为TRect(-8,-8808608)。
(见附件)
我的问题:
如何修复wsNormal窗口中移动的标题栏内容,使其看起来像下面的模型一样正确
带有一个按钮的简单示例表单,可复制两种表单状态
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:
要澄清这可能有用的原因,请执行以下操作:
我们有一个具有相同分辨率屏幕的多显示器,希望在这个非常大的“虚拟屏幕”上跨越窗体。桌面无法通过AMDs虚拟Destkop设置统一到一个大屏幕
出现此问题的原因是,最大化表单的标题栏rect的高度略小于非最大化表单标题栏的高度
此外,还需要负位置和放大尺寸,实际的偏移/放大来自所选的边框样式。经过一些研究,我找到了一种方法,以最小的努力达到所述场景的目标。这本身并不能回答问题,它只会达到目标 创建表单时以及表单最大化时(由用户或将表单WindowsState设置为
wsMaximized
),窗口消息WM_GETMINMAXINFO
会被发送
通过发送WM_GETMINMAXINFO
,表单将被询问在最大化情况下所需的位置和大小
在这里,我们可以覆盖windows默认定位,例如,通过相应地设置值,在多个屏幕上跨越最大化视图
当分析通过WM_GETMINMAXINFO
消息发送的默认值时,每个维度的值的偏移量为8
告诉窗口管理器将边框样式隐藏在当前屏幕视图之外,也会导致。
现在,当WindowsState设置为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消息:TWMGetMinMaxInfo
似乎在表单生命周期内保持不变
在状态0时,表单稍微移到顶部,这会告诉窗口管理器将此表单标题稍微变小。这是最大化表单的默认行为和我搜索的光学结果
状态1将显示我遇到的问题,而其他状态将显示将最大化表单放置在任何位置都是可能的,并且当标题栏不切割屏幕边缘时,标题栏将具有默认大小
如果您想知道要为TForm选择什么偏移量,您可以通过使用所选样式和主菜单信息询问windows。(请参阅:VCL.Forms.pas,
TCustomForm.GetClientRect
implementation)API窗口的标准标题是固定的,您不能做任何事情来改变其位置或大小。您将表单定位在负偏移量处,并希望标题不会随之移动。我猜不出您希望使用哪种解决方案,但标题将始终固定在窗口上。我的解决方案是使用最大化的window而不是实体模型。如果您发现自己处于无法使用最大化窗口的情况下,您可能需要询问该问题。也许有一种方法可以指定标题rect,因此它将等于wsMaximized状态下的rect。不,标题将卡在现在的位置。也许您也希望模拟标题。这是没有意义。当你使用wsMaximized
时,它可以正常工作,那么为什么你不直接使用wsMaximized
?为什么你要使用wsNormal
然后将表单过大以超过屏幕大小?如果你想要最大化窗口的行为,请最大化窗口,让操作系统完成它的工作。@Ken White,因为我们有一些lti监视器设置没有覆盖所有屏幕的虚拟桌面。使用wsMaximized可将窗体最大化为一个屏幕。使用wsNormal可覆盖所有屏幕。>“每个维度的值偏移量为8。“-这是不正确的。实际偏移量分别为水平和垂直方向的非客户指标SM_CXFRAME
和SM_CYFRAME
。您已经回答了应该问的问题。这个答案更适合“如何自定义窗口的最大化位置”之类的问题。它可能是重复的,但我不确定。偏移量取决于所选的边框样式。试试看。对于bsSingle,偏移量是3。是的,anwser是一个不同的问题。但我更愿意为这个问题找到一个解决方案,如果有的话。可能是通过Dsm建议的自定义样式。当然,您的帖子是关于带有大小边框的窗口,因此偏移量是SM|C[X|Y]YFRAME。单边框窗口的实际偏移量为SM|C[X | Y]FIXEDFRAME,而不是3。