Como ocultar o botão Fechar na janela do WPF?


204

Estou escrevendo uma caixa de diálogo modal no WPF. Como faço para definir uma janela WPF para não ter um botão Fechar? Eu ainda gostaria por suaWindowState que tivesse uma barra de título normal.

Eu encontrei ResizeMode, WindowStatee WindowStyle, mas nenhuma dessas propriedades permitir-me a esconder o botão de fechar, mas mostrar a barra de título, como em diálogos modais.


9
É uma caixa de diálogo de progresso executando um encadeamento em segundo plano que não suporta cancelamento; Acho que estou apenas tentando fazê-lo, para que eu ainda não precise apoiar o cancelamento. Você provavelmente está certo, no entanto.
Michael Hedgpeth

1
Eu também odeio aplicativos tentando remover o chrome da janela. Se eu criar uma caixa de diálogo de progresso, sempre faço o botão Fechar da janela fazer a mesma lógica que clicar no botão Cancelar real.
Christian Hayter

13
Para Chris: Vamos imaginar que seu software é para vigilância por vídeo. Um agente de segurança durante a noite tem (esse é o trabalho dele) manter as janelas abertas ... mas às vezes o trabalho delas é chato e eles querem navegar na Internet ou fechar as janelas das Video Matrices por qualquer motivo, remover os botões da janela é a maneira correta para fazer isso.
Jean-Marie

7
@ChrisUpchurch, "Por que você quer fazer isso? Parece-me um péssimo design de interface do usuário." - realmente "péssimo design de interface do usuário" é quando um programa apresenta uma caixa de diálogo com OK ; Botões Cancelar e Fechar . Para um usuário, pode não ser óbvio o que o Close faz. Ele cancela ou envia ? O consenso é não incluir botões de fechar em diálogos então não é que
MickyD

1
@ Jean-Marie Mas ocultar o botão fechar não impede que isso aconteça, apenas engana os desinformados e os preguiçosos (para o Google). Ocultar o botão Fechar apenas evita clicar nesse botão. As combinações de teclas Win e Alt Key ainda funcionarão normalmente. A maneira "correta" de fazer isso é criar uma conta de usuário para os trabalhadores, com uma política de grupo que os impeça de abrir / instalar qualquer software que não seja o aprovado. conta de administrador, à qual os supervisores têm acesso, para lidar com qualquer manutenção.
Digital_Utopia

Respostas:


275

O WPF não possui uma propriedade interna para ocultar o botão Fechar da barra de título, mas você pode fazer isso com algumas linhas de P / Invoke.

Primeiro, adicione estas declarações à sua 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);

Em seguida, coloque este código no Loadedevento da janela :

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

E pronto: não há mais botão Fechar. Você também não terá um ícone de janela no lado esquerdo da barra de título, o que significa que não há menu do sistema, mesmo quando você clica com o botão direito do mouse na barra de título - todos eles caminham juntos.

Observe que Alt+ F4ainda fechará a janela. Se você não quiser permitir que a janela seja fechada antes que o encadeamento em segundo plano seja concluído, você também poderá substituir OnClosinge definir Cancelcomo true, como sugeriu Gabe.


5
De acordo com os documentos que deveríamos usar SetWindowLongPtr.
Jonathan Allen

15
Principalmente uma observação a ... Espaço para nome de DllImport -> System.Runtime.InteropServices.DllImport. Namespace de WindowInteropHelper -> System.Windows.Interop.WindowInteropHelper
doobop

3
Na verdade, essa abordagem oculta os três botões (Min, Max e Close). É possível ocultar apenas o botão Fechar?
newman

4
@miliu, não. Você pode desativá-lo , mas não pode ocultá-lo sem ocultar Minimizar / Maximizar também. Eu suspeito que os desenvolvedores do Windows pensaram que seria confuso se o Maximize estivesse à direita, onde Close costuma estar.
Joe White

3
Coloque WindowStyle = "None" na sua tag Window no arquivo XAML.
precisa saber é o seguinte

88

Acabei de chegar a um problema semelhante e a solução de Joe White me parece simples e limpa. Eu o reutilizei e o defini como uma propriedade anexada do 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

}

Então, no XAML, você apenas o define assim:

<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

Defina a WindowStylepropriedade como None, que ocultará a caixa de controle junto com a barra de título. Não há necessidade de chamadas kernais.


20
Bem, isso ocultará completamente a barra de título da janela. Isso significa que você não obtém o título da janela e o usuário não poderá mover a janela.
Newman

8
Você pode fazer o móvel janela adicionando this.DragMove();à janela MouseDownevento
paul

1
Para um diálogo modal que deve ser puramente informativo e obrigatório, como o progresso na atualização de um banco de dados com um esquema antigo que foi aberto, essa solução é perfeita.
The Lonely Coder

