How can I create a window the size of the screen without it being treated as a fullscreen window? - The Old New Thinghttps://devblogs.microsoft.com/oldnewthing/20250522-00/?p=111211
问题描述
任务栏允许全屏窗口覆盖它。这样,当你在放映幻灯片或进行演示时,屏幕底部不会显示任务栏。自动检测算法在大多数情况下工作得相当好:如果窗口的客户区覆盖了整个屏幕,那么它就被认为是全屏窗口。
但你可能会发现,任务栏有时会将你的窗口误认为是全屏窗口,尽管你并不希望如此;或者当你希望窗口被视为全屏时,任务栏却未能将其识别为全屏。
一种你不想让屏幕大小的窗口被当作全屏窗口的情况是,如果你的窗口试图对屏幕应用某种效果,比如显示一个 50% 透明度的黑色窗口以实现暗化效果,就像“查找我的鼠标”PowerToy 所使用的那样。而一种你希望强制将屏幕大小的窗口当作全屏窗口的情况是,如果你的窗口有标题栏,因为标题栏是非客户区,而全屏计算只考虑客户区。
你有两种方法可以影响这一决策,这两种方法都在同一页面上有文档说明:一种是使用 ITaskbarList2::MarkFullscreenWindow另一种是使用 NonRudeHWND
窗口属性。
这两种设置在某种程度上是互补的,它们有各自适用的场合。
译注
MarkFullscreenWindow
和NonRudeHWND
这两种设置在功能上是相互补充的,但它们的作用方向是相反的:
MarkFullscreenWindow
:
作用:当你调用
MarkFullscreenWindow
并传递TRUE
时,明确地告诉任务栏“这个窗口是全屏窗口”。任务栏会根据这个声明将窗口视为全屏,并相应地隐藏任务栏。这个设置倾向于让任务栏将窗口识别为全屏窗口。
例子:如果你有一个带有标题栏的全屏窗口,任务栏可能会因为标题栏的存在而不将其视为全屏窗口。通过调用
MarkFullscreenWindow(TRUE)
,你可以强制任务栏将窗口视为全屏。
NonRudeHWND
:
作用:当你设置
NonRudeHWND
属性为1
时,你明确地告诉任务栏“这个窗口不是全屏窗口”。任务栏会根据这个声明将窗口视为非全屏,并相应地显示任务栏。这个设置倾向于让任务栏将窗口识别为非全屏窗口。
例子:如果你有一个覆盖整个屏幕的窗口,但你希望任务栏仍然可见(比如为了显示某些状态信息),通过设置
NonRudeHWND
属性为1
,你可以强制任务栏将窗口视为非全屏。举个例子
场景1:你有一个全屏窗口,但任务栏没有将其识别为全屏窗口(可能是因为窗口的某些非客户区部分导致任务栏误判)。
解决方案:调用
MarkFullscreenWindow(TRUE)
,明确告诉任务栏这个窗口是全屏的。场景2:你有一个覆盖整个屏幕的窗口,但你希望任务栏仍然可见(比如为了显示某些状态信息)。
解决方案:设置
NonRudeHWND
属性为1
,明确告诉任务栏这个窗口不是全屏的。
如果你向 ITaskbarList2::MarkFullscreenWindow
传递 TRUE
,那么你就是在声明你的窗口是一个全屏窗口。¹ 如果你传递 FALSE
,那么你就是在取消这一声明。注意,传递 FALSE
并不意味着“我声明这不是一个全屏窗口”。相反,它的意思是“我没有声明这是一个全屏窗口”。
你可以在显示窗口之前调用 MarkFullscreenWindow
,也可以在窗口已经显示的情况下调用它,这种情况下它会立即生效。然而,一旦你隐藏了窗口,你应用的任何设置都会丢失。如果你想让它在窗口下一次显示时继续生效,你需要再次设置它。如果资源管理器崩溃,标记也会丢失,因此要监听 TaskbarCreated
消息并重新应用你的标记。
当窗口显示时,或者当系统检测到你的窗口可能是一个全屏窗口时(比如当它改变大小以覆盖屏幕时),会咨询 NonRudeHWND
属性。在决策做出后更改该值,直到系统需要做出新的决策之前都不会有任何效果,比如如果你隐藏你的窗口然后再显示它。如果 NonRudeHWND
属性被设置为 1
,那么你就是在声明你的窗口肯定不是一个全屏窗口。移除该属性并不会强制你的窗口被当作全屏窗口;相反,它的意思是“继续你正常的全屏检测逻辑”。
各种情况总结如下:
MarkFullscreenWindow | NonRudeHWND | |
---|---|---|
设置后的效果 | 窗口被视为全屏 | 窗口被视为非全屏 |
最佳调用时机 | 在显示或调整窗口大小之前 | |
调用频率 | 每次显示窗口时 | 一次即可 |
如果在窗口可见时更改 | 生效 | 无事发生 |
如果 TaskbarCreated | 需要再次调用 | 不需要 |
¹ 窗口仍然必须满足一些基本标准,比如,你知道的,窗口需要实际上覆盖了屏幕(窗口的客户区(client area)必须覆盖整个屏幕。换句话说,窗口的大小和位置必须使得它看起来像是一个全屏窗口)。你不能创建一个小小的 1×1 窗口并宣称“我是一个全屏窗口!”
好吧,你非要也可以,反正别人会嘲笑你。🤪