Come nascondere il pulsante di chiusura nella finestra di WPF?


204

Sto scrivendo una finestra di dialogo modale in WPF. Come posso impostare una finestra WPF per non avere un pulsante di chiusura? Mi piacerebbe comunque che WindowStateavesse una normale barra del titolo.

Ho trovato ResizeMode, WindowStatee WindowStyle, ma nessuna di queste proprietà mi permette di nascondere il pulsante di chiusura ma mostra la barra del titolo, come nelle finestre di dialogo modali.


9
È una finestra di avanzamento che esegue un thread in background che non supporta l'annullamento; Immagino che sto solo provando a farlo, quindi non devo supportare l'annullamento (ancora). Probabilmente hai ragione, però.
Michael Hedgpeth,

1
Odio anche le app che cercano di rimuovere la finestra di Chrome. Se faccio una finestra di avanzamento, faccio sempre che il pulsante Chiudi della finestra faccia la stessa logica del clic sul pulsante Annulla effettivo.
Christian Hayter,

13
Per Chris: immaginiamo che il tuo software sia per la videosorveglianza. Un agente di sicurezza durante la notte HA (è il suo lavoro) tenere le finestre aperte ... ma a volte il loro lavoro è noioso e vogliono navigare in Internet o chiudere le finestre delle Matrici video per qualsiasi motivo, rimuovere i pulsanti di Windows è il modo corretto per farlo.
Jean-Marie,

7
@ChrisUpchurch, "Perché vuoi farlo? Mi sembra una progettazione dell'interfaccia utente davvero scadente." - La "progettazione dell'interfaccia utente davvero scadente" è quando un programma presenta una finestra di dialogo con OK ; Pulsanti Annulla e Chiudi . Per un utente, potrebbe non essere ovvio cosa fa Close . Ha annullare o presentare ? Il consenso non è quello di includere pulsanti di chiusura nelle finestre di dialogo, quindi c'è questo
MickyD

1
@ Jean-Marie Ma nascondere il pulsante di chiusura non impedisce che ciò accada, ingannare solo i non informati e pigri (a Google). Nascondere il pulsante di chiusura impedisce solo di fare clic su quel pulsante. Le combinazioni Win Key e Alt Key funzioneranno comunque normalmente Il modo "corretto" per farlo è creare un account utente per i lavoratori, con una politica di gruppo che impedisce loro di aprire / installare qualsiasi software diverso da quello approvato. account amministratore, a cui i supervisori hanno accesso, per gestire qualsiasi tipo di manutenzione.
Digital_Utopia,

Risposte:


275

WPF non ha una proprietà integrata per nascondere il pulsante Chiudi della barra del titolo, ma puoi farlo con poche righe di P / Invoke.

Per prima cosa, aggiungi queste dichiarazioni alla tua 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);

Quindi inserisci questo codice Loadednell'evento di Windows :

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

Ed ecco fatto: niente più pulsante Chiudi. Inoltre non avrai l'icona di una finestra sul lato sinistro della barra del titolo, il che significa che nessun menu di sistema, anche quando fai clic con il tasto destro del mouse sulla barra del titolo, vanno tutti insieme.

Nota che Alt+ F4chiuderà comunque la finestra. Se non vuoi consentire la chiusura della finestra prima che il thread in background sia terminato, puoi anche eseguire l'override OnClosinge impostare Cancelsu true, come suggerito da Gabe.


5
Secondo i documenti dovremmo SetWindowLongPtrinvece utilizzare .
Jonathan Allen,

15
Principalmente una nota per sé ... Spazio dei nomi di DllImport -> System.Runtime.InteropServices.DllImport. Spazio dei nomi di WindowInteropHelper -> System.Windows.Interop.WindowInteropHelper
doobop

3
In realtà, questo approccio nasconde tutti e tre i pulsanti (Min, Max e Close). È possibile nascondere il pulsante Chiudi?
Newman,

