如何在WPF窗口中隐藏关闭按钮?


204

我正在WPF中编写模式对话框。如何将WPF窗口设置为没有关闭按钮?我仍然希望它WindowState有一个普通的标题栏。

我发现了ResizeModeWindowStateWindowStyle,但是这些属性都不能让我隐藏关闭按钮,而是显示标题栏,如模式对话框中一样。


9
这是一个运行对话框,运行一个不支持取消的后台线程。我想我只是想做到这一点,所以我不必支持取消(还)。不过,您可能是对的。
Michael Hedgpeth,2009年

1
我也讨厌试图删除窗口镶边的应用程序。如果创建进度对话框,则始终使窗口的“关闭”按钮具有与单击实际“取消”按钮相同的逻辑。
Christian Hayter

13
对于克里斯:让我们想象一下您的软件是用于视频监控的。夜间的安全代理有(保持他的职责)保持窗户打开……但是有时他们的工作很无聊,并且出于某种原因他们想上网或关闭视频矩阵窗口,删除窗口按钮是正确的方法去做吧。
Jean-Marie

7
@ChrisUpchurch,“为什么要这样做?它让我感到非常糟糕的UI设计。” -真正的“糟糕的UI设计”是程序显示确定对话框时;取消关闭按钮。对于用户而言,Close所做的可能并不明显。是否取消提交共识是不要在对话框中包含关闭按钮,所以有
MickyD 2014年

1
@ Jean-Marie但是隐藏关闭按钮并不能阻止这种情况的发生,它只会愚弄那些不了解信息和懒惰的人(对Google)。隐藏关闭按钮只能防止单击该按钮。Win键和alt键组合仍然可以正常使用。“正确”的方法是为工作人员创建用户帐户,并使用组策略阻止他们打开/安装未经批准的任何软件。管理员有权访问的管理员帐户来处理任何维护。
Digital_Utopia 2015年

Answers:


275

WPF没有内置属性来隐藏标题栏的“关闭”按钮,但是您可以使用几行P / Invoke来实现。

首先,将这些声明添加到您的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);

然后将以下代码放入Window的Loaded事件中:

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

然后您就可以了:不再需要关闭按钮。标题栏的左侧也没有窗口图标,这意味着没有系统菜单,即使您右键单击标题栏也是如此。

请注意,Alt+ F4仍将关闭窗口。如果您不希望在完成后台线程之前关闭窗口,则也可以按照Gabe的建议重写OnClosing并设置Cancel为true。


5
根据文档,我们应该SetWindowLongPtr改用。
乔纳森·艾伦,2010年

15
主要是对自己的说明... DllImport的命名空间-> System.Runtime.InteropServices.DllImport。WindowInteropHelper的命名空间-> System.Windows.Interop.WindowInteropHelper
doobop 2010年

3
实际上,这种方法隐藏了所有三个按钮(最小,最大和关闭)。是否可以仅隐藏“关闭”按钮?
纽曼

4
@miliu,不。您可以禁用它,但也不能隐藏最小化/最大化来隐藏它。我怀疑Windows开发人员认为,如果最大化通常位于“关闭”的正确位置,那会造成混乱。
乔·怀特

3
在XAML文件的Window标记上放置WindowStyle =“ None”。
diegodsp

88

我只是遇到了类似的问题,在我看来,乔·怀特的解决方案简单明了。我重用了它并将其定义为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

}

然后,在XAML中,您可以这样设置:

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

62

WindowStyle属性设置为“无”将隐藏控件框以及标题栏。无需进行核心通话。


20
好吧,这将完全隐藏窗口标题栏。这意味着您没有窗口标题,并且用户将无法移动窗口。
纽曼

6
您可以通过添加this.DragMove();窗口MouseDown事件来使窗口可移动
paul 2014年

1
对于应该纯粹是信息性和强制性的模式对话框,例如使用已打开的旧模式升级数据库的进度,此解决方案是完美的。
孤独的编码者2014年

