12

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

我已经尝试单独设置和删除属性以及获取 current 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.

4

4 回答 4

4

MSDN上记录了确定哪些窗口在任务栏上有按钮的规则。Raymond Chen总结了这些规则:

关于哪些窗口进入任务栏有一些基本规则。简而言之:

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

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

剩下的唯一选择是删除WS_EX_APPWINDOW扩展样式并将其替换为WS_EX_TOOLWINDOW. 这确实会使窗口离开任务栏,但会改变窗口的外观

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

于 2011-11-23T15:21:31.627 回答
3

这是我如何做到这一点的。

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 属性的文档,它说“顶级窗口不能拥有所有者”。它应该与此完全相反,只有顶级窗口才能拥有所有者!

于 2012-02-22T23:14:34.613 回答
2
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 位机。

于 2011-11-23T14:32:59.190 回答
0

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

改编自亚历克斯的回答。

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);
}
于 2021-12-19T23:48:54.000 回答