有没有办法在不更改 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 挂钩用例

有一个并发症...

如果挂钩表单具有 bsDialogbsSingleBorderStyle(可能还有其他) 那么如果表单 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);