1
我认为有些人希望有边界
-pjdupreez

2
绝对是最佳解决方案。在面板上添加边框或实现移动没有问题。
buks

50

这不会摆脱关闭按钮,但会阻止某人关闭窗口。

将其放在文件后面的代码中:

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

7
请注意,在Window设置为模式对话框的窗口中执行此操作会干扰WindowDialogResult属性的设置,并可能使其无法使用。stackoverflow.com/questions/898708/cant-set-dialogresult-in-wpf
Sheridan

4
使用此方法时发生溢出,我取出了base.OnClosing(e),然后开始工作
jacobsgriffith 2014年

8
作为用户,我会讨厌将其放入应用程序中的程序员
UrbanEsc 2015年

2
@UrbanEsc我倾向于同意这样做是一件烦人的事,但是当我这样做(只有一次)时,这是强制性的要求,而且是必要的恶行,正在进行一些非常重要的过程无法中断,直到完成,应用程序才能继续。还有其他方法可以完成(后台线程,禁用UI直到准备就绪),但是老板和客户都喜欢这种方式,因为它强调了流程的重要性。
flurbius

15

要禁用关闭按钮,您应该在Window类中添加以下代码(该代码是从此处获取的,进行了一些编辑和重新格式化):

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

此代码还禁用“系统”菜单中的关闭项目,并不允许使用Alt + F4关闭对话框。

您可能需要以编程方式关闭窗口。只是打电话是Close()行不通的。做这样的事情:

allowClosing = true;
Close();

在Windows 7中:上面的命令还会禁用(但不会删除)下拉系统菜单中的关闭项。“关闭”按钮本身是禁用的(看起来是灰色的),但是没有被移除。此技巧不适用于“最小化/最大化”项/按钮-我怀疑WPF会重新启用它们。

3
禁用按钮比仅移除按钮要好,它可以保持一致的感觉,同时让用户知道正在执行重要的操作。
罗伯特·贝克

10

我尝试了Viachaslau的答案,因为我喜欢不删除按钮而是禁用按钮的想法,但是由于某种原因,它并不总是起作用:关闭按钮仍然处于启用状态,但没有任何错误。

另一方面,这始终有效(省略了错误检查):

[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
完善!Window在我的项目中添加为扩展方法。
马特·戴维斯

8

要设置的属性是=> 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
这也隐藏了最大/最小按钮
VoteCoffee 2014年

3
它删除了整个标题栏,使该框难看并且没有描述。gun弹枪方法和重复的答案。下注。
vapcguy

这是自助服务终端应用程序的最佳解决方案,始终需要最大化其应用程序并且不应允许客户关闭应用程序。So UpVote
Rajon Tanducar

8

我只是使用“交互行为” 添加了Joe White答案的实现(您需要引用System.Windows.Interactivity)。

码:

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

用法:

<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

让用户“关闭”窗口,但实际上只是将其隐藏。

在窗口的OnClosing事件中,如果已经可见,则将其隐藏:

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

每次执行后台线程时,请重新显示后台用户界面窗口:

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

终止程序执行时,请确保/可以关闭所有窗口:

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

因此,这几乎是您的问题。窗口框架右上方的关闭按钮不是WPF窗口的一部分,而是属于由操作系统控制的窗口框架的一部分。这意味着您将必须使用Win32 interop来执行此操作。

或者,您可以使用noframe并提供您自己的“框架”或根本没有框架。


1

以下是有关禁用关闭和最大化/最小化按钮的信息,它实际上并未删除按钮(但确实删除了菜单项!)。标题栏上的按钮以禁用/灰色状态绘制。(我还没有准备好亲自接管所有功能^^)

这与Virgoss解决方案略有不同,因为它删除了菜单项(以及尾随的分隔符,如果需要),而不是仅禁用它们。它与Joe Whites解决方案不同,因为它不会禁用整个系统菜单,因此,就我而言,我可以保留“最小化”按钮和图标。

后面的代码还支持禁用“最大化/最小化”按钮,因为与“关闭”按钮不同,从菜单中删除条目不会导致系统将按钮“禁用”,即使删除菜单项确实会禁用按钮的功能。

这个对我有用。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);
            }
        }
    }

用法:必须在初始化源之后执行此操作。一个合适的地方是使用Window的SourceInitialized事件:

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
}

要禁用Alt + F4功能,简单的方法就是连接Canceling事件,并在确实要关闭窗口时使用set标志。


0

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>

应该管用

编辑 -此线程立即显示如何完成此操作,但我不认为Window具有在不失去常规标题栏的情况下获取所需内容的属性。

编辑2线程显示了完成此操作的方法,但是您必须将自己的样式应用于系统菜单,并且显示如何执行此操作。


由于某些原因,“应该工作”刚刚显示出来,但是现在发生了更新
TStamper

3
我说的是标题栏中的Window状态。看起来就像编辑一个简单的按钮。
Michael Hedgpeth,2009年

@TStamper,如何使用您的代码段?我正在使用全局Window样式(和模板)。
Shimmy Weitzhandler,2010年

@ Shimmy-您指的是哪一个?
TStamper

0

尝试将关闭事件添加到窗口。将此代码添加到事件处理程序。

e.Cancel = true;

这将防止窗口关闭。这与隐藏关闭按钮具有相同的效果。


1
“这与隐藏关闭按钮具有相同的效果。” 除了按钮仍然可见并且可以单击之外,即按钮是动画的并且在您单击时视觉上按下-这违反了POLA
rory.ap

0

使用从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

这不会隐藏按钮,但会通过关闭窗口阻止用户前进。

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

-1

转到窗口属性集

window style = none;

你不会得到关闭按钮...


下注。实际上是WindowStyle = "None"-注意语法。另一方面,这是一种a弹枪的方法,当有很多更好的方法(如其他答案所示)处理时,它也会删除标题栏,使框丑陋且缺少标题,这是重复的答案。
vapcguy

-1

如其他答案所述,您可以使用WindowStyle="None"完全删除标题栏。

并且,如对其他答案的注释中所述,这防止了窗口被拖动,因此很难将其从其初始位置移开。

但是,您可以通过在Window的Code Behind文件中向构造函数添加一行代码来克服此问题:

MouseDown += delegate { DragMove(); };

或者,如果您更喜欢Lambda语法:

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

这使得整个窗口可拖动。窗口中存在的任何交互式控件(如按钮)仍将正常工作,并且不会充当窗口的拖动柄。


还是个坏主意。它删除了整个标题栏,使之成为shot弹枪的方法,并使该框看起来丑陋,这意味着没有标题/描述。有更好的选择。
vapcguy

@vapcguy删除整个标题栏。这是a弹枪的方法。使盒子看起来丑陋?你的意见。还有更好的选择吗?也许对你来说。不适合所有人。:-)
Holf

-1

在寻找答案之后,我制定了这个简单的解决方案,我将在这里分享,希望对其他人有所帮助。

我定了WindowStyle=0x10000000

这将设置“ 窗口样式” 的WS_VISIBLE (0x10000000)WS_OVERLAPPED (0x0)值。“重叠”是显示标题栏和窗口边框的必要值。通过移除WS_MINIMIZEBOX (0x20000)WS_MAXIMIZEBOX (0x10000)以及WS_SYSMENU (0x80000)从我的风格值值,所有从标题栏的按钮被拆除,其中包括关闭按钮。


在WPF中,WindowStyle是一个枚举,其值与Windows API常数不匹配;将值强制为WindowStyle枚举将不起作用。可以肯定的是,我已经检查了ILSpy中的.NET源代码。枚举值将转换为私有函数中的Windows API CreateWindowStyle,如果该函数遇到未知WindowStyle值,则仅应用WindowStyle.None。(唯一的方法是使用内部属性_Style_StyleEx使用反射,强烈反对。)
Mike Rosoft


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.