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

204

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

He encontrado ResizeMode, WindowStatey WindowStyle, pero ninguna de esas propiedades permiten que me esconda el botón de cierre, sino mostrar la barra de título, como en los cuadros de diálogo modales.

Michael Hedgpeth
fuente
9
Es un cuadro de diálogo de progreso que ejecuta un subproceso en segundo plano que no admite la cancelación; Supongo que solo estoy tratando de hacerlo para no tener que soportar la cancelación (todavía). Probablemente tengas razón, sin embargo.
Michael Hedgpeth el
1
También odio las aplicaciones que intentan eliminar el cromo de la ventana. Si hago un cuadro de diálogo de progreso, siempre hago que el botón Cerrar ventana haga la misma lógica que hacer clic en el botón Cancelar real.
Christian Hayter
13
Para Chris: imaginemos que su software es para videovigilancia. Un Agente de seguridad durante la noche TIENE (ese es su trabajo) mantener las ventanas abiertas ... pero a veces su trabajo es aburrido y quieren navegar por Internet o cerrar las ventanas de Video Matrices por cualquier motivo, quitar los botones de las ventanas es la manera correcta para hacerlo.
Jean-Marie
77
@ChrisUpchurch, "¿Por qué quieres hacer esto Me llama la atención como el diseño de interfaz de usuario realmente pésimo." - en realidad "pésimo diseño de UI" es cuando un programa presenta un cuadro de diálogo con OK ; Cancelar y cerrar botones. Para un usuario, puede que no sea obvio lo que hace Close . ¿Se cancela o envía ? El consenso no es incluir botones de cierre en los cuadros de diálogo, por lo que es eso
MickyD
1
@ Jean-Marie Pero ocultar el botón de cierre no evita que eso suceda, solo engaña a los desinformados y perezosos (a Google). Ocultar el botón de cierre solo evita hacer clic en ese botón. Las combinaciones de teclas Win y Alt seguirán funcionando normalmente. La forma "adecuada" de hacerlo es crear una cuenta de usuario para los trabajadores, con una política de grupo que les impida abrir / instalar cualquier software que no sea el aprobado. cuenta de administrador, a la que los supervisores tienen acceso, para manejar cualquier mantenimiento.
Digital_Utopia

Respuestas:

276

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 la ventana :

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á un ícono de ventana en el lado izquierdo de la barra de título, lo que significa que no hay menú del sistema, incluso cuando hace clic con el botón derecho en la barra de título, todos van juntos.

Tenga en cuenta que Alt+ F4aún cerrará la ventana. Si no desea permitir que la ventana se cierre antes de que finalice el subproceso de fondo, también puede anular OnClosingy establecer Cancelen verdadero, como sugirió Gabe.

Joe White
fuente
55
De acuerdo con los documentos que deberíamos usar en su SetWindowLongPtrlugar.
Jonathan Allen
15
Principalmente una nota para uno mismo ... Espacio de nombres de DllImport -> System.Runtime.InteropServices.DllImport. Espacio de nombres de WindowInteropHelper -> System.Windows.Interop.WindowInteropHelper
doobop
3
En realidad, este enfoque oculta los tres botones (Mín., Máx. Y Cerrar). ¿Es posible ocultar el botón Cerrar?
newman
44
@miliu, no. Puede desactivarlo , pero no puede ocultarlo sin ocultar Minimizar / Maximizar también. Sospecho que los desarrolladores de Windows pensaron que sería confuso si Maximize estuviera a la derecha donde normalmente está Close.
Joe White
3
Pon WindowStyle = "None" en tu etiqueta de Windows en el archivo XAML.
diegodsp
89

Acabo de tener 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, simplemente lo configura 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
fuente
64

Establezca la WindowStylepropiedad en Ninguno, lo que ocultará el cuadro de control junto con la barra de título. No hay necesidad de llamadas internas.

