从任务栏中隐藏应用程序

Posted

技术标签:

【中文标题】从任务栏中隐藏应用程序【英文标题】:Hiding an application from the taskbar 【发布时间】:2012-01-04 19:51:47 【问题描述】:

我一直在努力从我的应用程序的任务栏中隐藏另一个应用程序。 我一直在使用SetWindowLong 函数来设置/删除extended style 上的WS_EX_APPWINDOW

我已尝试单独设置和删除该属性以及获取当前的WindowLong,并将其删除/添加到该属性,如下所示:

SetWindowLong(pMainWindow, GWL_EXSTYLE, GetWindowLong(pMainWindow) & WS_EX_APPWINDOW);

并尝试像这样删除它:

SetWindowLong(pMainWindow, GWL_EXSTYLE, GetWindowLong(pMainWindow) & ~WS_EX_APPWINDOW);

还尝试了这两种方法,但没有先让窗口变长。这是我的完整代码:

public partial class MainWindow : Window

    public MainWindow()
    
        InitializeComponent();
    

    [DllImport("User32.dll")]
    public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
    [DllImport("User32.dll")]
    public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    [DllImport("user32.dll")]
    static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

    private const int SW_HIDE = 0x00;
    private const int SW_SHOW = 0x05;

    private const int WS_EX_APPWINDOW = 0x40000;
    private const int GWL_EXSTYLE = -0x14;

    private void HideWindowFromTaskbar(IntPtr pMainWindow)
    
        SetWindowLong(pMainWindow, GWL_EXSTYLE, ~WS_EX_APPWINDOW);

        ShowWindow(pMainWindow, SW_HIDE);
        ShowWindow(pMainWindow, SW_SHOW);
    

    private void ButtonHide_Click(object sender, RoutedEventArgs e)
    
        HideWindowFromTaskbar(Process.GetProcessesByName("notepad")[0].MainWindowHandle);
    

我注意到 Spy++ 在查看属性时发生了变化。我有一堆不同的结果,比如添加了WS_EX_APPWINDOW,但也随机有其他属性消失,等等。 在查看消息时,我还看到它确实收到了类似STYLE_CHANGED 的消息。

【问题讨论】:

你用 SW_HIDE 试过 SetWindowPlacement 了吗? 我没有,但这不只是隐藏了整个窗口吗?我只想删除它的任务栏栏/项目。 没试过这个,但它看起来可能适合你:alanbondo.wordpress.com/2008/06/22/… “我一直在努力从任务栏中隐藏另一个应用程序”正如我所说,我想隐藏一个不同的应用程序,否则这会起作用。 【参考方案1】:

确定哪些窗口在任务栏上有按钮的规则记录在MSDN 上。 Raymond Chen 给出了这些规则的以下summary:

有一些关于哪些窗口进入任务栏的基本规则。在 简短:

如果设置了 WS_EX_APPWINDOW 扩展样式,那么它将显示(可见时)。 如果窗口是顶层无主窗口,那么它将显示(可见时)。 否则不显示。

您正在尝试修改另一个应用程序中的窗口这一事实严重阻碍了您。您正在删除 WS_EX_APPWINDOW 扩展样式。这还不够,因为有问题的窗口将是一个***的无主窗口(参见要点 2)。一旦创建了窗口,您就无法更改它的所有者,并且由于该窗口是由另一个进程控制的,因此您几乎被卡住了。

剩下的唯一选择是删除 WS_EX_APPWINDOW 扩展样式并将其替换为 WS_EX_TOOLWINDOW。这确实会使窗口离开任务栏,但它会改变appearance of the window:

该窗口旨在用作浮动工具栏。一个工具窗口 有一个比普通标题栏短的标题栏,并且 窗口标题使用较小的字体绘制。工具窗口不 出现在任务栏或用户访问时出现的对话框中 按 ALT+TAB。如果一个工具窗口有一个系统菜单,它的图标不是 显示在标题栏上。但是,您可以显示系统菜单 通过右键单击或键入 ALT+SPACE。

