13

I have been struggling to hide another application from the taskbar from my application.
I have been using the SetWindowLong function in order to set/remove WS_EX_APPWINDOW on the extended style.

I have tried both setting and removing the property individually as well as taking the current WindowLong, and removing/adding it to that one, like so:

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

And tried removing it like so:

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

Also tried both those methods without first getting the window long. Here is my entire code:

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);
    }
}

I have noticed changes in Spy++ looking at the properties. I had a bunch of different results, like WS_EX_APPWINDOW being added, but also randomly have other attributes disappearing, etc.
When looking at the messages, I also saw that it DID get messages like STYLE_CHANGED.

4
  • Have you tried SetWindowPlacement with SW_HIDE?
    – Alex
    Commented Nov 23, 2011 at 14:12
  • I have not, but doesn't that just hide the entire window? I only want to remove it's taskbar bar/item. Commented Nov 23, 2011 at 14:23
  • Haven't tried this, but it looks like it may work for you: alanbondo.wordpress.com/2008/06/22/… Commented Nov 23, 2011 at 14:27
  • "I have been struggling to hide another application from the taskbar" As I said, I want to hide a DIFFERENT application, this would've worked otherwise though. Commented Nov 23, 2011 at 14:28

4 Answers 4

5

The rules for determining which windows have buttons on the taskbar are documented on MSDN. Raymond Chen gives the following summary of these rules:

There are some basic rules on which windows go into the taskbar. In short:

  • If the WS_EX_APPWINDOW extended style is set, then it will show (when visible).
  • If the window is a top-level unowned window, then it will show (when visible).
  • Otherwise it doesn't show.

The fact that you are trying to modify a window in another app severely hampers you. You are removing the WS_EX_APPWINDOW extended style. This is not enough because the window in question will be a top-level unowned window (see bullet point 2). You cannot change the owner of a window once it has been created and since the window is controlled by another process you are pretty much stuck.

The only option remaining is to remove the WS_EX_APPWINDOW extended style and replace it with WS_EX_TOOLWINDOW. This will indeed get the window off the taskbar but it will change the appearance of the window:

The window is intended to be used as a floating toolbar. A tool window has a title bar that is shorter than a normal title bar, and the window title is drawn using a smaller font. A tool window does not appear in the taskbar or in the dialog that appears when the user presses ALT+TAB. If a tool window has a system menu, its icon is not displayed on the title bar. However, you can display the system menu by right-clicking or by typing ALT+SPACE.

6
  • P.S. I wonder how that works when you set ShowInTaskbar to false on your own application. Commented Nov 23, 2011 at 21:23
  • I think it recreates the window with owner changed Commented Nov 23, 2011 at 21:27
  • Aha! Interesting! Maybe I need to notify the window of something like that, by sending such a message. Commented Nov 23, 2011 at 21:30
  • No chance of that working. The other app creates the window and determines to ownership. Commented Nov 23, 2011 at 21:32
  • Maybe I am misunderstanding here, but you CAN change the owner of a window after it's created, even if it's a window in another process - try it, it works. And this will remove the window from the taskbar / alt+tab. Commented Feb 22, 2012 at 0:30
3

Here is how I do this.

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)

This will remove the target window from the taskbar and alt tab. This will work on every OS since WS2000 at least.

Now, David Heffernan pointed to the MSDN documentation which says you can't do this. Well, I don't know why it says that but its inaccurate. You can do this and INFACT the .NET Framework does this, just use .NET Reflector to examine the code for System.Windows.Forms.Form.Owner property - it uses SetWindowLong to transfer ownership, as often as you would like!

And for more evidence of incorrect MSDN documentation, look no further than the docs for the Owner property, it says "A top-level window cannot have an owner." it should be the exact opposite of this, ONLY top-level windows can have an owner!

1
  • 1
    @MathiasLykkegaardLorenzen could you elaborate, what exactly is incorrect? Commented Aug 19, 2014 at 13:38
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);
  }

This works for me - tested with notepad. WinXp 32 Bit machine.

3
  • Making it a tool window has other implications. Ideally you need to make the window owned in order to get it off the taskbar. Commented Nov 23, 2011 at 14:36
  • I agree about not being ideal - I ported this from a delphi question asked here.
    – Alex
    Commented Nov 23, 2011 at 14:50
  • Thank you, it's at least somewhere near what I am searching for, but I'm still looking for a better way. Commented Nov 23, 2011 at 15:30
0

This works in WinUI3 with PInvoke.User32 nuget package on .NET 6.0:

Adapted from Alex's answer.

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);
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.