Sriwantha Attanayake
fuente
20
Bueno, esto ocultará la barra de título de la ventana por completo. Eso significa que no obtienes el título de la ventana y el usuario no podrá mover la ventana.
newman
8
Puede hacer que la ventana se mueva agregando this.DragMove();al MouseDownevento de la ventana
Paul
1
Para un diálogo modal que debería ser puramente informativo y obligatorio, como el progreso en la actualización de una base de datos con un esquema antiguo que se ha abierto, esta solución es perfecta.
The Lonely Coder
1
Sin embargo, creo que a algunas personas les gustaría tener una frontera
pjdupreez
2
Definitivamente la mejor solución. No hay ningún problema al agregar bordes al panel o al implementar el movimiento.
compra el
50

Esto no eliminará el botón de cerrar, pero impedirá 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
fuente
77
Tenga en cuenta que hacer esto en un Windowcuadro de diálogo modal interferirá con la Windowconfiguración de su DialogResultpropiedad y puede dejarlo inutilizable. stackoverflow.com/questions/898708/cant-set-dialogresult-in-wpf
Sheridan
44
Estaba obteniendo un desbordamiento usando este método, saqué base.OnClosing (e) y luego funcionó
jacobsgriffith
8
Como usuario, odiaría al programador que puso esto en su aplicación
UrbanEsc
2
@UrbanEsc Tendería a aceptar que es algo molesto, pero cuando hice esto, y solo fue la única vez, fue un requisito obligatorio, y era un mal necesario, había un proceso muy importante en curso eso no se pudo interrumpir y la aplicación no pudo continuar hasta que se hizo. Hubo otras formas en que podría haberse hecho (un hilo de fondo, con la interfaz de usuario deshabilitada hasta que esté lista), pero al jefe y al cliente les gustó de esta manera porque enfatizaban la gravedad del proceso.
flurbius
15

Para deshabilitar el botón de cierre, debe agregar el siguiente código a su clase de Windows (el código fue tomado de aquí , editado y reformateado un poco):

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

Este código también desactiva el elemento de cierre en el menú Sistema y no permite cerrar el diálogo usando Alt + F4.

Probablemente desee cerrar la ventana mediante programación. Solo llamar Close()no funcionará. Haz algo como esto:

allowClosing = true;
Close();
Viachaslau Tysianchuk
fuente
En Windows 7: lo anterior también desactiva (pero no elimina) el elemento Cerrar en el menú desplegable Sistema. El botón Cerrar en sí está desactivado (se ve gris), pero no se elimina. Este truco no funciona para el elemento / botón Minimizar / Maximizar: sospecho que WPF los vuelve a habilitar.
3
Deshabilitar el botón es mejor que simplemente quitarlos, mantiene una sensación constante mientras le informa al usuario que se está ejecutando una operación importante.
Robert Baker,
10

Estaba probando la respuesta de Viachaslau porque me gusta la idea de no quitar el botón sino deshabilitarlo, pero por alguna razón no siempre funcionó: el botón de cierre todavía estaba habilitado pero no había ningún error.

Esto, por otro lado, siempre funcionó (se omitió la comprobación de errores):

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

protected override void OnSourceInitialized( EventArgs e )
{
  base.OnSourceInitialized( e );
  var hWnd = new WindowInteropHelper( this );
  var sysMenu = GetSystemMenu( hWnd.Handle, false );
  EnableMenuItem( sysMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED );
}
stijn
fuente
1
¡Perfecto! Agregado como Windowmétodo de extensión en mi proyecto.
Matt Davis
8

La propiedad para establecer es => WindowStyle="None"

<Window x:Class="mdaframework.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="Start" Height="350" Width="525" ResizeMode="NoResize"  WindowStartupLocation="CenterScreen" WindowStyle="None">
daniele3004
fuente
44
Esto también oculta los botones max / min
VoteCoffee
3
Elimina toda la barra de título, haciendo que el cuadro sea feo y sin una descripción. Enfoque de escopeta y una respuesta duplicada. Voto a favor.
vapcguy
Esta es la mejor solución para aplicaciones de kiosco que siempre necesitan que su aplicación se maximice y no debe permitir que los clientes cierren la aplicación. So UpVote
Rajon Tanducar
8