4
@miliu, no. Puoi disabilitarlo , ma non puoi nasconderlo senza nascondere anche Riduci / Ingrandisci. Ho il sospetto che gli sviluppatori di Windows pensassero che sarebbe stato confuso se Maximize fosse sulla destra dove di solito si trova Close.
Joe White,

3
Put WindowStyle = "None" sul tag Window nel file XAML.
Diegodsp,

88

Ho appena avuto un problema simile e la soluzione di Joe White mi sembra semplice e pulita. L'ho riutilizzato e definito come una proprietà collegata di 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

}

Quindi in XAML è sufficiente impostarlo in questo modo:

<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

Impostare la WindowStyleproprietà su Nessuno per nascondere la casella di controllo insieme alla barra del titolo. Non c'è bisogno di chiamate kernal.


20
Bene, questo nasconderà completamente la barra del titolo della finestra. Ciò significa che non si ottiene il titolo della finestra e l'utente non sarà in grado di spostare la finestra.
Newman,

8
Puoi rendere mobile la finestra aggiungendola all'evento this.DragMove();della finestraMouseDown
paul

1
Per una finestra di dialogo modale che dovrebbe essere puramente informativa e obbligatoria, come i progressi nell'aggiornamento di un database con un vecchio schema che è stato aperto, questa soluzione è perfetta.
The Lonely Coder,

1
Penso che alcune persone vorrebbero avere un confine, però
pjdupreez

2
Sicuramente la soluzione migliore. Non ci sono problemi con l'aggiunta di bordi al pannello o l'implementazione dello spostamento.
acquista il

50

Questo non eliminerà il pulsante di chiusura, ma impedirà a qualcuno di chiudere la finestra.

Inserisci questo nel tuo codice dietro il file:

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

7
Essere consapevoli del fatto che farlo in un Windowche è impostato come una finestra di dialogo modale interferirà con l' Windowimpostazione della sua DialogResultproprietà e potrebbe renderlo inutilizzabile. stackoverflow.com/questions/898708/cant-set-dialogresult-in-wpf
Sheridan

4
Stavo ottenendo un overflow usando questo metodo, ho tolto base.OnClosing (e) e poi ha funzionato
jacobsgriffith

8
Come utente odio il programmatore che lo ha inserito nella loro applicazione
UrbanEsc,

