对于在相邻显示器上显示其边框的最大化样式窗口,我能做些啥?
Posted
技术标签:
【中文标题】对于在相邻显示器上显示其边框的最大化样式窗口,我能做些啥?【英文标题】:What can I do about maximized, styled windows, which show their borders on adjacent monitors?对于在相邻显示器上显示其边框的最大化样式窗口,我能做些什么? 【发布时间】:2012-06-11 19:23:48 【问题描述】:在多显示器系统上,“空白”VCL 应用程序可以很好地最大化,但是启用样式(并且选择了一个作为默认样式)的同一应用程序会错误地最大化。我看到的是窗口的右侧边缘延伸到第二台显示器(我的主要在左侧)。当我开始与其他 Windows 应用程序进行比较时,我注意到在 Windows 7 下(至少),最大化的窗口甚至在左侧、右侧或底部都没有非客户端边框。事实上,标准 VCL(非样式化)应用的行为方式与此相同,没有非客户端边界。
我该如何解决这个问题?我注意到 TFormStyleHook 有一个 WMNCCalcSize 处理程序,我还没有剖析它,但让我想知道 VCL 是否可能错误地处理最大化窗口的这条消息。
【问题讨论】:
还有更多 VCL 样式错误。请对此进行质检。 质检网址:qc.embarcadero.com/wc/qcmain.aspx 您能否在单个显示器中重现此行为?我问是因为在我当前的位置我没有另一台显示器来测试这个问题。 从视觉上看,样式化应用的单显示器行为与非样式化应用相匹配,所以没有问题。 强制性“旧事物”链接:“为什么最大化的窗口有错误的窗口矩形?” (blogs.msdn.com/b/oldnewthing/archive/2012/03/26/10287385.aspx) 在其最后一节中描述了为什么在最近的 Windows 版本中,在其他显示器上没有可见的最大化应用程序边框。自己绘制 NC 区域的代码显然没有得到这种特殊处理。 【参考方案1】:在这方面摆弄了一段时间后,我的看法是,这根本不是 vcl 样式的错误。这确实与comment 对mghie 的问题中提到的article 中的行为有关。
具体的行为是,最大化窗口的大小大于窗口最大化的监视器的工作区域。据说,窗口管理器隐藏了悬垂的边框。显然,定制框架并没有这样做。请注意,MSDN 自己的custom window frame example 似乎也遇到了同样的问题(请参阅社区内容中标题为“窗口最大化时的错误” 的帖子)。 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;
【讨论】:
Raymond 专门说“视觉技巧”,所以我想我们不会调整窗口矩形的大小,而只是剪掉悬垂的边框? @whos - 当然,它会好得多(也会摆脱内部框架)。我认为我们需要 VCL 合作,但也许不需要。【参考方案2】:我发现的唯一方法是处理 WM_SIZE 事件并修改窗口区域以切断额外的边框。
【讨论】:
以上是关于对于在相邻显示器上显示其边框的最大化样式窗口,我能做些啥?的主要内容,如果未能解决你的问题,请参考以下文章
WPF 透明窗体,无边框(比如一些桌面的日历桌面程序),如何让程序钉在桌面上。直接镶嵌在桌面背景上?
如何使用CSS来设置两个相邻TableView的边框样式,使它们看起来像是JavaFX 11中的单个TableView(OpenJFX 11)