簡體   English   中英

禁用 WPF 窗口標題欄中的關閉按鈕 (C#)

[英]Disable Close Button In Title Bar of a WPF Window (C#)

我想知道如何禁用(而不是刪除/隱藏)WPF 窗口中的關閉按鈕。 我知道如何隱藏它,使窗口的標題欄看起來像這樣:

在此處輸入圖像描述

但我想禁用它,這意味着它應該如下所示:

在此處輸入圖像描述

我正在用 C# 編寫腳本並使用 WPF(Windows Presentation Foundation)。

嘗試這個:

public partial class MainWindow : Window
{

    [DllImport("user32.dll")]
    static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);

    [DllImport("user32.dll")]
    static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);


    const uint MF_BYCOMMAND = 0x00000000;
    const uint MF_GRAYED = 0x00000001;

    const uint SC_CLOSE = 0xF060;

    public MainWindow()
    {
        InitializeComponent();
    }

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);

        // Disable close button
        IntPtr hwnd = new WindowInteropHelper(this).Handle;
        IntPtr hMenu = GetSystemMenu(hwnd, false);
        if (hMenu != IntPtr.Zero)
        {
            EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
        }
    }
}

取自這里

確保將ResizeMode設置為NoResize

您必須覆蓋並在OnCLosing事件中設置 e.cancel=true

public MyWindow()
{
    InitializeComponent();
    this.Closing += new System.ComponentModel.CancelEventHandler(MyWindow_Closing);
}

void MyWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
    e.Cancel = true;
}

這篇文章使用BehaviorGetWindowLongSetWindowLong回答:

public class HideCloseButtonOnWindow : System.Windows.Interactivity.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 System.Windows.Interop.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>

你可能可以用win32hackery做到這一點。

我是這樣做的:獲取CustomChromeWindow(最終看起來與圖片中的一模一樣),並將Command()屬性綁定到viewmodel,然后設置CanExecuteCommand = false,這將使按鈕禁用( 如何一個“使用 MVVM 模式禁用”WPF 中的按鈕? )。

我也可能有這種方式: 如何使用 C++ 在另一個進程中禁用窗口上的關閉按鈕?

基本上,使用 pInvoke 調用該代碼。 您可以輕松獲取 WPF 窗口句柄。

如果您想要一個更通用的Yoav 接受的答案版本,不需要將 Win API 調用添加到您的 Window 類,這里有一個擴展類和方法:

namespace WinApi
{
    using System.Runtime.InteropServices;
    using System.Windows.Interop;

    public static class WinApi
    {
        [DllImport("user32.dll")]
        public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);

        [DllImport("user32.dll")]
        public static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);

        const uint MF_BYCOMMAND = 0x00000000;
        const uint MF_GRAYED = 0x00000001;

        const uint SC_CLOSE = 0xF060;

        public static void DisableCloseButton(this System.Windows.Window window)
        {
            // Disable close button
            IntPtr hwnd = new WindowInteropHelper(window).EnsureHandle();
            IntPtr hMenu = GetSystemMenu(hwnd, false);

            if (hMenu != IntPtr.Zero)
                EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
        }
    }
}

然后像這樣從你的窗口調用它:

this.DisableCloseButton();

// or

WinApi.DisableCloseButton(this);

由於擴展使用EnsureHandle() ,因此您無需在窗口中掛鈎OnSourceInitialized()

請注意EnsureHandle()會引發OnSourceInitialized() ,因此在您完成任何您想要在該調用之前發生的任何事情之前不要調用它。

如果需要檢查句柄是否已創建,可以在 Window 代碼中調用new WindowInteropHelper(this).Handle()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM