在摆弄了一些时间之后,我的看法是,这根本不是 vcl 样式的错误。这确实与mghie对问题的评论中提到的文章中的行为有关。
具体行为是,最大化窗口的大小大于窗口最大化的监视器的工作区域。据说,窗口管理器隐藏了悬垂的边框。显然,对于定制的框架,它并没有做到这一点。请注意,MSDN 自己的自定义窗口框架示例似乎遇到了同样的问题(请参阅社区内容中标题为“窗口最大化时的错误”的帖子)。VCL 的应用程序与 MSDN 示例的不同之处在于它不是基于 DWM,但我仍然认为这是同一个问题。
悬垂边界的大小与系统调整边界 (SM_C[X|Y]SIZEFRAME) 的大小相同,但这与下面的解决方法无关,因为它忽略了操作系统建议的大小/位置并使用了工作区。
不幸的是,我认为这种解决方法根本不可用。一方面,没有记录提到的行为,另一方面,解决方法并不完美;仍然有一个奇怪的像素。如果您将窗口准确地捕捉到工作区,窗口管理器会决定将窗口偏移到它认为应该放置窗口(带有隐藏框架)的位置。(VCL 可能会被修改为执行窗口管理器所做的事情,并考虑到悬垂并且不绘制它们或类似的东西,但这将是更多的工作,它仍然是解决未记录的行为..)
反正;
type
TForm1 = class(TForm)
..
protected
// overriding styles is not necessary since TFormStyleHook.WMGetMinMaxInfo
// first calls the default window procedure
procedure WMGetMinMaxInfo(var Message: TWMGetMinMaxInfo);
message WM_GETMINMAXINFO;
..
procedure TForm1.WMGetMinMaxInfo(var Message: TWMGetMinMaxInfo);
var
R: TRect;
begin
// always arrives with MinMaxInfo.ptMaxPosition = (-SM_CXFRAME, -SM_CYFRAME)
// and MinMaxInfo.ptMaxSize = (PrimaryMonitor.Width (?) + 2 * SM_CXFRAME, ... )
inherited;
// should test for OS, styles etc. before running the below
R := Monitor.WorkareaRect;
InflateRect(R, -1, -1); // odd pixel
OffsetRect(R, -Monitor.Left, -Monitor.Top);
Message.MinMaxInfo.ptMaxPosition := R.TopLeft;
Message.MinMaxInfo.ptMaxSize := Point(R.Width, R.Height);
end;