2
@UrbanEsc Tenderei ad ammettere che è una cosa fastidiosa da fare, ma quando l'ho fatto - ed era solo una volta - era un requisito obbligatorio, ed era un male necessario, c'era un processo molto importante in corso che non poteva essere interrotto e l'app non poteva procedere fino a quando non veniva eseguita. C'erano altri modi in cui avrebbe potuto essere fatto (un thread in background, con l'interfaccia utente disabilitata fino a quando non era pronto), ma al capo e al client è piaciuto in questo modo perché ha enfatizzato la gravità del processo.
flurbius,

15

Per disabilitare il pulsante Chiudi dovresti aggiungere il seguente codice alla tua classe Window (il codice è stato preso da qui , modificato e riformattato un po '):

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

Questo codice disabilita anche la voce Chiudi nel menu Sistema e non consente di chiudere la finestra di dialogo usando Alt + F4.

Probabilmente vorrai chiudere la finestra a livello di codice. La sola chiamata Close()non funzionerà. Fai qualcosa del genere:

allowClosing = true;
Close();

In Windows 7: quanto sopra disabilita anche (ma non rimuove) la voce Chiudi nel menu a discesa Sistema. Il pulsante Chiudi stesso è disabilitato (sembra grigio), ma non rimosso. Questo trucco non funziona per la voce Riduci / Ingrandisci oggetto / pulsante - Sospetto che WPF li riattivi.

3
Disabilitare il pulsante è meglio che rimuoverli, mantiene una sensazione coerente e fa sapere all'utente che è in esecuzione un'operazione importante.
Robert Baker,

10

Stavo provando la risposta di Viachaslau poiché mi piace l'idea di non rimuovere il pulsante ma di disabilitarlo, ma per qualche motivo non ha sempre funzionato: il pulsante di chiusura era ancora abilitato ma nessun errore.

Questo d'altra parte ha sempre funzionato (controllo degli errori omesso):

[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
Perfetto! Aggiunto come Windowmetodo di estensione nel mio progetto.
Matt Davis,

8

La proprietà da impostare è => 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
Questo nasconde anche i pulsanti max / min
VoteCoffee

3
Rimuove l'intera barra del titolo, rendendo la casella brutta e senza una descrizione. Approccio di fucile da caccia e una risposta duplicata. Downvote.
vapcguy,

Questa è la soluzione migliore per le applicazioni kiosk che necessitano sempre di massimizzare la sua applicazione e non dovrebbe consentire ai clienti di chiudere l'app. So UpVote
Rajon Tanducar

8

Ho appena aggiunto la mia implementazione della risposta di Joe White usando Interactivity Behavior (è necessario fare riferimento a System.Windows.Interactivity).

codice:

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

utilizzo:

<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

Lascia che l'utente "chiuda" la finestra ma la nasconda davvero.

Nell'evento OnClosing della finestra, nascondi la finestra se già visibile:

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

Ogni volta che il thread in background deve essere eseguito, mostra nuovamente la finestra dell'interfaccia utente in background:

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

Quando si termina l'esecuzione del programma, assicurarsi che tutte le finestre siano / possano essere chiuse:

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

Quindi, praticamente qui è il tuo problema. Il pulsante di chiusura in alto a destra di un frame della finestra non fa parte della finestra di WPF, ma appartiene alla parte del frame della finestra che è controllata dal sistema operativo. Questo significa che dovrai usare l'interoperabilità di Win32 per farlo.

in alternativa, puoi usare il noframe e fornire il tuo "frame" o non avere alcun frame.


1

Quanto segue riguarda la disabilitazione dei pulsanti Chiudi e Massimizza / Riduci a icona, in realtà non rimuove i pulsanti (ma rimuove le voci di menu!). I pulsanti sulla barra del titolo sono disegnati in uno stato disabilitato / in grigio. (Non sono del tutto pronto per assumere da solo tutte le funzionalità ^^)

Questo è leggermente diverso dalla soluzione Virgoss in quanto rimuove le voci di menu (e il separatore finale, se necessario) invece di disabilitarle. Si differenzia dalla soluzione di Joe Whites in quanto non disabilita l'intero menu di sistema e quindi, nel mio caso, posso mantenere il pulsante e l'icona Riduci a icona.

Il codice follow supporta anche disabilitando l'Ingrandisci / pulsanti come, a differenza del pulsante Chiudi, rimuovere le voci dal menu non causa il sistema per rendere i pulsanti "disabile", anche se la rimozione delle voci del menu Minimizzare fa disattivare la funzionalità dei pulsanti.

Per me funziona. 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: questo deve essere fatto DOPO che la fonte è stata inizializzata. Un buon posto è usare l'evento SourceInitialized della finestra:

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
}

Per disabilitare la funzionalità Alt + F4, il metodo semplice consiste semplicemente nel collegare l'evento Annullamento e utilizzare impostare un flag per quando si desidera veramente chiudere la finestra.


0

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

dovrebbe funzionare

Modifica - per il tuo istante questa discussione mostra come farlo ma non credo che Window abbia una proprietà per ottenere ciò che vuoi senza perdere la normale barra del titolo.

Modifica 2 Questo thread mostra un modo per farlo, ma è necessario applicare il proprio stile al menu di sistema e mostra un modo per farlo.


per qualche motivo "dovrebbe funzionare" è stato appena visualizzato, ma ora si sono verificati aggiornamenti
TStamper,

3
Sto parlando dello stato di Window, che si trova nella barra del titolo. Questo sembra modificare un semplice pulsante.
Michael Hedgpeth,

@TStamper, come posso usare il tuo frammento? Sto usando uno stile Window globale (e un modello).
Shimmy Weitzhandler,

@ Shimmy- a quale ti riferisci?
TStamper

0

Prova ad aggiungere un evento di chiusura alla finestra. Aggiungi questo codice al gestore eventi.

e.Cancel = true;

Ciò impedirà la chiusura della finestra. Questo ha lo stesso effetto di nascondere il pulsante di chiusura.


1
"Questo ha lo stesso effetto di nascondere il pulsante di chiusura." tranne per il fatto che il pulsante è ancora visibile e cliccabile, ovvero è animato e si deprime visivamente quando si fa clic su di esso, il che sfida POLA .
rory.ap,

0

Usa questo, modificato da 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

Questo non nasconde il pulsante ma impedirà all'utente di andare avanti chiudendo la finestra.

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

-1

vai alle proprietà della finestra impostate

window style = none;

non ti avvicinerai ai pulsanti ...


Downvote. In realtà è WindowStyle = "None"- guarda la tua sintassi. Per un altro, è un approccio con un fucile da caccia che rimuove anche la barra del titolo, rendendo la scatola brutta e priva di un titolo, quando ci sono molti modi molto migliori per gestirlo (come evidenziato dalle altre risposte), ed è una risposta duplicata.
vapcguy,

-1

Come indicato in altre risposte, è possibile utilizzare WindowStyle="None"per rimuovere del tutto la barra del titolo.

E, come indicato nei commenti a quelle altre risposte, questo impedisce alla finestra di essere trascinabile, quindi è difficile spostarlo dalla sua posizione iniziale.

Tuttavia, puoi superare ciò aggiungendo una singola riga di codice al costruttore nel file Codice dietro la finestra:

MouseDown += delegate { DragMove(); };

Oppure, se preferisci la sintassi Lambda:

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

Questo rende l'intera finestra trascinabile. Tutti i controlli interattivi presenti nella finestra, come i pulsanti, funzioneranno comunque normalmente e non fungeranno da maniglie di trascinamento per la finestra.


Ancora una cattiva idea. Rimuove l'intera barra del titolo, rendendola un approccio da fucile e rende la scatola brutta e significa che non c'è titolo / descrizione per essa. Ci sono alternative molto migliori.
vapcguy,

@vapcguy Rimuove l'intera barra del titolo. È un approccio con il fucile da caccia. La scatola sembra brutta? La tua opinione. Alternative molto migliori? Per te, forse. Non per tutti. :-)
Holf

-1

Dopo aver cercato molto la risposta a questo, ho elaborato questa semplice soluzione che condividerò qui nella speranza che aiuti gli altri.

ho impostato WindowStyle=0x10000000 .

Questo imposta i valori WS_VISIBLE (0x10000000)e WS_OVERLAPPED (0x0)per Stile finestra. "Sovrapposto" è il valore necessario per mostrare la barra del titolo e il bordo della finestra. Rimuovendo il WS_MINIMIZEBOX (0x20000), WS_MAXIMIZEBOX (0x10000), ed WS_SYSMENU (0x80000)i valori del mio stile valore, tutti i pulsanti della barra del titolo sono stati rimossi, compreso il pulsante Chiudi.


In WPF WindowStyleè presente un elenco i cui valori non corrispondono alle costanti dell'API di Windows; forzare il valore WindowStyledell'enumerazione non funzionerà. A dire il vero, ho controllato il codice sorgente .NET in ILSpy; il valore enum viene tradotto nell'API di Windows nella funzione privata CreateWindowStylee se la funzione rileva un WindowStylevalore sconosciuto , si applica semplicemente WindowStyle.None. (L'unico modo sarebbe usare le proprietà interne _Stylee _StyleExusare la riflessione, che consiglio vivamente contro.)
Mike Rosoft,

-2

Usa WindowStyle="SingleBorderWindow", questo nasconderà i pulsanti max e min dalla finestra di WPF.


1
non risolve il problema nascondendo il closepulsante
ricordo di un sogno

-2

Se la necessità è solo quella di vietare all'utente di chiudere la finestra, questa è una soluzione semplice.

Codice XAML: IsCloseButtonEnabled="False"

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.