有没有办法在不更改 BorderStyle 的情况下使 Delphi VCL 表单变大?
Is there a way to make a Delphi VCL form sizable without changing the BorderStyle?
我刚刚花了很多时间试图在 GExperts 中使 Delphi 6/7 IDE 的 Tools/Environment 选项对话框变大。一切似乎都工作正常,直到我发现将窗体的 BorderStyle 更改为 bsSizable 会关闭并重新创建窗体的句柄,并且在此过程中会丢失调色板配置的列表框的内容。
(项目 属性 之后是空的。)
这样更改表单的大小(通过设置高度和宽度)工作正常,但允许用户调整大小会遇到上述问题。
有没有办法在不改变 BorderStyle 的情况下使 Delphi 表单变大?
通常,您可以通过实现对 WM_NCHITTEST 的响应并设置指示调整大小之一的结果来赋予 window 调整大小行为 "zones" 在 window 帧中。
例如:
procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
...
procedure TForm2.WMNCHitTest(var Message: TWMNCHitTest);
const
EDGEDETECT = 7; //adjust as required
var
deltaRect: TRect; //not used as a rect, just a convenient structure
begin
inherited;
with Message, deltaRect do
begin
Left := XPos - BoundsRect.Left;
Right := BoundsRect.Right - XPos;
Top := YPos - BoundsRect.Top;
Bottom := BoundsRect.Bottom - YPos;
if (Top<EDGEDETECT)and(Left<EDGEDETECT) then
Result := HTTOPLEFT
else if (Top<EDGEDETECT)and(Right<EDGEDETECT) then
Result := HTTOPRIGHT
else if (Bottom<EDGEDETECT)and(Left<EDGEDETECT) then
Result := HTBOTTOMLEFT
else if (Bottom<EDGEDETECT)and(Right<EDGEDETECT) then
Result := HTBOTTOMRIGHT
else if (Top<EDGEDETECT) then
Result := HTTOP
else if (Left<EDGEDETECT) then
Result := HTLEFT
else if (Bottom<EDGEDETECT) then
Result := HTBOTTOM
else if (Right<EDGEDETECT) then
Result := HTRIGHT
end;
end;
上面的代码对于这些情况来说是相当样板的东西,但为了节省时间,我采用了这个特定的例子 from here。如果应用于现有 window/form.
,您需要调整它以适应 WndProc 挂钩用例
有一个并发症...
如果挂钩表单具有 bsDialog 或 bsSingle 的 BorderStyle(可能还有其他) 那么如果表单 also 有系统菜单(biSysMenu 设置在 BorderIcons ).问题是这样的:更改 BorderIcons 属性 也会强制重新创建 window 这将使您回到第一个 w.r.t 形式 HWND 正在重新创建。
但是,在 Delphi 7 中检查了 工具 > 环境 选项对话框后,不 似乎有一个系统菜单,因此在该对话框的 WndProc 挂钩中添加 WM_NCHITTEST 处理应该会产生预期的效果。
"Wnd" 作为对话框句柄,您可以将对话框转换为重叠 window 并带有尺寸框:
SetWindowLong(Wnd, GWL_STYLE,
GetWindowLong(Wnd, GWL_STYLE) and not WS_POPUP or WS_THICKFRAME);
删除对话框:
SetWindowLong(Wnd, GWL_EXSTYLE,
GetWindowLong(Wnd, GWL_EXSTYLE) and not WS_EX_DLGMODALFRAME);
然后附加适当的系统菜单项以调整要处理的消息的大小:
AppendMenu(GetSystemMenu(Wnd, False), MF_STRING, SC_SIZE, 'Size');
并绘制新框架:
SetWindowPos(Wnd, 0, 0, 0, 0, 0,
SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_FRAMECHANGED);
我刚刚花了很多时间试图在 GExperts 中使 Delphi 6/7 IDE 的 Tools/Environment 选项对话框变大。一切似乎都工作正常,直到我发现将窗体的 BorderStyle 更改为 bsSizable 会关闭并重新创建窗体的句柄,并且在此过程中会丢失调色板配置的列表框的内容。 (项目 属性 之后是空的。)
这样更改表单的大小(通过设置高度和宽度)工作正常,但允许用户调整大小会遇到上述问题。
有没有办法在不改变 BorderStyle 的情况下使 Delphi 表单变大?
通常,您可以通过实现对 WM_NCHITTEST 的响应并设置指示调整大小之一的结果来赋予 window 调整大小行为 "zones" 在 window 帧中。
例如:
procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
...
procedure TForm2.WMNCHitTest(var Message: TWMNCHitTest);
const
EDGEDETECT = 7; //adjust as required
var
deltaRect: TRect; //not used as a rect, just a convenient structure
begin
inherited;
with Message, deltaRect do
begin
Left := XPos - BoundsRect.Left;
Right := BoundsRect.Right - XPos;
Top := YPos - BoundsRect.Top;
Bottom := BoundsRect.Bottom - YPos;
if (Top<EDGEDETECT)and(Left<EDGEDETECT) then
Result := HTTOPLEFT
else if (Top<EDGEDETECT)and(Right<EDGEDETECT) then
Result := HTTOPRIGHT
else if (Bottom<EDGEDETECT)and(Left<EDGEDETECT) then
Result := HTBOTTOMLEFT
else if (Bottom<EDGEDETECT)and(Right<EDGEDETECT) then
Result := HTBOTTOMRIGHT
else if (Top<EDGEDETECT) then
Result := HTTOP
else if (Left<EDGEDETECT) then
Result := HTLEFT
else if (Bottom<EDGEDETECT) then
Result := HTBOTTOM
else if (Right<EDGEDETECT) then
Result := HTRIGHT
end;
end;
上面的代码对于这些情况来说是相当样板的东西,但为了节省时间,我采用了这个特定的例子 from here。如果应用于现有 window/form.
,您需要调整它以适应 WndProc 挂钩用例有一个并发症...
如果挂钩表单具有 bsDialog 或 bsSingle 的 BorderStyle(可能还有其他) 那么如果表单 also 有系统菜单(biSysMenu 设置在 BorderIcons ).问题是这样的:更改 BorderIcons 属性 也会强制重新创建 window 这将使您回到第一个 w.r.t 形式 HWND 正在重新创建。
但是,在 Delphi 7 中检查了 工具 > 环境 选项对话框后,不 似乎有一个系统菜单,因此在该对话框的 WndProc 挂钩中添加 WM_NCHITTEST 处理应该会产生预期的效果。
"Wnd" 作为对话框句柄,您可以将对话框转换为重叠 window 并带有尺寸框:
SetWindowLong(Wnd, GWL_STYLE,
GetWindowLong(Wnd, GWL_STYLE) and not WS_POPUP or WS_THICKFRAME);
删除对话框:
SetWindowLong(Wnd, GWL_EXSTYLE,
GetWindowLong(Wnd, GWL_EXSTYLE) and not WS_EX_DLGMODALFRAME);
然后附加适当的系统菜单项以调整要处理的消息的大小:
AppendMenu(GetSystemMenu(Wnd, False), MF_STRING, SC_SIZE, 'Size');
并绘制新框架:
SetWindowPos(Wnd, 0, 0, 0, 0, 0,
SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_FRAMECHANGED);