Search Unity

[SOLVED] How to remove the title bar of a game ?

Discussion in 'Scripting' started by Quasar47, Aug 17, 2019.

Thread Status:
Not open for further replies.
  1. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    Hello everyone, my problem is very simple : I have a game with unusual proportions (600*1000) that can be swapped between horizontal and vertical layout. The reason is my game's window displays two cameras on top of each other, with a button to swap the layout. The thing is, my game in vertical mode looks like this :

    1.png


    It's great in itself, but you can see the bottom of the screen is cut but the windows task bar. I can still move the game window up to make everything appear correctly, but as soon as I drop the window it snaps right back to its original height, with the title bar fully visible. So, I want to remove it.

    If possible, I do not want to have to change the resolution of the cameras (450*600), because 1) I already have a setup for that resolution and I don't want to waste time resetting everything, and 2) I want to remove the bar for more immersion. I tried to call command lines fro my build but I can't code in c++ and what I tried didn't work. Do you have any ideas ? Thanks for your answers.

    PS : Just in case it's not clear, all I want is this :

    3.png
     
    unknownsk likes this.
  2. Grizmu

    Grizmu

    Joined:
    Aug 27, 2013
    Posts:
    131
    You can make it by using native functions available in the user32.dll. Here's an example on how to do it, which hides your window titlebar to get the maximum height and makes the window render above the windows taskbar:

    Code (CSharp):
    1. using System.Runtime.InteropServices;
    2. using UnityEngine;
    3.  
    4. public class ToolbarHider : MonoBehaviour{
    5.  
    6. #region DLLstuff
    7.     const int SWP_HIDEWINDOW = 0x80; //hide window flag.
    8.     const int SWP_SHOWWINDOW = 0x40; //show window flag.
    9.     const int SWP_NOMOVE = 0x0002; //don't move the window flag.
    10.     const int SWP_NOSIZE = 0x0001; //don't resize the window flag.
    11.     const uint WS_SIZEBOX = 0x00040000;
    12.     const int GWL_STYLE = -16;
    13.     const int WS_BORDER = 0x00800000; //window with border
    14.     const int WS_DLGFRAME = 0x00400000; //window with double border but no title
    15.     const int WS_CAPTION = WS_BORDER | WS_DLGFRAME; //window with a title bar
    16.     const int WS_SYSMENU = 0x00080000;      //window with no borders etc.
    17.     const int WS_MAXIMIZEBOX = 0x00010000;
    18.     const int WS_MINIMIZEBOX = 0x00020000;  //window with minimizebox
    19.  
    20.     [DllImport("user32.dll")]
    21.     static extern System.IntPtr GetActiveWindow();
    22.  
    23.     [DllImport("user32.dll")]
    24.     static extern int FindWindow(string lpClassName, string lpWindowName);
    25.  
    26.     [DllImport("user32.dll")]
    27.     static extern bool SetWindowPos(
    28.         System.IntPtr hWnd, // window handle
    29.         System.IntPtr hWndInsertAfter, // placement order of the window
    30.         short X, // x position
    31.         short Y, // y position
    32.         short cx, // width
    33.         short cy, // height
    34.         uint uFlags // window flags.
    35.     );
    36.  
    37.     [DllImport("user32.dll")]
    38.     static extern System.IntPtr SetWindowLong(
    39.          System.IntPtr hWnd, // window handle
    40.          int nIndex,
    41.          uint dwNewLong
    42.     );
    43.  
    44.     [DllImport("user32.dll")]
    45.     static extern System.IntPtr GetWindowLong(
    46.         System.IntPtr hWnd,
    47.         int nIndex
    48.     );
    49.  
    50.     System.IntPtr hWnd;
    51.     System.IntPtr HWND_TOP = new System.IntPtr(0);
    52.     System.IntPtr HWND_TOPMOST = new System.IntPtr(-1);
    53.     System.IntPtr HWND_NOTOPMOST = new System.IntPtr(-2);
    54.  
    55.     #endregion
    56.  
    57.     [SerializeField] bool hideOnStart = false;
    58.  
    59.     public void ShowWindowBorders(bool value){
    60.         if(Application.isEditor) return; //We don't want to hide the toolbar from our editor!
    61.  
    62.         int style = GetWindowLong(hWnd, GWL_STYLE).ToInt32(); //gets current style
    63.  
    64.         if(value){
    65.             SetWindowLong(hWnd, GWL_STYLE, (uint)(style | WS_CAPTION | WS_SIZEBOX)); //Adds caption and the sizebox back.
    66.             SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); //Make the window normal.
    67.         } else {
    68.             SetWindowLong(hWnd, GWL_STYLE, (uint)(style & ~(WS_CAPTION | WS_SIZEBOX))); //removes caption and the sizebox from current style.
    69.             SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); //Make the window render above toolbar.
    70.         }
    71.     }
    72.  
    73.     private void Awake() {
    74.         hWnd = GetActiveWindow(); //Gets the currently active window handle for use in the user32.dll functions.
    75.     }
    76.     private void Start() {
    77.         if(hideOnStart) ShowWindowBorders(false);
    78.     }
    79. }
    Snap 2019-08-17 at 19.52.25.png
    Snap 2019-08-17 at 19.53.15.png
    Add this component to any gameobject and either set hideOnStart to true, or call ShowWindowBorders() method when needed.

    Have in mind that the code will work only on Windows. If you also want to be able to build your game for other platforms you'll either have to add preprocessor conditions or setup an asmdef file.
     
    Last edited: Aug 17, 2019
  3. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    Thanks for the script Griz. Do you have any idea how to keep the bar hidden when the screen resolution changes ? I've tried for a while now swapping between horizontal and vertical layouts using Screen.SetResolution but the bar keeps reappearing.
     
  4. Grizmu

    Grizmu

    Joined:
    Aug 27, 2013
    Posts:
    131
    You can call ShowWindowBorders(false) method, which is included in the example. to hide the bar again.
     
  5. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    Oh sorry, I just messed with my code, which made my bar reappear as soon as it dissapeared, by bad. I feel pretty dumb asking this x) Do you know by any chance why this method can't be called through a UI button ? I put it in a parent method and tried to call it but nothing changes.

    EDIT : Okay, I posed a second dumb question, I called the method throughout another script that allowed me to maximize / minimize the screen via custom buttons, but I forgot to assign your script as a variable into mine. Sorry, It's late for me and it seems I can't think clearly today.
     
    Last edited: Aug 17, 2019
  6. Grizmu

    Grizmu

    Joined:
    Aug 27, 2013
    Posts:
    131
    it can be called through an UI button. Are you calling it in the build, or in the editor? Applicaiton.isEditor blocks it from working in the editor to avoid hiding it's titlebar.

    Also make sure that you call it with false (unticked) bool parameter.
     
  7. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122

    I have a setup where I call your function in the Start method, then in a custom function that changes the resolution of the screen, and THEN hides again the bar, because changing the resolution resets the bar display. I also have another function for the button, and I kinda screwed up with all my booleans. But I found the solution, now it works like a charm. Thank you for your help :)
     
    Grizmu likes this.
  8. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    Hey there, me again. How do you use these lines ?
    Code (CSharp):
    1.  
    2.             SetWindowLong(hWnd, GWL_STYLE, (uint)(style & ~(WS_CAPTION | WS_SIZEBOX))); //removes caption and the sizebox from current style.
    3.             SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); //Make the window render above toolbar.
    I'm trying to offset the width and the height of my window so that it doesn't interescts with the windows task bar. I tried changing the zeroes following the instructions in your comments, but nothing changed.
     
  9. Grizmu

    Grizmu

    Joined:
    Aug 27, 2013
    Posts:
    131
    Here are the references for those functions: SetWindowLong and SetWindowPos.
    To make it possible to change the position or size of the window through SetWindowPos remove the SWP_NOMOVE and SWP_NOSIZE flags. Just make sure to change zeros in the width and height parameters to something big enough, otherwise your window will implode into itself.
     
  10. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122

    I had some trouble at first, but now it works perfectly. I finally have my window changing resolutions and the bar hiding properly. Thanks Griz, you rock !
     
    Grizmu likes this.
  11. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122

    Oops, looks like I still can't go to sleep yet, since I have two bugs that I don't know where they come from. Apparently, when the bar is displayed, the window can always been resizables by dragging the mouse on the edges on the screen, even though I unchecked "Resizable Window" in the project settings. Also, dragging my mouse on the screen makes the window collapse on itself if I don't have the NOSIZE flag. I mustn't have that flag if I want my window to change resolution properly, so I don't know how to circumvent that one.
     
  12. Grizmu

    Grizmu

    Joined:
    Aug 27, 2013
    Posts:
    131
    Resizing is caused by the WS_SIZEBOX flag(reference available here). Remove that from your SetWindowLong calls and you should be set and free to go to sleep. : )

    For the NOSIZE problem you can try calling SetWindowPos again with this flag after you set up the size of your window.
     
  13. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    Removins WS_Sizebox worked, but the Nosize thing still collapses my window, no matter what parameters I put in the function. How would you do it with a simple window ? Here's what I tried :
    Code (CSharp):
    1.         if (show)
    2.         {
    3.             SetWindowLong(hWnd, GWL_STYLE, (uint)(style | WS_CAPTION)); //Adds caption and the sizebox back.
    4.             SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, (short)(currentResolution.x + borderSize.x), (short)(currentResolution.y + borderSize.y), SWP_NOMOVE | SWP_SHOWWINDOW); //Make the window normal.
    5.             SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, (short)Screen.width, (short)Screen.height, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); //Make the window normal.
    6.         }
    7.         else
    8.         {
    9.             SetWindowLong(hWnd, GWL_STYLE, (uint)(style & ~(WS_CAPTION))); //removes caption and the sizebox from current style.
    10.             SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, (short)currentResolution.x, (short)currentResolution.y, SWP_NOMOVE | SWP_SHOWWINDOW); //Make the window render above toolbar.
    11.             SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, (short)Screen.width, (short)Screen.height, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); //Make the window render above toolbar.
    12.         }
     
  14. Grizmu

    Grizmu

    Joined:
    Aug 27, 2013
    Posts:
    131
    You need to experiment around with it. I reckon that SWP_SHOWWINDOW flag might be causing it. You can try to remove it, or use a different flag instead.

    Also you can comment all calls but one and experiment with the variables to see how the window will act to changes. Secondly try disabling Application.isEditor to be able to debug in the editor. Have in mind though that you might make your editor window dissapear, so make sure that you save the project before doing that, as if it happens you'll have to kill the editor from the task manager.
     
    Last edited: Aug 18, 2019
  15. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    OK, thank you for the help. It's 2 am though, so maybe I'll do that a bit later : )
     
    Grizmu likes this.
  16. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    Okay, back into the problem, I finally managed to fix what was wrong. In addition to your script, I had another script tasked with moving the window by clicking on an UI element whether the border was visible or not. Apparently, when I moved the window I forgot to add the offset to the new resolution it was supposed to have, and I only wrote the currentResolution, which means each time I dragged the window, it reduced its size bit by bit untl it was gone.

    The Nosize problem had nothing to do with your script in fact, I just badly combined it with other scripts and I forgot to update a certain variable that allowed them to detect if the window was framed or not. Guess it was not my day. Thank again Griz, now everything works as intended (for real this time ^^ ).
     
    Grizmu likes this.
  17. FeBLeSs

    FeBLeSs

    Joined:
    May 26, 2019
    Posts:
    3
    Sorry to bother you both with the resolved issue, but I'm also having the trouble when the resolution changes. It's bothering me more than 20 hours, so I'd like to ask others for help. I'll list when it works and when it doesn't.

    I assume when you change the resolution from the default and close the application window, then reopen the application, it wants to go back to the default size (I guess it remembers the closed size in cache or something) and counts that as "resolution change". So every time I close the application in different sizes and reopen it, the "ShowWindowBorders(false)" does not work even if it's still there calling from "Start()" (I debugged thousands of times and made sure it was being called) as if it just gets ignored. Thus, the title bar shows.

    The only time it works is when I close the application in default size.
    Code (CSharp):
    1. Screen.SetResolution(DifferentWidthFromDefault, DifferentHeightFromDefault, FullScreenMode.Windowed);
    2. ShowWindowBorders(false);
    When I have the following code inside a button, and when it's clicked, the resolution changes and "ShowWindowBorders(false)" gets called but never does its job (which I still see the title bar).

    But funny thing is, if I don't use that button and uses keyboard input to manually do the following,
    Code (CSharp):
    1. if (Input.GetKeyDown(Somekey)) {
    2.         Screen.SetResolution(SomeWidth, SomeHeight, FullScreenMode.Windowed);
    3. }
    4.        
    5. if (Input.GetKeyDown(SomeOtherkey)) {
    6.         ShowWindowBorders(false);
    7. }
    This code will get rid of the title bar after changing the resolution. It's still not perfectly done though. It does as if the entire application gets stretched to where the title bar used to be. Thus, showing some parts where I don't want users to see.

    It only perfectly works as intended if I close the application window in default size.

    I'm really stuck, any advice will be helpful. I'll have this page open and checking at all times. Thank you. And time for more digging....
     
  18. FeBLeSs

    FeBLeSs

    Joined:
    May 26, 2019
    Posts:
    3
    I figured out that changing the resolution apparently takes some time, so executing "ShowWindowBorders(false)" right away was happening before.

    SetResolution Called -> processingResChange & ShowWindowBorders(false) Called -> Border Disappears -> Res Changes.

    After I put some interval between those two executions (like 0.1 seconds) it seems to work, but still not perfectly. As I mentioned above, for example, even though I said 1280 x 720, it changes to 1296 x 759 (Not stretching, just expanding, so hidden parts become visible). Same for every other resolutions. It's always 16 more pixels on Width and 39 more pixels on Height. I assume that's the application window border size. Maybe I'll have to manually decrease by that amount when I call SetResolution method.
     
  19. FeBLeSs

    FeBLeSs

    Joined:
    May 26, 2019
    Posts:
    3
    Okay, that was a success, by manually putting some time interval between res change and border hide methods, and manually putting some width and height offsets. But I understand that's more like a cheating way, not actually using the user32.dll file to fix it.

    If you guys still know the answer without doing my way, please give me heads up. Thank you.
     
  20. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122

    Hey there, sorry for not replying earlier. I had the same issue as you, toggling the resolution mode on and off would constantly offset the resolution values for my screen. I did the same thing : I just added some offset values to counterbalance that, so I don't think there's a way to to this properly :/
     
  21. Gmjjr

    Gmjjr

    Joined:
    Nov 21, 2017
    Posts:
    3
    Howdy,
    I tried using the script posted here and it works great! except for one issue, when the application resizes, all my buttons' hitboxes are offset. have any of y'all run into this issue and if so, have you found a solution?
     
  22. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122
    Hey there, this topic is a bit old, but I'll try to help you as much as I can. I never encountered this problem with my UI, so it must mean either your canvas is not set to screen space camera, or your buttons have their anchors set incorrectly. I don't really know what causes this problem, so it must be one of these.
     
  23. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    I'm having the same issue on our project. At the time, windowless was an optional feature so we just dropped it, but it would be great to be able to resolve it.

    Regarding your suggested fixes, our project is completely in screen space and the buttons' anchors are all set correctly (everything lines up exactly when the titlebar hider is disabled).

    I noticed you resolved this a while ago - does your solution still work in 2019.3? Perhaps this was a bug introduced recently in the engine.


    Here's the inspector for our main canvas in the project which exhibited the issue, in case you see any clues here that are different from yours in important ways:

    upload_2020-5-26_17-20-40.png
     
  24. Gmjjr

    Gmjjr

    Joined:
    Nov 21, 2017
    Posts:
    3
    My canvas and anchors are set correctly, I've even gone as far as double checking them to be safe.
    I'ts not that my buttons aren't appearing after hiding the bar, but that their event detection (mouseover, click, etc) is no longer on the image. The button works fine at any resolution I've tried, so long as I don't hide the title bar.
    ItDoneBroke.gif

    Edit:
    I did some more digging and found where someone has published a script that does exactly what I was looking to do. I'm not sure if this will help anyone else out, but I'll drop a link to it.
    https://novack.itch.io/borderless
     
    Last edited: May 27, 2020
  25. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    122

    I've already tried this asset, and even left a debug message for the developer ; I wouldn't personnaly recommend it since it has pretty impredictable results, but if it does what you wanted to achieve, go for it.


    I've attached a few pictures to show you my full setup, however mine is a bit tricky, since I have multiple screens dealing with resizing the window at once : WindowScript and ToolbarHider. SInce ToolbarHider is already shown in the thread, here is WindowScript. It contrains only functions you can call by UI buttons to resize, maximize, close and drag the window. Make sure the pixel offset in ToolbalHider and WindowScript is always the same :

    https://pastebin.com/w9byAZ2c

    As for my setup :

    up.png down.png


    I hope this helps, if you have more questions don't hesitate.
     
  26. Feartheway

    Feartheway

    Joined:
    Dec 12, 2017
    Posts:
    92
    anyone give some guidance on how to do this on linux?
     
    Igor_Fedorovskiy likes this.
  27. Igor_Fedorovskiy

    Igor_Fedorovskiy

    Joined:
    Mar 26, 2020
    Posts:
    3
    HI, who know how do this from MacOS?
     
  28. Feartheway

    Feartheway

    Joined:
    Dec 12, 2017
    Posts:
    92
    I think its in the unity build menu, build settings, player settings
    You can also do it via the operating system in linux.
     

    Attached Files:

  29. Ollibanjo

    Ollibanjo

    Joined:
    Feb 5, 2020
    Posts:
    2
    Hi Griz, thanks for your solution. It is working fine for me, i use Unity 2020.1.11f1
    With your script the Titlebar is hidden:
    , upload_2020-12-18_23-42-44.png
    These are my Settings, game is build in resolution for Samsung S10e, and also only in portrait mode in windows.
    My initiall problem was, that a litte bit of my gamewindow was out of my display because the TitleBar from windows was added to the resolution.


    upload_2020-12-19_0-0-50.png

    also for the other people, maybe have a look at: https://novack.itch.io/borderless
     
    Last edited: Dec 18, 2020
  30. jasursadikov

    jasursadikov

    Joined:
    Feb 25, 2020
    Posts:
    17
    Is it possible to make window tile the same as in here:
    upload_2021-1-3_3-53-28.png

    upload_2021-1-3_3-54-13.png

    Make it like a transparent but keeping functionality?
     
  31. mz00956

    mz00956

    Joined:
    Jun 29, 2019
    Posts:
    21
    No because thats not the Windows title bar. Its a custom one that just calles the same functions as the default one
     
  32. wixette

    wixette

    Joined:
    Mar 30, 2020
    Posts:
    2
    For macOS, create a dynamic library project in XCode. Put the following Objective-C code into the project:

    TitlebarLib.h

    Code (csharp):
    1. #import <Foundation/Foundation.h>
    2. #import <AppKit/AppKit.h>
    3.  
    4. #if __cplusplus
    5. extern "C" {
    6. #endif
    7.  
    8. int ShowTitleBar();
    9.  
    10. int HideTitleBar();
    11.  
    12. #if __cplusplus
    13. }
    14. #endif
    TitlebarLib.m

    Code (csharp):
    1. #import "TitlebarLib.h"
    2.  
    3. int ShowTitleBar() {
    4.     NSWindow* win = [NSApplication.sharedApplication mainWindow];
    5.     win.titleVisibility = NSWindowTitleVisible;
    6.     win.titlebarAppearsTransparent = false;
    7.     win.movableByWindowBackground = false;
    8.     win.styleMask &= ~NSWindowStyleMaskFullSizeContentView;
    9.     return 0;
    10. }
    11.  
    12. int HideTitleBar() {
    13.     NSWindow* win = [NSApplication.sharedApplication mainWindow];
    14.     win.titleVisibility = NSWindowTitleHidden;
    15.     win.titlebarAppearsTransparent = true;
    16.     win.movableByWindowBackground = true;
    17.     win.styleMask |= NSWindowStyleMaskFullSizeContentView;
    18.     return 0;
    19. }
    Build the XCode project. Put the output file libTitlebarLib.dylib into the Plugins dir of the Unity project. Use the following code to import the two native functions:

    Code (CSharp):
    1. using System.Runtime.InteropServices;
    2. using UnityEngine;
    3.  
    4. public class GameManager : MonoBehaviour {
    5.   [DllImport("libTitlebarLib")]
    6.   public extern static int ShowTitleBar();
    7.  
    8.   [DllImport("libTitlebarLib")]
    9.   public extern static int HideTitleBar();
    10.  
    11.   public void OnShowTitleBar() {
    12.     int ret = ShowTitleBar();
    13.     Debug.Log($"ShowTitleBar = {ret}");
    14.   }
    15.  
    16.   public void OnHideTitleBar() {
    17.     int ret = HideTitleBar();
    18.     Debug.Log($"HideTitleBar = {ret}");
    19.   }
    20. }
    macOS_hide_unity_titlebar.png
     
  33. AntiScope

    AntiScope

    Joined:
    Sep 27, 2021
    Posts:
    1
    Why is my window so tiny??
     

    Attached Files:

  34. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,455
    Please create your own posts. Do not necro/hijack threads.

    Community Code of Conduct
     
Thread Status:
Not open for further replies.