【讨论】:

P.S.我想知道当您在自己的应用程序上将 ShowInTaskbar 设置为 false 时它是如何工作的。 我认为它重新创建了所有者更改的窗口 啊哈!有趣的!也许我需要通过发送这样的消息来通知窗口类似的事情。 没有机会。另一个应用程序创建窗口并确定所有权。 也许我在这里误解了,但是您可以在创建窗口后更改它的所有者,即使它是另一个进程中的窗口 - 试试吧,它可以工作。这将从任务栏/ alt+tab 中删除窗口。【参考方案2】:

这是我的做法。

1. Create a window (hwndOwner) with WS_POPUP style and WS_EX_TOOLWINDOW
2. Call SetWindowLong(hwnd, GWL_HWNDPARENT, hwndOwner)
3. Call SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) |     ~WS_EX_APPWINDOW)

这将从任务栏和 alt 选项卡中删除目标窗口。这至少适用于自 WS2000 以来的每个操作系统。

现在,David Heffernan 指出 MSDN 文档说您不能这样做。嗯,我不知道它为什么这么说,但它不准确。您可以这样做,INFACT .NET Framework 会这样做,只需使用 .NET Reflector 检查 System.Windows.Forms.Form.Owner 属性的代码 - 它使用 SetWindowLong 随时转移所有权!

对于不正确的 MSDN 文档的更多证据,只需查看 Owner property 的文档,它说“***窗口不能拥有所有者”。它应该与此完全相反,只有***窗口才能拥有所有者!

【讨论】:

@MathiasLykkegaardLorenzen 你能详细说明一下,究竟是什么不正确?【参考方案3】:
private const int SW_HIDE = 0x00;
private const int SW_SHOW = 0x05;
private const int WS_EX_APPWINDOW = 0x40000;
private const int GWL_EXSTYLE = -0x14;
private const int WS_EX_TOOLWINDOW = 0x0080;

  private static void HideAppinTaskBar()
  
  var Handle = FindWindowByCaption(IntPtr.Zero, "Untitled - Notepad");
  ShowWindow(Handle, SW_HIDE);
  SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) |     WS_EX_TOOLWINDOW);
  ShowWindow(Handle, SW_SHOW);
  

这对我有用 - 用记事本测试过。 WinXp 32 位机。

【讨论】:

使其成为工具窗口还有其他含义。理想情况下,您需要拥有该窗口才能使其脱离任务栏。 我同意不理想 - 我从这里提出的一个德尔福问题移植了这个。 谢谢,它至少在我正在寻找的地方附近,但我仍在寻找更好的方法。【参考方案4】:

这适用于 WinUI3.NET 6.0 上的 PInvoke.User32 nuget 包:

改编自 Alex 的回答。

private void HideAppFromTaskBar(MainWindow window)

    //Get the Window's HWND
    var windowNative = window.As<IWindowNative>();
    var windowHandle = windowNative.WindowHandle;

    User32.ShowWindow(windowHandle, User32.WindowShowStyle.SW_HIDE);
    var flags = (User32.SetWindowLongFlags)User32.GetWindowLong(windowHandle, User32.WindowLongIndexFlags.GWL_EXSTYLE);
    User32.SetWindowLong(windowHandle, User32.WindowLongIndexFlags.GWL_EXSTYLE, flags | User32.SetWindowLongFlags.WS_EX_TOOLWINDOW);
    User32.ShowWindow(windowHandle, User32.WindowShowStyle.SW_SHOW);

【讨论】:

以上是关于从任务栏中隐藏应用程序的主要内容,如果未能解决你的问题,请参考以下文章

delphi2007如何让程序不在任务栏中隐藏和显示?

如何在任务栏中显示 QMainWindow

从任务栏中隐藏窗口而不使用 WS_EX_TOOLWINDOW

Qt笔记-窗口程序在任务栏中隐藏及永久置顶

以win形式隐藏在任务栏中的消息框

Electron 应用程序 - 如何在全屏模式下禁用/隐藏任务栏中的窗口