Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WPF

How to Remove the Close Button from a WPF ToolWindow

4.50/5 (7 votes)
10 Nov 2016Public Domain2 min read 55.8K  
This tip shows how to remove the close window from a WPF ToolWindow, so that exiting the window can be tightly controlled.

Introduction

One of the things I’ve had to do over the years is remove the Close box from a WPF window, in order to create a tools or response-type window that the user can only exit by selecting one of the buttons that I provide him. I use it so frequently that I eventually created my own class, inherited from the Window class, that contains the extra functionality.

NOTE: This solution is aimed at windows with the Style of ToolWindow… it simply removes the close button in the upper-right corner in order to control more tightly how exit from the window is accomplished.

Keep in mind also that this solution will work for any windows, not just those with a ToolWindow style, EXCEPT that it will also remove the minimize and maximize buttons.

Using the Code

This is a walkthrough of the process for creating a WPF ToolWindow, using a brand-new project as an example. Simply follow the steps outlined here to make it work.

The project I created was called SampleRemoveCloseBox, and that was also the name of the namespace.

First, create a new WPF project, and add a single button to close the program. The XAML should look like this:

XML
//
// XAML Code, window with close button
//
<Window x:Class="SampleRemoveCloseBox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" 
        Width="525" WindowStyle="ToolWindow">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Button Name="btnClose" Margin="5,5,5,5" 
        Click="btnClose_Click">Close the Program</Button>
    </Grid>
</Window>
...

And the program when run looks like this:

Image 1

The goal is to remove the close box in the upper right corner, so that the only way to exit the program is by pressing the button.

In the code-behind, create the class for the window.

C#
//
// C# Code, CustomWindow class declaration
//
public partial class CustomWindow : Window
{
    // Prep stuff needed to remove close button on window
    private const int GWL_STYLE = -16;
    private const int WS_SYSMENU = 0x80000;
    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
    private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

    public CustomWindow()
    {
        Loaded += ToolWindow_Loaded;
    }

    void ToolWindow_Loaded(object sender, RoutedEventArgs e)
    {
        // Code to remove close box from window
        var hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
        SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU);
    }
}...

This is the code that removes the close button. If you want to do this without the custom class, just place the prep stuff in your window class, and then the actual code in the loaded event for your window.

But to continue this tutorial, change the window definition to inherit from this class instead of window.

C#
//
// C# Code, inherit window from CustomWindow
//
public partial class MainWindow : CustomWindow
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void btnClose_Click(object sender, RoutedEventArgs e)
    {
        Close();
    }
}
...

Now change the XAML to also inherit from that class instead of window.

XML
//
// XAML Code, window is of CustomWindow class
//
<local:CustomWindow x:Class="SampleRemoveCloseBox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:SampleRemoveCloseBox"
        Title="MainWindow" Height="350" 
        Width="525" WindowStyle="ToolWindow">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Button Name="btnClose" Margin="5,5,5,5" 
        Click="btnClose_Click">Close the Program</Button>
    </Grid>
</local:CustomWindow>...

And now the program when run looks like this:

Image 2

Notice that the close button is gone from the upper right corner of the program. This can be used for popup dialog boxes for which a response is required, or any kind of a data entry window where the user should use the provided methods to leave the window. Basically, it is useful anywhere you use a ToolWindow.

The title bar is not strictly under WPF control, so what you can do with it is limited. Because of that, you need to set the window style using WIN32 calls, but they work well enough.

And that's all there is to it. A pretty simple solution, even though it is incredibly NOT intuitively obvious.

Points of Interest

For a long time, I simply dropped the relevant code onto any form I needed it on, but eventually I did create a CustomWindow class that automatically included that functionality, making it even easier to implement this solution.

History

  • 2016-11-09 -- Original version

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication