在Windows 10中从任务栏中移除窗口

5
我希望能在Windows 10的多个桌面中从任务栏中移除窗口。 对于Windows 8.1,我使用了ITaskbarList :: DeleteTab方法,并且效果非常好。
对于Windows 10,这种方法也会将窗口从任务栏中隐藏,但是之后我会在所有桌面上看到此窗口。我只想在一个桌面上看到此窗口。
有人知道如何在Windows 10中隐藏窗口并使其仅出现在一个桌面上的方法吗?
下面你可以看到我所说的“在Windows 10中隐藏任务栏中的窗口”的意思:

enter image description here


1
“在Windows 10中从任务栏隐藏窗口并将此窗口保留在一个桌面上”这句话是什么意思?你能换个说法吗? - specializt
1
那是窗口预览。 - jblixr
这是一个Windows配置选项,除非您想操作Windows设置,否则不需要“删除”任何内容。这听起来像是请求恶意软件创建帮助的味道。 - specializt
如果我没记错的话,其中一种方法是将你的窗口设置为一个隐藏窗口的子窗口。 - Filip Skakun
1
@specializt 确实如此,但令人困惑的是,该文档讨论的是MFC所有权,而不是Win32所有权。遗憾的是,Win32 SDK文档经常混用这些术语,因为相同的函数入口点用于设置父级或所有者。这有效,因为单个窗口可以具有父级所有者(取决于它是子窗口还是顶级窗口),不能同时拥有两者。Raymond Chen在一段时间前发表了博客文章; 强烈推荐阅读以消除困惑:https://blogs.msdn.microsoft.com/oldnewthing/20100315-00/?p=14613 - Cody Gray
显示剩余9条评论
3个回答

4

TL;DR:

  1. 从扩展样式中删除WS_EX_APPWINDOWWS_EX_TOOLWINDOW
  2. 为窗口设置一个所有者。

示例:

从扩展样式中删除标志:

SetWindowLong(myHWND, GWL_EXSTYLE, 
    GetWindowLong(myHWND, GWL_EXSTYLE) & ~WS_EX_APPWINDOW & ~WS_EX_TOOLWINDOW);

设置所有者:

SetWindowLongPtr(myHWND, GWLP_HWNDPARENT, myOwnerHWND);

完整解释:

尽管Cody的解答很好,但它并没有完全回答这个确切的问题。

确切的问题是:“如何显示不出现在任务栏中的窗口,仅出现在一个虚拟桌面上?”

正如Cody所解释的那样,有几种方法可以删除窗口的任务栏按钮。然而,在它们中只有一种方法使其同时只在一个虚拟桌面上显示。

如果在扩展样式中包含标志WS_EX_APPWINDOW,它将强制该窗口显示在任务栏上。这就是为什么在此情况下必须清除它的原因。

如果在扩展样式中包含标志WS_EX_TOOLWINDOW,它将强制该窗口显示在任务栏上,将强制该窗口在所有虚拟桌面上显示。因此,在这里也不是一个选项。

最后,如果你的窗口既没有标志,又没有所有者,则只有在它没有所有者时才会出现在任务栏中。无论如何,它都不会强制出现在所有虚拟桌面上。因此,解决方案是既没有标志,又设置一个所有者。


4
根据我的经验测试,出现在任务栏预览中的窗口与通常出现在任务栏中的窗口完全相同。很久以前,比如在Windows 2000中,一个应用程序的每个合格窗口只会显示为任务栏上的按钮。从Windows XP开始,任务栏分组成为一种选项,因此单个应用程序的所有合格窗口可以被分组在一起,并显示为任务栏上的单个按钮。然后,在Windows Vista中,当您将鼠标悬停在相应的任务栏按钮上时,可以显示这些打开窗口的预览。Windows 8和Windows 10都没有改变这个基本规则;它们只改变了预览的外观。
因此,我们可以参考MSDN文档中关于哪些窗口出现在任务栏上的规则。
每当应用程序创建一个不属于任何人的窗口时,Shell 会在任务栏上创建一个按钮。要确保窗口按钮放置在任务栏上,请使用 WS_EX_APPWINDOW 扩展样式创建一个不属于任何人的窗口。要防止窗口按钮被放置在任务栏上,请使用 WS_EX_TOOLWINDOW 扩展样式创建不属于任何人的窗口。或者,您可以创建一个隐藏窗口,并将此隐藏窗口设置为可见窗口的所有者。
Raymond Chen 在 这里 更精确地总结了这些规则。引用他的话:
有一些关于任务栏中窗口的基本规则。简而言之:
  • 如果设置了WS_EX_APPWINDOW扩展样式,那么它将会显示(当它可见时)。
  • 如果该窗口是顶级无主窗口,则它将显示(当它可见时)。
  • 否则,它不会显示。
(尽管ITaskbarList界面使这变得有些混乱。)
你之前搞混了,调用ITaskbarList::DeleteTab是不必要的。为了确保窗口不出现在任务栏中,只需应用与决定窗口何时出现在任务栏中相反的规则即可。
如果您有一个顶级无主窗口,它将显示在任务栏中,除非您删除WS_EX_APPWINDOW扩展窗口样式。如果您有一个拥有的窗口,则它将不会显示在任务栏中,除非设置WS_EX_APPWINDOW扩展窗口样式以强制其显示在任务栏中。
如果您设置了WS_EX_APPWINDOW扩展窗口样式,那么应该将其删除。这会强制在任务栏中显示窗口。
否则,您应该为窗口设置一个所有者。例如,让第二个窗口由第一个窗口拥有。

谢谢您对窗口的父/所有者的回答和评论,它们真的很有用。我找到了我的错误所在。我在这里留下一个关于Qt特定内容的备注,因为它可能对某些事情有用。如果您想创建具有所有者(而不是父级)的QWidget,则需要在QWidget的构造函数中传递父级并设置窗口标志(例如Qt :: Window,Qt :: Tool)。如果在构造函数之后调用setParent和setWidnwoFlags,则会将父级(非所有者)设置为窗口。 - Unick

0
WS_EX_NOACTIVATE添加到窗口的ex样式中。 https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles

使用此样式创建的顶级窗口在用户单击它时不会成为前景窗口。当用户最小化或关闭前景窗口时,系统不会将此窗口带到前景。窗口不应通过编程访问或通过可访问技术(如Narrator)进行键盘导航来激活。要激活窗口,请使用SetActiveWindow或SetForegroundWindow函数。默认情况下,该窗口不会出现在任务栏上。要强制窗口出现在任务栏上,请使用WS_EX_APPWINDOW样式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接