How to hide close button in WPF window?

214,998

Solution 1

WPF doesn't have a built-in property to hide the title bar's Close button, but you can do it with a few lines of P/Invoke.

First, add these declarations to your Window class:

private const int GWL_STYLE = -16;
private const int WS_SYSMENU = 0x80000;
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

Then put this code in the Window's Loaded event:

var hwnd = new WindowInteropHelper(this).Handle;
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU);

And there you go: no more Close button. You also won't have a window icon on the left side of the title bar, which means no system menu, even when you right-click the title bar - they all go together.

Important note: all this does is hide the button. The user can still close the window! If the user presses Alt+F4, or closes the app via the taskbar, the window will still close.

If you don't want to allow the window to close before the background thread is done, then you could also override OnClosing and set Cancel to true, as Gabe suggested.

Solution 2

I just got to similar problem and Joe White's solution seems to me simple and clean. I reused it and defined it as an attached property of Window

public class WindowBehavior
{
    private static readonly Type OwnerType = typeof (WindowBehavior);

    #region HideCloseButton (attached property)

    public static readonly DependencyProperty HideCloseButtonProperty =
        DependencyProperty.RegisterAttached(
            "HideCloseButton",
            typeof (bool),
            OwnerType,
            new FrameworkPropertyMetadata(false, new PropertyChangedCallback(HideCloseButtonChangedCallback)));

    [AttachedPropertyBrowsableForType(typeof(Window))]
    public static bool GetHideCloseButton(Window obj) {
        return (bool)obj.GetValue(HideCloseButtonProperty);
    }

    [AttachedPropertyBrowsableForType(typeof(Window))]
    public static void SetHideCloseButton(Window obj, bool value) {
        obj.SetValue(HideCloseButtonProperty, value);
    }

    private static void HideCloseButtonChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var window = d as Window;
        if (window == null) return;

        var hideCloseButton = (bool)e.NewValue;
        if (hideCloseButton && !GetIsHiddenCloseButton(window)) {
            if (!window.IsLoaded) {
                window.Loaded += HideWhenLoadedDelegate;
            }
            else {
                HideCloseButton(window);
            }
            SetIsHiddenCloseButton(window, true);
        }
        else if (!hideCloseButton && GetIsHiddenCloseButton(window)) {
            if (!window.IsLoaded) {
                window.Loaded -= ShowWhenLoadedDelegate;
            }
            else {
                ShowCloseButton(window);
            }
            SetIsHiddenCloseButton(window, false);
        }
    }

    #region Win32 imports

    private const int GWL_STYLE = -16;
    private const int WS_SYSMENU = 0x80000;
    [DllImport("user32.dll", SetLastError = true)]
    private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
    [DllImport("user32.dll")]
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

    #endregion

    private static readonly RoutedEventHandler HideWhenLoadedDelegate = (sender, args) => {
        if (sender is Window == false) return;
        var w = (Window)sender;
        HideCloseButton(w);
        w.Loaded -= HideWhenLoadedDelegate;
    };

    private static readonly RoutedEventHandler ShowWhenLoadedDelegate = (sender, args) => {
        if (sender is Window == false) return;
        var w = (Window)sender;
        ShowCloseButton(w);
        w.Loaded -= ShowWhenLoadedDelegate;
    };

    private static void HideCloseButton(Window w) {
        var hwnd = new WindowInteropHelper(w).Handle;
        SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU);
    }

    private static void ShowCloseButton(Window w) {
        var hwnd = new WindowInteropHelper(w).Handle;
        SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_SYSMENU);
    }

    #endregion

    #region IsHiddenCloseButton (readonly attached property)

    private static readonly DependencyPropertyKey IsHiddenCloseButtonKey =
        DependencyProperty.RegisterAttachedReadOnly(
            "IsHiddenCloseButton",
            typeof (bool),
            OwnerType,
            new FrameworkPropertyMetadata(false));

    public static readonly DependencyProperty IsHiddenCloseButtonProperty =
        IsHiddenCloseButtonKey.DependencyProperty;

    [AttachedPropertyBrowsableForType(typeof(Window))]
    public static bool GetIsHiddenCloseButton(Window obj) {
        return (bool)obj.GetValue(IsHiddenCloseButtonProperty);
    }

    private static void SetIsHiddenCloseButton(Window obj, bool value) {
        obj.SetValue(IsHiddenCloseButtonKey, value);
    }

    #endregion

}

Then in XAML you just set it like this:

<Window 
    x:Class="WafClient.Presentation.Views.SampleWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:u="clr-namespace:WafClient.Presentation.Behaviors"
    ResizeMode="NoResize"
    u:WindowBehavior.HideCloseButton="True">
    ...
</Window>

Solution 3

Set WindowStyle property to None which will hide the control box along with the title bar. No need to kernal calls.

Solution 4

This won't get rid of the close button, but it will stop someone closing the window.

Put this in your code behind file:

protected override void OnClosing(CancelEventArgs e)
{
   base.OnClosing(e);
   e.Cancel = true;
}

Solution 5

To disable close button you should add the following code to your Window class (the code was taken from here, edited and reformatted a bit):

protected override void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);

    HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;

    if (hwndSource != null)
    {
        hwndSource.AddHook(HwndSourceHook);
    }

}

private bool allowClosing = false;

[DllImport("user32.dll")]
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32.dll")]
private static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);

private const uint MF_BYCOMMAND = 0x00000000;
private const uint MF_GRAYED = 0x00000001;

private const uint SC_CLOSE = 0xF060;

private const int WM_SHOWWINDOW = 0x00000018;
private const int WM_CLOSE = 0x10;

private IntPtr HwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    switch (msg)
    {
        case WM_SHOWWINDOW:
            {
                IntPtr hMenu = GetSystemMenu(hwnd, false);
                if (hMenu != IntPtr.Zero)
                {
                    EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
                }
            }
            break;
        case WM_CLOSE:
            if (!allowClosing)
            {
                handled = true;
            }
            break;
    }
    return IntPtr.Zero;
}

This code also disables close item in System menu and disallows closing the dialog using Alt+F4.

You will probably want to close the window programmatically. Just calling Close() will not work. Do something like this:

allowClosing = true;
Close();
Share:
214,998

Related videos on Youtube

Michael Hedgpeth
Author by

Michael Hedgpeth

DevOps/Automation architect focused on chef

Updated on August 27, 2021

