How to hide close button in WPF window?
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();
Related videos on Youtube
Comments
-
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
, andWindowStyle
, but none of those properties allow me to hide the close button but show the title bar, as in modal dialogs.-
Andy about 15 yearsDoes your modal dialog have a cancel button? If so, could you treat hitting the close button the same as pressing Cancel?
-
Michael Hedgpeth about 15 yearsIt'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 about 15 yearsIt'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 almost 14 yearsI 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 almost 12 yearsFor 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 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 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 about 15 yearsfor some reason "should work" just was displayed, but now updated have occurred
-
Michael Hedgpeth about 15 yearsI'm talking about the Window state though, which is in the title bar. This looks like editing a simple button.
-
Shimmy Weitzhandler over 14 years@TStamper, how do I use your snippet? I am using a global Window style (and template).
-
a_h over 14 years@Shimmy- which one are you referring to?
-
Admin about 14 yearsIn 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 almost 14 yearsAccording to the docs we should be using
SetWindowLongPtr
instead. -
doobop over 13 yearsMostly a note to self... Namespace of DllImport -> System.Runtime.InteropServices.DllImport. Namespace of WindowInteropHelper -> System.Windows.Interop.WindowInteropHelper
-
Robert Baker about 13 yearsDisabling 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 almost 12 yearsBe aware that doing this in a
Window
that is set up as a modal dialog will interfere with theWindow
setting itsDialogResult
property and may make it unusable. stackoverflow.com/questions/898708/cant-set-dialogresult-in-wpf -
Talon about 11 yearsNot sure why all the other answers. var win = new Window(); win.WindowStyle = WindowStyle.None; win.Show();
-
Antonio Teh Sumtin about 11 yearsIn 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 about 11 yearsActually, this approach hides all three buttons (Min, Max and Close). Is it possible to just hide the Close button?
-
newman about 11 yearsWell, 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 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 over 10 yearsPerfect! Added as a
Window
extension method in my project. -
paul about 10 yearsYou can make the window movable by adding
this.DragMove();
to the window'sMouseDown
event -
VoteCoffee about 10 yearsThis also hides the max/min buttons
-
memory of a dream about 10 yearsdoes not solve the problem hiding the
close
button -
jacobsgriffith almost 10 yearsI was getting an overflow using this method, I took out base.OnClosing(e) and then it worked
-
The Lonely Coder over 9 yearsFor 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 over 9 yearsI think some people would like to have a border, though
-
Admin almost 9 yearsAs a user i would hate the programmer who put this into their application
-
diegodsp almost 9 yearsPut WindowStyle="None" on your Window tag in the XAML file.
-
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 almost 8 yearsMore difficulty from WPF for even the most trivial tasks. Gawd I am not liking learning WPF.
-
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 about 7 yearsForgot 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, andWindow_Loaded
needs to be instatiated asprivate void Window_Loaded(object sender, RoutedEventArgs e) { ... }
. Not everyone knows these things. -
vapcguy about 7 yearsFully 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 about 7 yearsDownvote. 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 about 7 yearsStill 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 about 7 yearsIt removes the whole title bar, rendering the box ugly and without a description. Shotgun approach and a duplicate answer. Downvote.
-
buks almost 7 yearsDefinitely the best solution. There is no problem with adding border to panel, or implementing moving.
-
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 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 about 5 yearsThis 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 almost 5 yearsPlease note that setting WindowStyle="None", whilst it hides all the buttons prevents the window from being moved. This option still allows that.
-
Mike Rosoft over 4 yearsIn WPF
WindowStyle
is an enumeration whose values do not match the Windows API constants; coercing the value toWindowStyle
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 functionCreateWindowStyle
, and if the function encounters an unknownWindowStyle
value, it simply appliesWindowStyle.None
. (The only way would be to use the internal properties_Style
and_StyleEx
using reflection, which I strongly recommend against.) -
StayOnTarget almost 4 yearsShould it be
window.Loaded += ShowWhenLoadedDelegate;
instead of-=
? Otherwise I don't see anywhere that ShowWhenLoadedDelegate could ever be called. -
Mike Yang over 3 yearsi can still close it from task bar
-
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.