Comment masquer le bouton de fermeture dans la fenêtre WPF?


204

J'écris une boîte de dialogue modale dans WPF. Comment définir une fenêtre WPF pour ne pas avoir de bouton de fermeture? Je voudrais toujours que sa WindowStatebarre de titre soit normale.

J'ai trouvé ResizeMode,, WindowStateet WindowStyle, mais aucune de ces propriétés ne me permet de masquer le bouton de fermeture mais d'afficher la barre de titre, comme dans les boîtes de dialogue modales.


9
Il s'agit d'une boîte de dialogue de progression exécutant un fil d'arrière-plan qui ne prend pas en charge l'annulation; Je suppose que j'essaie juste de le faire, donc je n'ai pas encore à supporter l'annulation. Vous avez probablement raison, cependant.
Michael Hedgpeth

1
Je déteste également les applications qui essaient de supprimer le chrome des fenêtres. Si je crée une boîte de dialogue de progression, je fais toujours en sorte que le bouton Fermer de la fenêtre ait la même logique que de cliquer sur le bouton Annuler.
Christian Hayter

13
Pour Chris: Imaginons que votre logiciel soit destiné à la vidéosurveillance. Un agent de sécurité pendant la nuit A (c'est son travail) de garder les fenêtres ouvertes ... mais parfois leur travail est ennuyeux et ils veulent surfer sur Internet ou fermer les fenêtres des matrices vidéo pour une raison quelconque, retirer les boutons des fenêtres est la bonne façon pour le faire.
Jean-Marie

7
@ChrisUpchurch, "Pourquoi voulez-vous faire cela? Cela me semble être une conception d'interface utilisateur vraiment moche." - vraiment "conception d'interface utilisateur moche", c'est quand un programme présente une boîte de dialogue avec OK ; Boutons Annuler et Fermer . Pour un utilisateur, l'action de Close peut ne pas être évidente . Est-ce qu'il annule ou soumet ? Le consensus est de ne pas inclure de boutons de fermeture dans les boîtes de dialogue donc il y a ça
MickyD

1
@ Jean-Marie Mais cacher le bouton de fermeture n'empêche pas que cela se produise, cela ne fait que tromper les non informés et les paresseux (à Google). Masquer le bouton de fermeture empêche seulement de cliquer sur ce bouton. Les combinaisons de touches Win et Alt continueront de fonctionner normalement. La manière "correcte" de le faire consiste à créer un compte utilisateur pour les employés, avec une stratégie de groupe qui les empêche d'ouvrir / d'installer tout logiciel autre que ce qui est approuvé. compte administrateur, auquel les superviseurs ont accès, pour gérer toute maintenance.
Digital_Utopia

Réponses:


276

WPF n'a pas de propriété intégrée pour masquer le bouton Fermer de la barre de titre, mais vous pouvez le faire avec quelques lignes de P / Invoke.

Tout d'abord, ajoutez ces déclarations à votre classe Window:

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

Ensuite, mettez ce code dans la fenêtre de Loaded événement de :

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

Et voilà: plus de bouton Fermer. Vous n'aurez pas non plus d'icône de fenêtre sur le côté gauche de la barre de titre, ce qui signifie qu'il n'y a pas de menu système, même lorsque vous cliquez avec le bouton droit sur la barre de titre - ils vont tous ensemble.

Notez que Alt+ F4fermera toujours la fenêtre. Si vous ne souhaitez pas autoriser la fermeture de la fenêtre avant la fin du thread d'arrière-plan, vous pouvez également remplacer OnClosinget définir la valeur Canceltrue, comme l'a suggéré Gabe.


5
Selon les documents que nous devrions utiliser à la SetWindowLongPtrplace.
Jonathan Allen

15
Surtout une note pour soi ... Espace de noms de DllImport -> System.Runtime.InteropServices.DllImport. Espace de noms de WindowInteropHelper -> System.Windows.Interop.WindowInteropHelper
doobop

3
En fait, cette approche masque les trois boutons (Min, Max et Close). Est-il possible de simplement masquer le bouton Fermer?
newman

4
@miliu, non. Vous pouvez le désactiver , mais vous ne pouvez pas le masquer sans masquer également Réduire / Agrandir. Je soupçonne les développeurs Windows de penser que ce serait déroutant si Maximize était à droite où se trouve habituellement Close.
Joe White

3
Mettez WindowStyle = "None" sur votre balise Window dans le fichier XAML.
diegodsp

89

Je viens d'arriver à un problème similaire et la solution de Joe White me semble simple et propre. Je l'ai réutilisé et l'ai défini comme une propriété attachée 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

}

