gpt4 book ai didi

delphi - 在运行时创建自定义标题栏和边框,TMainMenu 起作用

转载 作者:行者123 更新时间:2023-12-03 15:26:51 26 4
gpt4 key购买 nike

我正在开发一个相当大的项目,该项目使用自定义表单,并且想自己绘制这些表单的非客户区域。我无法使用 vcl-styles,因为许多表单需要有一个标题栏和边框,其颜色是在运行时选择的,据我所知,样式的设计是应用程序范围内的。

到目前为止,我所完成的工作是绘制标题栏和边框,在标题上绘制,禁用最小化、最大化和关闭按钮,并将它们替换为我自己的按钮。我通过拦截 WM_NCPaint 和 WM_NCACTIVATE 消息并在处理 WM_NCACTIVATE 时在继承的关键字之后调用我自己的过程来实现此目的,并发送 WM_ACTIVATE 消息而不处理 WM_NCPAINT 消息,如下所示:

SendMessage(Handle, WM_NCACTIVATE, ORD(active), -1);

我这样做的原因是因为我无法让 TMainMenu 一致地绘制自身,在单步执行代码后,似乎正确处理的 WM_NCACTIVATE 消息绘制了主菜单。我尝试的另一种方法是在主菜单上调用 UpdateItems,但这没有给出任何结果。

我通过处理 WM_NCHITTEST 消息来停用右上角的按钮,如下所示:

procedure TBasicForm.WMNCHITTEST(var message : TMessage);
begin
inherited;
case message.Result of
HTMINBUTTONE, HTMAXBUTTON, HTCLOSE: message.Result := HTCAPTION;
end;
end;

我通过处理 WM_NCLBUTTONDOWN 获得了自己的按钮(在处理 WM_NCACTIVATE 时调用的过程中绘制),这不是一个完美的解决方案,但可以轻松改进。 (我相信我不需要详细说明这一点。

不过到目前为止,这听起来相当不错。

  • 以某种方式在表单之间切换焦点时出现大量闪烁。
  • 有时会显示原来的右上角按钮,但它们不再对鼠标使用react。
  • 关闭表单时,标题栏(仅标题栏)将恢复到原来的外观。

直接的问题是,我该如何解决这三个问题?不过,我可能会以完全错误的方式处理这个问题,在这种情况下,问题是,如何实现自定义绘制的标题栏和边框,最好不要过多干扰边框和标题栏的功能,主菜单是否正确绘制?

正如我所说,这是一个相当大的项目,包含许多表单,因此在表单设计器中更改内容是我最不考虑做的事情之一。

要重现我遇到的问题,请创建一个新表单并按照我之前所述处理 WM_NCHITTEST、WM_NCACTIVATE 和 WM_NCPAINT。

...
procedure WMNCHITTEST(var message : TMessage); message WM_NCHITTEST;
procedure WMNCACTIVATE(var message : TMessage); message WM_NCACTIVATE;
procedure WMNCPAINT(var message : TMessage); message WM_NCPAINT;
...
implementation
...
procedure TBasicForm.WMNCHITTEST(var message : TMessage);
begin
inherited;
case message.Result of
HTMINBUTTONE, HTMAXBUTTON, HTCLOSE: message.Result := HTCAPTION;
end;
end;

procedure TBasicForm.WMNCACTIVATE(var message : TMessage);
begin
inherited;
Canvas.Brush.Style := bsSolid;
Canvas.Brush.Color := clRed;

Canvas.Rectangle(0, 0, Width, GetSystemMetric(SM_CYCAPTION) + GetSystemMetric(SM_CYBORDER));
Canvas.Rectangle(0, 0, GetSystemMetric(SM_CXBORDER), Height);
Canvas.Rectangle(Width - GetSystemMetric(SM_CXBORDER), 0, Width, Height);
Canvas.Rectangle(Width - GetSystemMetric(SM_CXBORDER), Heigth - GetSystemMetric(SM_CYBORDER), Width, Height);
end;

procedure TBasicForm.WMNCPAINT(var message : TMessage);
begin
SendMessage(Handle, WM_NCACTIVATE, ORD(active), -1);
end;
...

现在,向项目添加第二个表单,确保创建两个表单并在两个表单之间重复切换焦点(也尝试单击第二个表单,然后单击第一个表单的自定义绘制标题栏),这应该会导致在一些闪烁中,关闭、最小和最大按钮出现。关闭表单(按 alt + f4)应简要显示原始标题栏。

最佳答案

编写一个适当的类来绘制表单的非客户区域需要大量工作,您已经处理了一些涉及的基本窗口消息,但还有更多工作。根据我的经验,这些是我的建议。

A。当以某种方式在表单之间切换焦点时,有相当多的闪烁。

。这个问题可能有很多原因,但主要是在 Canvas 上多次调用绘制方法,您可以使用位图缓冲区(TBitmap)将所有标题栏绘制到 Canvas 上来克服这个问题位图,最后仅在传递位图后调用 Canvas.Draw。

A。有时,原始的右上角按钮会出现,但它们不再对鼠标使用react。

查看下一个问题的答案。

A。关闭表单时,标题栏(仅标题栏)将恢复到原来的外观。

这是因为当表单恢复或调整大小时,您需要使表单的 NC 区域失效,因此您必须添加对一些附加消息的支持,如 WM_WINDOWPOSCHANGING、WM_SIZE、WM_MOVE、WM_NCMOUSEMOVE、 WM_NCLBUTTONDOWN、WM_NCRBUTTONDOWN 等

为了避免所有这些工作,您可以使用 VCL 样式,为此您必须重写 TFormStyleHook 类并实现一组自定义样式 Hook ,并应用到您想要自定义标题的表单中bar 使用 RegisterStyleHook 方法,如下所示

TStyleManager.Engine.RegisterStyleHook(TMyForm1, TMyCustomformStyleHook1);
TStyleManager.Engine.RegisterStyleHook(TMyForm2, TMyCustomformStyleHook2);

关于delphi - 在运行时创建自定义标题栏和边框,TMainMenu 起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23919039/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com