Solo agrego mi implementación de la respuesta de Joe White utilizando el comportamiento de interactividad (debe hacer referencia a System.Windows.Interactivity).

código:

public class HideCloseButtonOnWindow : Behavior<Window>
{
    #region bunch of native methods

    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

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.Loaded += OnLoaded;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.Loaded -= OnLoaded;
        base.OnDetaching();
    }

    private void OnLoaded(object sender, RoutedEventArgs e)
    {
        var hwnd = new WindowInteropHelper(AssociatedObject).Handle;
        SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU);
    }
}

uso:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:w="clr-namespace:WpfApplication2">

    <i:Interaction.Behaviors>
        <w:HideCloseButtonOnWindow />
    </i:Interaction.Behaviors>

</Window>
tom.maruska
fuente
2

Deje que el usuario "cierre" la ventana, pero realmente solo escóndela.

En el evento OnClosing de la ventana, oculte la ventana si ya está visible:

    If Me.Visibility = Windows.Visibility.Visible Then
        Me.Visibility = Windows.Visibility.Hidden
        e.Cancel = True
    End If

Cada vez que se ejecute el subproceso de fondo, vuelva a mostrar la ventana de la interfaz de usuario de fondo:

    w.Visibility = Windows.Visibility.Visible
    w.Show()

Al finalizar la ejecución del programa, asegúrese de que todas las ventanas estén / puedan cerrarse:

Private Sub CloseAll()
    If w IsNot Nothing Then
        w.Visibility = Windows.Visibility.Collapsed ' Tell OnClosing to really close
        w.Close()
    End If
End Sub
BSalita
fuente
1

Entonces, más o menos aquí está tu problema. El botón de cierre en la esquina superior derecha de un marco de ventana no es parte de la ventana de WPF, pero pertenece a la parte del marco de ventana que controla su sistema operativo. Esto significa que tendrá que usar la interoperabilidad Win32 para hacerlo.

alternativamente, puede usar el noframe y proporcionar su propio "marco" o no tener ningún marco.

Muad'Dib
fuente
1

Lo siguiente es sobre deshabilitar los botones de cerrar y Maximizar / Minimizar, no realidad elimina los botones (¡pero elimina los elementos del menú!). Los botones en la barra de título se dibujan en un estado deshabilitado / atenuado. (No estoy listo para asumir toda la funcionalidad yo mismo ^^)

Esto es ligeramente diferente de la solución de Virgoss en que elimina los elementos del menú (y el separador final, si es necesario) en lugar de simplemente deshabilitarlos. Se diferencia de la solución Joe Whites, ya que no deshabilita todo el menú del sistema y, en mi caso, puedo mantener el botón y el icono Minimizar.

El código siguiente también admite la desactivación de los botones Maximizar / Minimizar ya que, a diferencia del botón Cerrar, eliminar las entradas del menú no hace que el sistema haga que los botones estén "desactivados", aunque eliminar las entradas del menú desactiva la funcionalidad de los botones.

