我正在尝试制作从工具栏中弹出的无边框表单.我希望用户能够抓住右下角("调整大小句柄")并能够调整表单大小,但无法以任何其他方式调整表单大小或重新定位.
我听说我可以拦截WM_NCHITTEST发送到表单的消息,并设置其结果HTBOTTOMRIGHT,让操作系统处理重新调整表单的大小,就像它有一个相当大的框架一样.我的想法是检测鼠标指针是否已进入我在角落中定义的框,如果它已经,则返回HTBOTTOMRIGHT结果.

这并不像我预期的那样有效.我能够拦截消息,但似乎只有当用户将鼠标光标放在窗体的1px粗边框上时才会发送消息.这意味着它可以按照我想要的方式工作,如果你将光标精确地放在右下角的边缘上.
这是我的WndProc覆盖:
protected override void WndProc(ref Message m)
{
const UInt32 WM_NCHITTEST = 0x0084;
const UInt32 HTBOTTOMRIGHT = 17;
const int RESIZE_HANDLE_SIZE = 40;
bool handled = false;
if (m.Msg == WM_NCHITTEST)
{
Size formSize = this.Size;
Point screenPoint = new Point(m.LParam.ToInt32());
Point clientPoint = this.PointToClient(screenPoint);
Rectangle hitBox = new Rectangle(formSize.Width - RESIZE_HANDLE_SIZE, formSize.Height - RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE);
if (hitBox.Contains(clientPoint))
{
m.Result = (IntPtr)HTBOTTOMRIGHT;
handled = true;
}
}
if …Run Code Online (Sandbox Code Playgroud) 我已经将我的表单更改为无边框形式,我只是将BorderStyle属性更改为bsNone,但现在我的应用程序丢失了窗口锚点和一些命令,如
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;
Run Code Online (Sandbox Code Playgroud)
结果如下:
上面的图像是我想要的,但我已经提到的Windows命令不起作用
有什么办法可以设置BorderStyle: bsNone并且不丢失这些命令吗?
EDITED
如果我使用WS_THICKFRAME我的表单返回一个小的顶部边框和Windows命令运行良好,但我不想要顶部边框.
编辑2
我非常接近预期的结果,但还有一点问题......
我把它放在我的身上 FormCreate
SetWindowLong(Handle
,GWL_STYLE
,GetWindowLong(Handle, GWL_STYLE)
AND (NOT WS_CAPTION)
);
Run Code Online (Sandbox Code Playgroud)
我创建了这个方法
private
procedure WmNCCalcSize(var Msg: TWMNCCalcSize); message WM_NCCALCSIZE;
Run Code Online (Sandbox Code Playgroud)
然后
procedure TfrmBase.WmNCCalcSize(var Msg: TWMNCCalcSize);
begin
inherited;
if Msg.CalcValidRects then
begin …Run Code Online (Sandbox Code Playgroud)