¿Cómo ocultar el botón de cerrar en la ventana de WPF?

Resuelto Michael Hedgpeth asked hace 15 años • 24 respuestas

Estoy escribiendo un diálogo modal en WPF. ¿Cómo configuro una ventana de WPF para que no tenga un botón de cierre? Todavía me gustaría que tuviera WindowStateuna barra de título normal.

Encontré ResizeMode, WindowStatey WindowStyle, pero ninguna de esas propiedades me permite ocultar el botón de cerrar pero mostrar la barra de título, como en los cuadros de diálogo modales.

Michael Hedgpeth avatar Apr 13 '09 20:04 Michael Hedgpeth
Aceptado

WPF no tiene una propiedad incorporada para ocultar el botón Cerrar de la barra de título, pero puede hacerlo con unas pocas líneas de P/Invoke.

Primero, agregue estas declaraciones a su clase de Ventana:

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);

Luego ponga este código en el Loadedevento de Windows:

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

Y ahí lo tienes: no más botón Cerrar. Tampoco tendrás un ícono de ventana en el lado izquierdo de la barra de título, lo que significa que no habrá menú del sistema, incluso cuando hagas clic derecho en la barra de título; todos van juntos.

Nota importante: esto lo único que hace es ocultar el botón. ¡El usuario aún puede cerrar la ventana! Si el usuario presiona Alt+ F4o cierra la aplicación a través de la barra de tareas, la ventana aún se cerrará.

Si no desea permitir que la ventana se cierre antes de que finalice el hilo de fondo, también puede anularlo OnClosingy establecerlo Cancelen verdadero, como sugirió Gabe.

Joe White avatar Jun 06 '2009 04:06 Joe White

Acabo de llegar a un problema similar y la solución de Joe White me parece simple y limpia. Lo reutilicé y lo definí como una propiedad adjunta de 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

}

Luego en XAML lo configuras así:

<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>
SpudCZ avatar Jul 14 '2010 15:07 SpudCZ

Establezca WindowStylela propiedad en Ninguno, lo que ocultará el cuadro de control junto con la barra de título. No es necesario realizar llamadas al núcleo.

Sriwantha Attanayake avatar Aug 23 '2012 11:08 Sriwantha Attanayake

Esto no eliminará el botón de cerrar, pero evitará que alguien cierre la ventana.

Pon esto en tu código detrás del archivo:

protected override void OnClosing(CancelEventArgs e)
{
   base.OnClosing(e);
   e.Cancel = true;
}
flurbius avatar May 15 '2009 05:05 flurbius