Esto funciona para mi. YMMV.

    using System;
    using System.Collections.Generic;
    using System.Text;

    using System.Runtime.InteropServices;
    using Window = System.Windows.Window;
    using WindowInteropHelper = System.Windows.Interop.WindowInteropHelper;
    using Win32Exception = System.ComponentModel.Win32Exception;

    namespace Channelmatter.Guppy
    {

        public class WindowUtil
        {
            const int MF_BYCOMMAND = 0x0000;
            const int MF_BYPOSITION = 0x0400;

            const uint MFT_SEPARATOR = 0x0800;

            const uint MIIM_FTYPE = 0x0100;

            [DllImport("user32", SetLastError=true)]
            private static extern uint RemoveMenu(IntPtr hMenu, uint nPosition, uint wFlags);

            [DllImport("user32", SetLastError=true)]
            private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);

            [DllImport("user32", SetLastError=true)]
            private static extern int GetMenuItemCount(IntPtr hWnd);

            [StructLayout(LayoutKind.Sequential)]
            public struct MenuItemInfo {
                public uint   cbSize;
                public uint   fMask;
                public uint   fType;
                public uint   fState;
                public uint   wID;
                public IntPtr hSubMenu;
                public IntPtr hbmpChecked;
                public IntPtr hbmpUnchecked;
                public IntPtr dwItemData; // ULONG_PTR
                public IntPtr dwTypeData;
                public uint   cch;
                public IntPtr hbmpItem;
            };

            [DllImport("user32", SetLastError=true)]
            private static extern int GetMenuItemInfo(
                IntPtr hMenu, uint uItem,
                bool fByPosition, ref MenuItemInfo itemInfo);

            public enum MenuCommand : uint
            {
                SC_CLOSE = 0xF060,
                SC_MAXIMIZE = 0xF030,
            }

            public static void WithSystemMenu (Window win, Action<IntPtr> action) {
                var interop = new WindowInteropHelper(win);
                IntPtr hMenu = GetSystemMenu(interop.Handle, false);
                if (hMenu == IntPtr.Zero) {
                    throw new Win32Exception(Marshal.GetLastWin32Error(),
                        "Failed to get system menu");
                } else {
                    action(hMenu);
                }
            }

            // Removes the menu item for the specific command.
            // This will disable and gray the Close button and disable the
            // functionality behind the Maximize/Minimuze buttons, but it won't
            // gray out the Maximize/Minimize buttons. It will also not stop
            // the default Alt+F4 behavior.
            public static void RemoveMenuItem (Window win, MenuCommand command) {
                WithSystemMenu(win, (hMenu) => {
                    if (RemoveMenu(hMenu, (uint)command, MF_BYCOMMAND) == 0) {
                        throw new Win32Exception(Marshal.GetLastWin32Error(),
                            "Failed to remove menu item");
                    }
                });
            }

            public static bool RemoveTrailingSeparator (Window win) {
                bool result = false; // Func<...> not in .NET3 :-/
                WithSystemMenu(win, (hMenu) => {
                    result = RemoveTrailingSeparator(hMenu);
                });
                return result;
            }

            // Removes the final trailing separator of a menu if it exists.
            // Returns true if a separator is removed.
            public static bool RemoveTrailingSeparator (IntPtr hMenu) {
                int menuItemCount = GetMenuItemCount(hMenu);
                if (menuItemCount < 0) {
                    throw new Win32Exception(Marshal.GetLastWin32Error(),
                        "Failed to get menu item count");
                }
                if (menuItemCount == 0) {
                    return false;
                } else {
                    uint index = (uint)(menuItemCount - 1);
                    MenuItemInfo itemInfo = new MenuItemInfo {
                        cbSize = (uint)Marshal.SizeOf(typeof(MenuItemInfo)),
                        fMask = MIIM_FTYPE,
                    };

                    if (GetMenuItemInfo(hMenu, index, true, ref itemInfo) == 0) {
                        throw new Win32Exception(Marshal.GetLastWin32Error(),
                            "Failed to get menu item info");
                    }

                    if (itemInfo.fType == MFT_SEPARATOR) {
                        if (RemoveMenu(hMenu, index, MF_BYPOSITION) == 0) {
                            throw new Win32Exception(Marshal.GetLastWin32Error(),
                                "Failed to remove menu item");
                        }
                        return true;
                    } else {
                        return false;
                    }
                }
            }

            private const int GWL_STYLE = -16;

            [Flags]
            public enum WindowStyle : int
            {
                WS_MINIMIZEBOX = 0x00020000,
                WS_MAXIMIZEBOX = 0x00010000,
            }

            // Don't use this version for dealing with pointers
            [DllImport("user32", SetLastError=true)]
            private static extern int SetWindowLong (IntPtr hWnd, int nIndex, int dwNewLong);

            // Don't use this version for dealing with pointers
            [DllImport("user32", SetLastError=true)]
            private static extern int GetWindowLong (IntPtr hWnd, int nIndex);

            public static int AlterWindowStyle (Window win,
                WindowStyle orFlags, WindowStyle andNotFlags) 
            {
                var interop = new WindowInteropHelper(win);

                int prevStyle = GetWindowLong(interop.Handle, GWL_STYLE);
                if (prevStyle == 0) {
                    throw new Win32Exception(Marshal.GetLastWin32Error(),
                        "Failed to get window style");
                }

                int newStyle = (prevStyle | (int)orFlags) & ~((int)andNotFlags);
                if (SetWindowLong(interop.Handle, GWL_STYLE, newStyle) == 0) {
                    throw new Win32Exception(Marshal.GetLastWin32Error(),
                        "Failed to set window style");
                }
                return prevStyle;
            }

            public static int DisableMaximizeButton (Window win) {
                return AlterWindowStyle(win, 0, WindowStyle.WS_MAXIMIZEBOX);
            }
        }
    }