Ensuite, en XAML, vous le définissez comme ceci:

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

64

Définissez la WindowStylepropriété sur Aucun, ce qui masquera la boîte de contrôle ainsi que la barre de titre. Pas besoin d'appels kernal.


20
Eh bien, cela masquera complètement la barre de titre de la fenêtre. Cela signifie que vous n'obtenez pas le titre de la fenêtre et que l'utilisateur ne pourra pas déplacer la fenêtre.
newman

8
Vous pouvez rendre la fenêtre mobile en ajoutant this.DragMove();à l' MouseDownévénement de la fenêtre
paul

1
Pour une boîte de dialogue modale qui devrait être purement informative et obligatoire, comme les progrès de mise à niveau d'une base de données avec un ancien schéma qui a été ouvert, cette solution est parfaite.
The Lonely Coder

1
Je pense que certaines personnes aimeraient avoir une frontière, cependant
pjdupreez

2
Certainement la meilleure solution. Il n'y a aucun problème à ajouter une bordure au panneau ou à implémenter le déplacement.
buks

50

Cela ne supprimera pas le bouton de fermeture, mais cela empêchera quelqu'un de fermer la fenêtre.

Mettez ceci dans votre code derrière le fichier:

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

7
N'oubliez pas que cette opération dans une Windowboîte de dialogue modale interfère avec la Windowdéfinition de sa DialogResultpropriété et peut la rendre inutilisable. stackoverflow.com/questions/898708/cant-set-dialogresult-in-wpf
Sheridan

4
J'obtenais un débordement en utilisant cette méthode, j'ai retiré la base.OnClosing (e) et ensuite cela a fonctionné
jacobsgriffith

8
En tant qu'utilisateur, je détesterais le programmeur qui a mis cela dans son application
UrbanEsc

2
@UrbanEsc J'aurais tendance à convenir que c'est une chose ennuyeuse à faire, mais quand je l'ai fait - et ce n'était qu'une seule fois - c'était une exigence obligatoire, et c'était un mal nécessaire, il y avait un processus très important en cours cela ne pouvait pas être interrompu et l'application ne pouvait pas continuer tant qu'elle n'était pas terminée. Il y avait d'autres façons que cela aurait pu être fait (un thread d'arrière-plan, avec l'interface utilisateur désactivée jusqu'à ce qu'il soit prêt) mais le patron et le client l'ont tous deux aimé de cette façon car cela soulignait la gravité du processus.
flurbius

15