1
Eu acho que algumas pessoas gostariam de ter uma borda, embora
pjdupreez

2
Definitivamente a melhor solução. Não há problema em adicionar borda ao painel ou implementar a movimentação.
buks

50

Isso não se livra do botão Fechar, mas impede que alguém feche a janela.

Coloque isso no seu código por trás do arquivo:

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

7
Esteja ciente de que fazer isso de maneira Windowconfigurada como um diálogo modal interferirá na Windowconfiguração de sua DialogResultpropriedade e poderá torná-lo inutilizável. stackoverflow.com/questions/898708/cant-set-dialogresult-in-wpf
Sheridan

4
Eu estava ficando um estouro usando este método, eu tirei base.OnClosing (e) e, em seguida, ele trabalhou
jacobsgriffith

8
Como um usuário Eu odiaria o programador que colocar isso em sua aplicação
UrbanEsc

2
@UrbanEsc, eu tenderia a concordar que isso é uma coisa chata de se fazer, mas quando eu fiz isso - e foi a única vez - era um requisito obrigatório e um mal necessário, havia algum processo muito importante em andamento isso não pôde ser interrompido e o aplicativo não pôde continuar até que estivesse pronto. Havia outras maneiras de fazer isso (um encadeamento em segundo plano, com a interface do usuário desativada até ficar pronta), mas o chefe e o cliente gostaram dessa maneira porque enfatizavam a gravidade do processo.
Flurbius

15

Para desativar o botão Fechar, você deve adicionar o seguinte código à sua classe Window (o código foi retirado daqui , editado e reformatado um pouco):

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

Esse código também desativa o item de fechamento no menu Sistema e não permite fechar a caixa de diálogo usando Alt + F4.

Você provavelmente desejará fechar a janela programaticamente. Apenas ligar Close()não funcionará. Faça algo parecido com isto:

allowClosing = true;
Close();

No Windows 7: O item acima também desabilita (mas não remove) o item Fechar no menu suspenso Sistema. O botão Fechar em si está desativado (parece cinza), mas não é removido. Esse truque não funciona para o item / botão Minimizar / Maximizar - suspeito que o WPF os reative.

3
Desabilitar o botão é melhor do que apenas removê-los, ele mantém uma sensação consistente ao permitir que o usuário saiba que uma operação importante está em execução.
Robert Baker

10

Eu estava tentando a resposta de Viachaslau, já que gosto da idéia de não remover o botão, mas desativá-lo, mas por algum motivo nem sempre funcionava: o botão Fechar ainda estava ativado, mas sem erros.

Por outro lado, isso sempre funcionou (verificação de erro omitida):