Uso: Esto debe hacerse DESPUÉS de que se inicialice la fuente. Un buen lugar es usar el evento SourceInitialized de la ventana:

Window win = ...; /* the Window :-) */
WindowUtil.DisableMaximizeButton(win);
WindowUtil.RemoveMenuItem(win, WindowUtil.MenuCommand.SC_MAXIMIZE);
WindowUtil.RemoveMenuItem(win, WindowUtil.MenuCommand.SC_CLOSE);
while (WindowUtil.RemoveTrailingSeparator(win)) 
{
   //do it here
}

Para deshabilitar la funcionalidad Alt + F4, el método fácil es simplemente conectar el evento de Cancelación y usar establecer un indicador para cuando realmente desea cerrar la ventana.

daniele3004
fuente
0

Código XAML

<Button Command="Open" Content="_Open">
    <Button.Style>
        <Style TargetType="Button">
            <Style.Triggers>
                <Trigger Property="IsEnabled" Value="False">
                    <Setter Property="Visibility" Value="Collapsed" />
                </Trigger>
            </Style.Triggers>
        </Style>
     </Button.Style>
</Button>

Deberia trabajar

Editar : para su instante, este hilo muestra cómo se puede hacer eso, pero no creo que Window tenga una propiedad para obtener lo que desea sin perder la barra de título normal.

Editar 2 Este hilo muestra una forma de hacerlo, pero debe aplicar su propio estilo al menú del sistema y muestra una forma de cómo puede hacerlo.

TStamper
fuente
por alguna razón "debe trabajar" solo se muestran, pero ahora se actualizan haber ocurrido
TStamper
3
Sin embargo, estoy hablando del estado de la ventana, que está en la barra de título. Esto parece editar un botón simple.
Michael Hedgpeth el
@TStamper, ¿cómo uso tu fragmento? Estoy usando un estilo de ventana global (y plantilla).
Shimmy Weitzhandler
@ Shimmy, ¿a cuál te refieres?
TStamper
0

Intente agregar un evento de cierre a la ventana. Agregue este código al controlador de eventos.

e.Cancel = true;

Esto evitará que la ventana se cierre. Esto tiene el mismo efecto que ocultar el botón de cierre.

Dennis R
fuente
1
"Esto tiene el mismo efecto que ocultar el botón de cierre". excepto que el botón todavía está visible y se puede hacer clic, es decir, está animado y se presiona visualmente cuando hace clic, lo que desafía a POLA .
rory.ap
0

Use esto, modificado desde https://stephenhaunts.com/2014/09/25/remove-the-close-button-from-a-wpf-window :

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;

namespace Whatever
{
    public partial class MainMenu : Window
    {
        private const int GWL_STYLE = -16;
        private const int WS_SYSMENU = 0x00080000;

        [DllImport("user32.dll", SetLastError = true)]
        private static extern int GetWindowLongPtr(IntPtr hWnd, int nIndex);