Pour désactiver le bouton de fermeture, vous devez ajouter le code suivant à votre classe Window (le code a été extrait d' ici , modifié et reformaté un peu):

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

Ce code désactive également la fermeture de l'élément dans le menu Système et interdit la fermeture de la boîte de dialogue à l'aide de Alt + F4.

Vous voudrez probablement fermer la fenêtre par programme. L'appel Close()ne fonctionnera pas. Faites quelque chose comme ça:

allowClosing = true;
Close();

Sous Windows 7: ce qui précède désactive également (mais ne supprime pas) l'élément Fermer dans le menu déroulant Système. Le bouton Fermer lui-même est désactivé (semble gris), mais pas supprimé. Cette astuce ne fonctionne pas pour l'élément / bouton Réduire / Agrandir - je soupçonne que WPF les réactive.

3
Il est préférable de désactiver le bouton que de simplement le retirer, il conserve une sensation cohérente tout en permettant à l'utilisateur de savoir qu'une opération importante est en cours d'exécution.
Robert Baker

10

J'essayais la réponse de Viachaslau car j'aime l'idée de ne pas retirer le bouton mais de le désactiver, mais pour une raison quelconque, cela n'a pas toujours fonctionné: le bouton de fermeture était toujours activé mais aucune erreur que ce soit.

Cela a en revanche toujours fonctionné (vérification des erreurs omise):

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

1
Parfait! Ajouté comme Windowméthode d'extension dans mon projet.
Matt Davis

8

La propriété à définir est => 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">

4
Cela masque également les boutons max / min
VoteCoffee

3
Il supprime toute la barre de titre, rendant la boîte laide et sans description. Approche de fusil de chasse et une réponse en double. Downvote.
vapcguy

Il s'agit de la meilleure solution pour les applications de kiosque qui ont toujours besoin de maximiser son application et ne devraient pas permettre aux clients de fermer l'application. So UpVote
Rajon Tanducar

8

J'ajoute simplement mon implémentation de la réponse de Joe White en utilisant le comportement d'interactivité (vous devez référencer System.Windows.Interactivity).

code:

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

usage:

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

2

Laissez l'utilisateur "fermer" la fenêtre mais masquez-la simplement.

Dans l'événement OnClosing de la fenêtre, masquez la fenêtre si elle est déjà visible:

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

Chaque fois que le thread d'arrière-plan doit être exécuté, affichez à nouveau la fenêtre d'interface utilisateur d'arrière-plan:

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

Lorsque vous terminez l'exécution du programme, assurez-vous que toutes les fenêtres sont / peuvent être fermées:

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

1

Voici donc à peu près votre problème. Le bouton de fermeture en haut à droite d'un cadre de fenêtre ne fait pas partie de la fenêtre WPF, mais il appartient à la partie du cadre de fenêtre qui est contrôlée par votre système d'exploitation. Cela signifie que vous devrez utiliser l'interopérabilité Win32 pour le faire.

alternativement, vous pouvez utiliser le noframe et soit fournir votre propre «cadre», soit n'avoir aucun cadre.


1

Ce qui suit concerne la désactivation des boutons Fermer et Agrandir / Réduire, cela ne supprime pas réellement les boutons (mais il supprime les éléments de menu!). Les boutons de la barre de titre sont dessinés dans un état désactivé / grisé. (Je ne suis pas tout à fait prêt à reprendre moi-même toutes les fonctionnalités ^^)

Ceci est légèrement différent de la solution Virgoss en ce qu'elle supprime les éléments de menu (et le séparateur de fin, si nécessaire) au lieu de simplement les désactiver. Elle diffère de la solution Joe Whites car elle ne désactive pas l'intégralité du menu système et donc, dans mon cas, je peux garder le bouton et l'icône Réduire.

Le code suivant prend également en charge la désactivation des boutons Agrandir / Réduire car, contrairement au bouton Fermer, la suppression des entrées du menu n'entraîne pas le système à rendre les boutons «désactivés» même si la suppression des entrées de menu ne désactiver la fonctionnalité des boutons.

Ça marche pour moi. 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);
            }
        }
    }

Utilisation: Cela doit être fait APRÈS l'initialisation de la source. Un bon endroit est d'utiliser l'événement SourceInitialized de la fenêtre:

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
}

Pour désactiver la fonctionnalité Alt + F4, la méthode la plus simple consiste simplement à câbler l'événement Canceling et à définir un indicateur lorsque vous voulez vraiment fermer la fenêtre.


0

Code 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>

devrait marcher

Modifier - pour l'instant, ce fil montre comment cela peut être fait, mais je ne pense pas que Window ait une propriété pour obtenir ce que vous voulez sans perdre la barre de titre normale.

Edit 2 Ce fil montre un moyen de le faire, mais vous devez appliquer votre propre style au menu système et il montre comment vous pouvez le faire.


pour une raison quelconque "devrait fonctionner" vient d'être affiché, mais maintenant mis à jour ont eu lieu
TStamper

3
Je parle de l'état de la fenêtre, qui se trouve dans la barre de titre. Cela ressemble à la modification d'un simple bouton.
Michael Hedgpeth

@TStamper, comment utiliser votre extrait de code? J'utilise un style de fenêtre global (et un modèle).
Shimmy Weitzhandler

@ Shimmy - à laquelle faites-vous référence?
TStamper

0