Comments

  • Michael Hedgpeth
    Michael Hedgpeth over 2 years

    I'm writing a modal dialog in WPF. How do I set a WPF window to not have a close button? I'd still like for its WindowState to have a normal title bar.

    I found ResizeMode, WindowState, and WindowStyle, but none of those properties allow me to hide the close button but show the title bar, as in modal dialogs.

    • Andy
      Andy about 15 years
      Does your modal dialog have a cancel button? If so, could you treat hitting the close button the same as pressing Cancel?
    • Michael Hedgpeth
      Michael Hedgpeth about 15 years
      It's a progress dialog for a background worker. I'm starting to think that not including a window title would probably be best.
    • Michael Hedgpeth
      Michael Hedgpeth about 15 years
      It's a progress dialog running a background thread that doesn't support cancelling; I guess I'm just trying to make it so I don't have to support cancelling (yet). You're probably right, though.
    • Christian Hayter
      Christian Hayter almost 14 years
      I also hate apps trying to remove window chrome. If I make a progress dialog, I always make the window Close button do the same logic as clicking the actual Cancel button.
    • Jean-Marie
      Jean-Marie almost 12 years
      For Chris: Lets imagine your software is for Video Surveillance. A security Agent during the night HAS (that's his job) to keep the windows opened... but sometimes their work is boring and they want to surf Internet or close the Video Matrices windows for any reason, removing the windows buttons is the proper way to do it.
    • MickyD
      MickyD over 9 years
      @ChrisUpchurch, "Why do you want to do this? It strikes me as really lousy UI design. " - really "lousy UI design" is when a program presents a dialog box with OK; Cancel and Close buttons. To a user, it may not be obvious what Close does. Does it cancel or submit? Consensus is not to include close buttons in dialogs so there is that
    • Digital_Utopia
      Digital_Utopia over 8 years
      @Jean-Marie But hiding the close button doesn't prevent that from happening, it only fools the uninformed and lazy(to Google). Hiding the close button only prevents clicking that button. Win key and alt key combos will still work as normal The "proper" way to do it, is to make a user account for workers, with a group policy that prevents them from opening/installing any software other than what's approved.Then have an admin account, that supervisors have access to, to handle any maintenance.
  • a_h
    a_h about 15 years
    for some reason "should work" just was displayed, but now updated have occurred
  • Michael Hedgpeth
    Michael Hedgpeth about 15 years
    I'm talking about the Window state though, which is in the title bar. This looks like editing a simple button.
  • Shimmy Weitzhandler
    Shimmy Weitzhandler over 14 years
    @TStamper, how do I use your snippet? I am using a global Window style (and template).
  • a_h
    a_h over 14 years
    @Shimmy- which one are you referring to?
  • Admin
    Admin about 14 years
    In Windows 7: The above also disables (but does not remove) the Close item in the drop-down System menu. The Close button itself is disable (looks gray), but not removed. This trick does not work for the Minimize/Maximize item/button -- I suspect WPF re-enables them.
  • Jonathan Allen
    Jonathan Allen almost 14 years
    According to the docs we should be using SetWindowLongPtr instead.
  • doobop
    doobop over 13 years
    Mostly a note to self... Namespace of DllImport -> System.Runtime.InteropServices.DllImport. Namespace of WindowInteropHelper -> System.Windows.Interop.WindowInteropHelper
  • Robert Baker
    Robert Baker about 13 years
    Disabling the button is better than just removing them, it keeps a consistent feel while letting the user know that an important operation is running.
  • Sheridan
    Sheridan almost 12 years
    Be aware that doing this in a Window that is set up as a modal dialog will interfere with the Window setting its DialogResult property and may make it unusable. stackoverflow.com/questions/898708/cant-set-dialogresult-in-‌​wpf
  • Talon
    Talon about 11 years
    Not sure why all the other answers. var win = new Window(); win.WindowStyle = WindowStyle.None; win.Show();
  • Antonio Teh Sumtin
    Antonio Teh Sumtin about 11 years
    In my opinion, this is by far the best answer of them all, I am new to WPF and was just looking into this matter, brilliant!
  • newman
    newman about 11 years
    Actually, this approach hides all three buttons (Min, Max and Close). Is it possible to just hide the Close button?
  • newman
    newman about 11 years
    Well, this will hide the window title bar completely. That means you don't get window title and user will not be able to move the window.
  • Joe White
    Joe White about 11 years
    @miliu, nope. You can disable it, but you can't hide it without hiding Minimize/Maximize as well. I suspect the Windows devs thought it would be confusing if Maximize was on the right where Close usually is.
  • Matt Davis
    Matt Davis over 10 years
    Perfect! Added as a Window extension method in my project.
  • paul
    paul about 10 years
    You can make the window movable by adding this.DragMove(); to the window's MouseDown event
  • VoteCoffee
    VoteCoffee about 10 years
    This also hides the max/min buttons
  • memory of a dream
    memory of a dream about 10 years
    does not solve the problem hiding the close button
  • jacobsgriffith
    jacobsgriffith almost 10 years
    I was getting an overflow using this method, I took out base.OnClosing(e) and then it worked
  • The Lonely Coder
    The Lonely Coder over 9 years
    For a modal dialog that should be purely informational and mandatory, like progress on upgrading a database with an old schema that has been opened, this solution is perfect.
  • pjdupreez
    pjdupreez over 9 years
    I think some people would like to have a border, though
  • Admin
    Admin almost 9 years
    As a user i would hate the programmer who put this into their application
  • diegodsp
    diegodsp almost 9 years
    Put WindowStyle="None" on your Window tag in the XAML file.
  • Joe White
    Joe White almost 9 years
    @diegodsp, from the original question: "I'd still like for its WindowState to have a normal title bar." WindowStyle=None has no title bar.
  • Jonathan Wood
    Jonathan Wood almost 8 years
    More difficulty from WPF for even the most trivial tasks. Gawd I am not liking learning WPF.
  • rory.ap
    rory.ap over 7 years
    "This has the same effect as hiding the close button." except that the button is still visible and clickable, i.e. it's animated and depresses visually when you click it -- which defies POLA.
  • vapcguy
    vapcguy about 7 years
    Forgot to mention you need a this.Loaded += new RoutedEventHandler(Window_Loaded) line in the code that runs onload, so it will pick up the event, and Window_Loaded needs to be instatiated as private void Window_Loaded(object sender, RoutedEventArgs e) { ... }. Not everyone knows these things.
  • vapcguy
    vapcguy about 7 years
    Fully agree with @pjdupreez - a dialog box without the title bar is both ugly and non-descriptive. Voting down because it's a shotgun approach. Most I feel would not want to do it this way if it could be avoided - especially when an alternative DOES exist.
  • vapcguy
    vapcguy about 7 years
    Downvote. It's actually WindowStyle = "None" - watch your syntax. For another, it is a shotgun approach that also removes the title bar, making the box ugly and lacking a title, when there are so many much better ways to handle this (as evidenced by the other answers), and is a duplicate answer.
  • vapcguy
    vapcguy about 7 years
    Still a bad idea. It removes the whole title bar, making this a shotgun approach, and makes the box look ugly and means there's no title/description for it. There are much better alternatives.
  • vapcguy
    vapcguy about 7 years
    It removes the whole title bar, rendering the box ugly and without a description. Shotgun approach and a duplicate answer. Downvote.
  • buks
    buks almost 7 years
    Definitely the best solution. There is no problem with adding border to panel, or implementing moving.
  • flurbius
    flurbius almost 7 years
    @UrbanEsc I would tend to agree that its an annoying thing to do, but when I did this - and it was only the one time - it was a mandatory requirement, and it was a necessary evil, there was some very important process going on that could not be interrupted and the app couldn't proceed until it was done. There were other ways it could have been done (a background thread, with the UI disabled until ready) but the boss and client both liked it this way because it emphasised the gravity of the process.
  • Holf
    Holf almost 7 years
    @vapcguy It removes the whole title bar. It is a shotgun approach. Makes the box look ugly? Your opinion. Much better alternatives? For you, perhaps. Not for everybody. :-)
  • Rajon Tanducar
    Rajon Tanducar about 5 years
    This is the best solution for kiosk applications which always need its application to be maximized and shouldn't allow customers to close app. So UpVote
  • Daniel Hollinrake
    Daniel Hollinrake almost 5 years
    Please note that setting WindowStyle="None", whilst it hides all the buttons prevents the window from being moved. This option still allows that.
  • Mike Rosoft
    Mike Rosoft over 4 years
    In WPF WindowStyle is an enumeration whose values do not match the Windows API constants; coercing the value to WindowStyle enumeration will not work. To be sure, I have checked the .NET source code in ILSpy; the enum value is translated to Windows API in the private function CreateWindowStyle, and if the function encounters an unknown WindowStyle value, it simply applies WindowStyle.None. (The only way would be to use the internal properties _Style and _StyleEx using reflection, which I strongly recommend against.)
  • StayOnTarget
    StayOnTarget almost 4 years
    Should it be window.Loaded += ShowWhenLoadedDelegate; instead of -= ? Otherwise I don't see anywhere that ShowWhenLoadedDelegate could ever be called.
  • Mike Yang
    Mike Yang over 3 years
    i can still close it from task bar
  • Joe White
    Joe White over 3 years
    @MikeYang Good point. This is just another case of the user still being able to close the window with Alt+F4, but it's probably more likely for people to run into the taskbar-close scenario. I expanded my answer a bit to further call out the fact that hiding the button doesn't actually prevent closing the window.