[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
Perfeito! Adicionado como um Windowmétodo de extensão no meu projeto.
Matt Davis

8

A propriedade a ser configurada é => 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
Isso também oculta os botões max / min
VoteCoffee

3
Ele remove a barra de título inteira, tornando a caixa feia e sem uma descrição. Abordagem de espingarda e uma resposta duplicada. Voto negativo.
precisa saber é o seguinte

Esta é a melhor solução para aplicativos de quiosque, que sempre precisa que seu aplicativo seja maximizado e não deve permitir que os clientes fechem o aplicativo. So UpVote
Rajon Tanducar

8

Acabei de adicionar minha implementação da resposta de Joe White usando o Interactivity Behavior (você precisa fazer referência ao 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>

2

Deixe o usuário "fechar" a janela, mas realmente apenas a oculte.

No evento OnClosing da janela, oculte a janela se já estiver visível:

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

Cada vez que o encadeamento em segundo plano for executado, mostre novamente a janela da interface do usuário em segundo plano:

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

Ao encerrar a execução do programa, verifique se todas as janelas estão / podem ser fechadas:

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

Então, aqui está o seu problema. O botão Fechar no canto superior direito de um quadro de janela não faz parte da janela WPF, mas pertence à parte do quadro de janela que é controlada pelo seu sistema operacional. Isso significa que você precisará usar a interoperabilidade do Win32 para fazer isso.

alternativamente, você pode usar o noframe e fornecer seu próprio "quadro" ou não ter nenhum quadro.


1

A seguir, é sobre como desativar os botões Fechar e Maximizar / Minimizar, não removem os botões (mas removem os itens de menu!). Os botões na barra de título são desenhados no estado desativado / acinzentado. (Não estou pronto para assumir todas as funcionalidades ^ ^)

Isso é um pouco diferente da solução Virgoss, pois remove os itens de menu (e o separador à direita, se necessário), em vez de apenas desativá-los. Difere da solução de Joe Whites, pois não desativa todo o menu do sistema e, portanto, no meu caso, posso manter o botão e o ícone Minimizar.

O código de acompanhamento também suporta a desativação do Maximizar / Minimizar botões como, ao contrário do botão Fechar, removendo as entradas do menu não causar o sistema para tornar os botões de "deficiente", apesar de remover as entradas do menu faz desactivar a funcionalidade dos botões.

Funciona para mim. 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: Isso deve ser feito APÓS a fonte ser inicializada. Um bom lugar é usar o evento SourceInitialized da janela:

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 desabilitar a funcionalidade Alt + F4, o método fácil é apenas conectar o evento Canceling e usar um sinalizador para quando você realmente deseja fechar a janela.


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>

Deveria trabalhar

Editar - por um instante, este Tópico mostra como isso pode ser feito, mas não creio que o Windows tenha uma propriedade para obter o que deseja sem perder a barra de título normal.

Editar 2 Este tópico mostra uma maneira de fazer isso, mas você deve aplicar seu próprio estilo ao menu do sistema e mostra como você pode fazer isso.


por alguma razão "deve funcionar" só foi exibido, mas agora atualizado ter ocorrido
TStamper

3
Estou falando do estado da janela, que está na barra de título. Parece editar um botão simples.
Michael Hedgpeth

@TStamper, como uso seu snippet? Estou usando um estilo global de janela (e modelo).
Shimmy Weitzhandler

@ Shimmy- qual você está se referindo?
TSTamper

0

Tente adicionar um evento de fechamento à janela. Adicione esse código ao manipulador de eventos.

e.Cancel = true;

Isso impedirá que a janela se feche. Isso tem o mesmo efeito que ocultar o botão Fechar.


1
"Isso tem o mesmo efeito que ocultar o botão" Fechar "." exceto que o botão ainda está visível e clicável, ou seja, é animado e pressionado visualmente quando você clica nele - o que desafia POLA .
Rog.ap

0

Use isso, modificado em 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

Isso não oculta o botão, mas impede o usuário de avançar fechando a janela.

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

-1

Ir para o conjunto de propriedades da janela

window style = none;

você não consegue fechar botões ...


Voto negativo. Na verdade, WindowStyle = "None"observe sua sintaxe. Por outro lado, é uma abordagem de espingarda que também remove a barra de título, tornando a caixa feia e sem título, quando há muitas maneiras muito melhores de lidar com isso (como evidenciado pelas outras respostas) e é uma resposta duplicada.
vapcguy

-1

Conforme indicado em outras respostas, você pode usar WindowStyle="None"para remover completamente a barra de título.

E, conforme declarado nos comentários dessas outras respostas, isso evita que a janela seja arrastável, tornando difícil movê-la de sua posição inicial.

No entanto, você pode superar isso adicionando uma única linha de código ao Construtor no arquivo Code Behind da janela:

MouseDown += delegate { DragMove(); };

Ou, se você preferir a sintaxe Lambda:

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

Isso torna toda a janela arrastável. Quaisquer controles interativos presentes na janela, como botões, ainda funcionarão normalmente e não funcionarão como alças de arrasto para a janela.


Ainda é uma má ideia. Ele remove toda a barra de título, tornando-a uma abordagem de espingarda, e torna a caixa feia e significa que não há título / descrição para ela. Existem alternativas muito melhores.
vapcguy

@vapcguy Remove a barra de título inteira. É uma abordagem de espingarda. Faz a caixa parecer feia? Sua opinião. Alternativas muito melhores? Para você, talvez. Não para todos. :-)
Holf

-1

Depois de muito procurar a resposta, resolvi esta solução simples que vou compartilhar aqui, na esperança de ajudar outras pessoas.

Eu ajustei WindowStyle=0x10000000.

Isso define os valores WS_VISIBLE (0x10000000)e WS_OVERLAPPED (0x0)para o estilo da janela. "Sobreposto" é o valor necessário para mostrar a barra de título e a borda da janela. Removendo o WS_MINIMIZEBOX (0x20000), WS_MAXIMIZEBOX (0x10000), e WS_SYSMENU (0x80000)os valores do meu valor estilo, todos os botões da barra de título foram removidos, incluindo o botão Fechar.


No WPF, WindowStylehá uma enumeração cujos valores não correspondem às constantes da API do Windows; coagir o valor à WindowStyleenumeração não funcionará. Para ter certeza, verifiquei o código-fonte .NET no ILSpy; o valor da enumeração é convertido para a API do Windows na função privada CreateWindowStylee, se a função encontrar um WindowStylevalor desconhecido , ela simplesmente será aplicada WindowStyle.None. (A única maneira seria usar as propriedades internas _Stylee _StyleExusando a reflexão, o que eu recomendo fortemente contra.)
Mike Rosoft


-2

Se a necessidade é apenas proibir o usuário de fechar a janela, esta é uma solução simples.

Código XAML: IsCloseButtonEnabled="False"

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.