Essayez d'ajouter un événement de fermeture à la fenêtre. Ajoutez ce code au gestionnaire d'événements.

e.Cancel = true;

Cela empêchera la fermeture de la fenêtre. Cela a le même effet que de masquer le bouton de fermeture.


1
"Cela a le même effet que de cacher le bouton de fermeture." sauf que le bouton est toujours visible et cliquable, c'est-à-dire qu'il est animé et déprime visuellement lorsque vous cliquez dessus - ce qui défie POLA .
rory.ap

0

Utilisez ceci, modifié depuis 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);
        }  

    }
}

0

Cela ne masque pas le bouton mais empêche l'utilisateur d'avancer en fermant la fenêtre.

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

-1

ensemble de propriétés de fenêtre goto

window style = none;

vous n'obtiendrez pas de boutons de fermeture ...


Downvote. C'est en fait WindowStyle = "None"- regardez votre syntaxe. Pour un autre, c'est une approche au fusil de chasse qui supprime également la barre de titre, rendant la boîte moche et sans titre, alors qu'il existe de bien meilleures façons de gérer cela (comme en témoignent les autres réponses), et est une réponse en double.
vapcguy

-1

Comme indiqué dans d'autres réponses, vous pouvez utiliser WindowStyle="None"pour supprimer complètement la barre de titre.

Et, comme indiqué dans les commentaires de ces autres réponses, cela empêche la fenêtre d'être déplaçable, il est donc difficile de la déplacer de sa position initiale.

Cependant, vous pouvez résoudre ce problème en ajoutant une seule ligne de code au constructeur dans le fichier Code Behind de la fenêtre:

MouseDown += delegate { DragMove(); };

Ou, si vous préférez la syntaxe Lambda:

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

Cela rend la fenêtre entière glissable. Tous les contrôles interactifs présents dans la fenêtre, tels que les boutons, fonctionneront toujours normalement et n'agiront pas comme des poignées de déplacement pour la fenêtre.


Encore une mauvaise idée. Il supprime toute la barre de titre, ce qui en fait une approche de fusil de chasse, et rend la boîte moche et signifie qu'il n'y a pas de titre / description pour cela. Il existe de bien meilleures alternatives.
vapcguy

@vapcguy Il supprime toute la barre de titre. C'est une approche au fusil de chasse. Rend la boîte moche? Votre opinion. De bien meilleures alternatives? Pour vous, peut-être. Pas pour tout le monde. :-)
Holf

-1

Après avoir longuement cherché la réponse, j'ai élaboré cette solution simple que je partagerai ici dans l'espoir qu'elle aide les autres.

Je mets WindowStyle=0x10000000.

Ceci définit les valeurs WS_VISIBLE (0x10000000)et WS_OVERLAPPED (0x0)pour le style de fenêtre. "Overlapped" est la valeur nécessaire pour afficher la barre de titre et la bordure de la fenêtre. En supprimant la WS_MINIMIZEBOX (0x20000), WS_MAXIMIZEBOX (0x10000), et les WS_SYSMENU (0x80000)valeurs de ma valeur de style, tous les boutons de la barre de titre ont été supprimés, y compris le bouton Fermer.


Dans WPF WindowStyleest une énumération dont les valeurs ne correspondent pas aux constantes de l'API Windows; contraindre la valeur à l' WindowStyleénumération ne fonctionnera pas. Pour être sûr, j'ai vérifié le code source .NET dans ILSpy; la valeur enum est traduite en API Windows dans la fonction privée CreateWindowStyle, et si la fonction rencontre une WindowStylevaleur inconnue , elle s'applique simplement WindowStyle.None. (La seule façon serait d'utiliser les propriétés internes _Styleet d' _StyleExutiliser la réflexion, ce que je déconseille fortement.)
Mike Rosoft

-2

Utilisez WindowStyle="SingleBorderWindow", cela masquera le bouton max et min de la fenêtre WPF.


1
ne résout pas le problème en cachant le closebouton
souvenir d'un rêve

-2

Si le besoin est uniquement d'interdire à l'utilisateur de fermer la fenêtre, c'est une solution simple.

Code XAML: IsCloseButtonEnabled="False"

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.