我已经将表单更改为无边界表单,只是将BorderStyle
属性更改为bsNone
,但是现在我的应用程序丢失了Windows锚点和一些命令,例如
WIN +↑(将表单客户端对齐)
WIN +↓(将表单最小化)
WIN +→(将表单右对齐)
WIN +←(将表单左对齐)
我尝试设置BorderStyle: bsSizeable
并在FormCreate
内使用以下代码,但这不起作用:
procedure TfrmBase.FormCreate(Sender: TObject);
begin
SetWindowLong(Handle
,GWL_STYLE
,GetWindowLong(Handle, GWL_STYLE)
AND (NOT WS_CAPTION)
AND (NOT WS_THICKFRAME)
);
Refresh;
FormColor := oLauncher.oCor;
end;
结果:
上面的图像是我想要的,但是我已经提到的Windows命令不起作用
有什么方法可以设置BorderStyle: bsNone
并且不会丢失这些命令吗?
已编辑
如果我使用WS_THICKFRAME
,则我的表单将返回一个小的顶部边框,并且Windows命令运行良好,但是我不希望该顶部边框。
已编辑2
我非常接近预期的结果,但是还有一点问题...
我把它放在我的FormCreate
SetWindowLong(Handle
,GWL_STYLE
,GetWindowLong(Handle, GWL_STYLE)
AND (NOT WS_CAPTION)
);
然后我创建方法
private
procedure WmNCCalcSize(var Msg: TWMNCCalcSize); message WM_NCCALCSIZE;
然后
procedure TfrmBase.WmNCCalcSize(var Msg: TWMNCCalcSize);
begin
inherited;
if Msg.CalcValidRects then
begin
InflateRect(Msg.CalcSize_Params.rgrc[0], 0, 6);
Msg.Result := 0;
end;
end;
我有这种方法here
现在边框消失了,但是当我的窗体失去焦点时,顶部/底部边框再次显示。...
如何避免这种情况?
已解决
我将边界留为BorderStyle: bsSizeable
,然后做到了:
private
procedure WmNCCalcSize(var Msg: TWMNCCalcSize); message WM_NCCALCSIZE;
[...]
procedure TfrmBase.WmNCCalcSize(var Msg: TWMNCCalcSize);
var
R: TRect;
begin
if not Msg.CalcValidRects then
R := PRect(Msg.CalcSize_Params)^;
inherited;
if Msg.CalcValidRects then
Msg.CalcSize_Params.rgrc0 := Msg.CalcSize_Params.rgrc1
else
PRect(Msg.CalcSize_Params)^ := R;
Msg.Result := 0;
end;
procedure TfrmBase.FormCreate(Sender: TObject);
begin
BorderStyle := bsNone;
SetWindowLong(Handle
,GWL_STYLE
,WS_CLIPCHILDREN or WS_OVERLAPPEDWINDOW
);
end;
procedure TfrmBase.FormShow(Sender: TObject);
begin
Width := (Width - 1);
end;
GitHUB上的解决方案
我已经创建了一个repository here
答案 0 :(得分:2)
您引用的某些命令是与窗口大小相关的系统命令。那需要厚的框架,没有它,“ WIN +右”和“ WIN +左”将不起作用。此外,您需要最小化框和最大化框才能使WIN +向上/向下命令起作用。
最好从头开始,并包含所需的样式,否则VCL可能会干扰。如果您可能需要重新创建表单,请将样式放在CreateWnd
替代中。
procedure TForm1.FormCreate(Sender: TObject);
begin
BorderStyle := bsNone;
SetWindowLong(Handle, GWL_STYLE, WS_CLIPCHILDREN or WS_OVERLAPPEDWINDOW);
end;
然后是您不需要的框架。在问题的编辑中,您可以膨胀客户端矩形以摆脱该矩形。不要猜测框架的宽度/高度,就像下面这样。
procedure TForm1.WMNCCalcSize(var Message: TWMNCCalcSize);
var
R: TRect;
begin
if not Message.CalcValidRects then
R := PRect(Message.CalcSize_Params)^;
inherited;
if Message.CalcValidRects then
Message.CalcSize_Params.rgrc0 := Message.CalcSize_Params.rgrc1
else
PRect(Message.CalcSize_Params)^ := R;
Message.Result := 0;
end;
这时必须读取消息的probably cause cryptic problems,参数在不同的阶段具有不同的含义,等等。
以上内容留下的窗口完全没有任何非客户区域。客户矩形等于窗口矩形。尽管标题不可见,但是您可以通过按Alt + Space激活系统菜单。问题是,系统坚持绘图激活状态。现在它在客户区画了一个框架!
通过拦截WM_NCACTIVATE
摆脱它,您还需要它根据激活状态绘制标题:
procedure TForm1.WMNCActivate(var Message: TWMNCActivate);
begin
if Message.Active then
// draw active caption
else
// draw incactive caption
// don't call inherited
end;
您可能不得不处理一些小故障,弄乱窗户会造成后果。在我的测试中,例如,最小化表单在alt + tab对话框中没有关联的图标。
下面是我完整的测试单元。
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
protected
procedure WMNCActivate(var Message: TWMNCActivate); message WM_NCACTIVATE;
procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
BorderStyle := bsNone;
SetWindowLong(Handle, GWL_STYLE, WS_CLIPCHILDREN or WS_OVERLAPPEDWINDOW);
end;
procedure TForm1.WMNCActivate(var Message: TWMNCActivate);
begin
if Message.Active then
// draw active caption
else
// draw incactive caption
// don't call inherited
end;
procedure TForm1.WMNCCalcSize(var Message: TWMNCCalcSize);
var
R: TRect;
begin
if not Message.CalcValidRects then
R := PRect(Message.CalcSize_Params)^;
inherited;
if Message.CalcValidRects then
Message.CalcSize_Params.rgrc0 := Message.CalcSize_Params.rgrc1
else
PRect(Message.CalcSize_Params)^ := R;
Message.Result := 0;
end;
end.