Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Resolved Can the taskbar icon of a Unity game be hidden?

Discussion in 'Scripting' started by Weightless, May 12, 2020.

  1. Weightless

    Weightless

    Joined:
    Sep 7, 2017
    Posts:
    15
    I want to hide/remove the game's taskbar icon without hiding the game window itself. Since there is no simple option in Unity to do this, I have tried hiding the icon using WS_EX_TOOLWINDOW, following this example:
    https://stackoverflow.com/questions/8243588/c-sharp-hiding-an-application-from-the-taskbar, but had no luck.
    Here: https://answers.unity.com/questions/1314410/make-application-close-to-the-tray.html, it is suggested that "-batchmode" can hide the taskbar icon, which is true but this command hides the window too.

    Achieving this should be possible since here: https://stackoverflow.com/questions/52031400/place-an-applications-icon-into-system-tray, using WS_EX_TOOLWINDOW someone was able to hide the icon so I am definitely doing something wrong. This is how my code looks like right now:

    Code (CSharp):
    1.      
    2.         [DllImport("User32.dll")]
    3.         public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
    4.         [DllImport("User32.dll")]
    5.         public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
    6.  
    7.         [DllImport("user32.dll")]
    8.         static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
    9.  
    10.         private const int SW_HIDE = 0x00;
    11.         private const int SW_SHOW = 0x05;
    12.         private const int GWL_EXSTYLE = -0x14;
    13.         private const int WS_EX_TOOLWINDOW = 0x0080;
    14.  
    15.         void Start()
    16.         {
    17.             IntPtr pMainWindow = Process.GetProcessesByName("Game")[0].MainWindowHandle;
    18.             ShowWindow(pMainWindow, SW_HIDE);
    19.             SetWindowLong(pMainWindow, GWL_EXSTYLE, GetWindowLong(pMainWindow, GWL_EXSTYLE) | ~WS_EX_TOOLWINDOW);
    20.             ShowWindow(pMainWindow, SW_SHOW);
    21.         }

    Just to be clear, I'm talking about this taskbar icon:
     
  2. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,098
    Did you check the logs?
    you can find the logs here (replace username, CompanyName, ProductName):
    C:\Users\username\AppData\LocalLow\CompanyName\ProductName\Player.log


    It is likely that the process cannot be found and throws an exception. But you are trying to access the currentProcess anyway I guess, so you could simply use
    Process.GetCurrentProcess()
    .

    For the actual interop and logic I am not an expert and cannot tell you if that code would work or not.
     
    Weightless likes this.
  3. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,777
    Line 17 looks problem-prone to me. When I've done this sort of thing in the past I've used:
    Code (csharp):
    1.  
    2.         [DllImport("user32.dll")]
    3.         static extern IntPtr GetActiveWindow();
    4.  
    maybe try that instead to assign your pMainWindow?
     
    Weightless likes this.
  4. Weightless

    Weightless

    Joined:
    Sep 7, 2017
    Posts:
    15
    Thanks a lot, got it working. Part of the problem was indeed that the process/window could not be found, but with @StarManta's suggestion, using GetActiveWindow() the window can be found and then to hide the taskbar you have to make the window a tool window using WS_EX_TOOLWINDOW. It's important that you DON'T use the "~'" character because that is I assume for removing attributes. So anyway thanks a lot for the help and here is the final code to remove the taskbar icon of a Unity application:

    Code (CSharp):
    1.  
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using System.Diagnostics;
    6. using System.Runtime.InteropServices;
    7. using UnityEngine;
    8.  
    9. public class HideTaskbarIcon : MonoBehaviour
    10. {
    11.     [DllImport("user32.dll")]
    12.     static extern IntPtr GetActiveWindow();
    13.     [DllImport("User32.dll")]
    14.     public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
    15.     [DllImport("User32.dll")]
    16.     public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
    17.  
    18.     private const int GWL_EXSTYLE = -0x14;
    19.     private const int WS_EX_TOOLWINDOW = 0x0080;
    20.  
    21.     void Start()
    22.     {
    23.         IntPtr pMainWindow = GetActiveWindow();
    24.         SetWindowLong(pMainWindow, GWL_EXSTYLE, GetWindowLong(pMainWindow, GWL_EXSTYLE) | WS_EX_TOOLWINDOW);  
    25.     }
    26. }
    27.  
     
    steril and Hosnkobf like this.
  5. ksam2

    ksam2

    Joined:
    Apr 28, 2012
    Posts:
    1,080
  6. ruudvangaal

    ruudvangaal

    Joined:
    May 15, 2017
    Posts:
    27
    Be careful that your game is indeed the Active Window. Not always true if some other window is active (like running your game through another process). Also, ~ is a bitwise inversion, ~WS_EX_TOOLWINDOW means 'all bits EXCEPT WS_EX_TOOLWINDOW'.
     
    Bunny83 likes this.
  7. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,113
    Right, you would use it as a mask to get rid of the bit. However for that you would use the bitwise and operator. So while this line does set the bit:

    Code (CSharp):
    1. SetWindowLong(pMainWindow, GWL_EXSTYLE, GetWindowLong(pMainWindow, GWL_EXSTYLE) | WS_EX_TOOLWINDOW);  
    this line would remove it:

    Code (CSharp):
    1. SetWindowLong(pMainWindow, GWL_EXSTYLE, GetWindowLong(pMainWindow, GWL_EXSTYLE) & ~WS_EX_TOOLWINDOW);  
    but still keep all other bits that were set before.