        [DllImport("user32.dll")]
        private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

        public MainMenu()
        {
             InitializeComponent();
             this.Loaded += new RoutedEventHandler(Window_Loaded);
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            var hwnd = new WindowInteropHelper(this).Handle;
            SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) & ~WS_SYSMENU);
        }  

    }
}
vapcguy
fuente
0

Esto no oculta el botón, pero evitará que el usuario avance al cerrar la ventana.

protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{            
    if (e.Cancel == false)
    {
        Application.Current.Shutdown();
    }
}
A. Lartey
fuente
-1

Ir a conjunto de propiedades de ventana

window style = none;

no conseguirás cerrar botones ...

Pavan R Bhupalam
fuente
Voto a favor. En realidad es WindowStyle = "None", mira tu sintaxis. Por otro lado, es un enfoque de escopeta que también elimina la barra de título, haciendo que el cuadro sea feo y carezca de título, cuando hay muchas formas mucho mejores de manejar esto (como lo demuestran las otras respuestas), y es una respuesta duplicada.
vapcguy
-1

Como se indica en otras respuestas, puede usar WindowStyle="None"para eliminar la barra de título por completo.

Y, como se indica en los comentarios a esas otras respuestas, esto evita que la ventana se pueda arrastrar, por lo que es difícil moverla desde su posición inicial.

Sin embargo, puede superar esto agregando una sola línea de código al Constructor en el archivo Código detrás de la ventana:

MouseDown += delegate { DragMove(); };

O, si prefiere la sintaxis de Lambda:

MouseDown += (sender, args) => DragMove();

Esto hace que toda la ventana se pueda arrastrar. Los controles interactivos presentes en la ventana, como los botones, seguirán funcionando normalmente y no actuarán como controles de arrastre para la ventana.

Holf
fuente
Sigue siendo una mala idea. Elimina toda la barra de título, lo que lo convierte en un enfoque de escopeta, y hace que la caja se vea fea y significa que no hay título / descripción para ello. Hay alternativas mucho mejores.
vapcguy
@vapcguy Elimina toda la barra de título. Es un enfoque de escopeta. ¿Hace que la caja se vea fea? Su opinión. ¿Alternativas mucho mejores? Para ti, tal vez. No para todos. :-)
Holf
-1

Después de mucho buscar la respuesta a esto, elaboré esta solución simple que compartiré aquí con la esperanza de que ayude a otros.

Me puse WindowStyle=0x10000000.

Esto establece los valores WS_VISIBLE (0x10000000)y WS_OVERLAPPED (0x0)para Estilo de ventana. "Superpuesto" es el valor necesario para mostrar la barra de título y el borde de la ventana. Mediante la eliminación de la WS_MINIMIZEBOX (0x20000), WS_MAXIMIZEBOX (0x10000), y WS_SYSMENU (0x80000)los valores de mi valor de estilo, todos los botones de la barra de título se eliminaron, incluyendo el botón Cerrar.

Joe Horr
fuente
En WPF WindowStylehay una enumeración cuyos valores no coinciden con las constantes de la API de Windows; coaccionar el valor para la WindowStyleenumeración no funcionará. Para estar seguro, he comprobado el código fuente .NET en ILSpy; el valor de enumeración se traduce a la API de Windows en la función privada CreateWindowStyle, y si la función encuentra un WindowStylevalor desconocido , simplemente se aplica WindowStyle.None. (La única forma sería usar las propiedades internas _Styley _StyleExusar la reflexión, lo cual recomiendo encarecidamente)
Mike Rosoft,
-2

Use WindowStyle="SingleBorderWindow", esto ocultará el botón máximo y mínimo de la ventana de WPF.

Vishal Nayan
fuente
1
no resuelve el problema ocultando el closebotón
recuerdo de un sueño
-2

Si la necesidad es solo prohibir al usuario que cierre la ventana, esta es una solución simple.

Código XAML: IsCloseButtonEnabled="False"

Filipe Piletti Plucenio
fuente