Bagaimana cara menyembunyikan tombol tutup di jendela WPF?

204

Saya sedang menulis dialog modal dalam WPF. Bagaimana cara mengatur jendela WPF agar tidak memiliki tombol tutup? Saya masih ingin itu WindowStatememiliki judul bar normal.

Saya menemukan ResizeMode,, WindowStatedan WindowStyle, tetapi tidak satu pun dari properti itu yang memungkinkan saya untuk menyembunyikan tombol tutup tetapi menunjukkan bilah judul, seperti dalam dialog modal.

Michael Hedgpeth
sumber
9
Ini adalah dialog progres yang menjalankan utas latar belakang yang tidak mendukung pembatalan; Saya kira saya hanya mencoba membuatnya jadi saya tidak harus mendukung pembatalan (belum). Tapi Anda mungkin benar.
Michael Hedgpeth
1
Saya juga benci aplikasi yang mencoba menghapus krom jendela. Jika saya membuat dialog progres, saya selalu membuat jendela tombol Tutup melakukan logika yang sama dengan mengklik tombol Batal yang sebenarnya.
Christian Hayter
13
Untuk Chris: Mari bayangkan perangkat lunak Anda untuk Video Surveillance. Seorang agen keamanan pada malam hari MEMILIKI (itu tugasnya) untuk menjaga jendela tetap terbuka ... tapi kadang-kadang pekerjaan mereka membosankan dan mereka ingin menjelajahi Internet atau menutup jendela Video Matriks dengan alasan apa pun, menghapus tombol windows adalah cara yang tepat untuk melakukannya.
Jean-Marie
7
@ChrisUpchurch, "Mengapa Anda ingin melakukan ini? Itu menurut saya desain UI benar-benar buruk." - benar-benar "desain UI buruk" adalah ketika sebuah program menyajikan kotak dialog dengan OK ; Batalkan dan Tutup tombol. Bagi pengguna, mungkin tidak jelas apa yang dilakukan Close . Apakah itu membatalkan atau mengirim ? Konsensus adalah untuk tidak memasukkan tombol tutup dalam dialog sehingga ada itu
MickyD
1
@ Jean-Marie Tapi menyembunyikan tombol tutup tidak mencegah hal itu terjadi, itu hanya membodohi orang yang kurang informasi dan malas (ke Google). Menyembunyikan tombol tutup hanya mencegah mengklik tombol itu. Win key dan alt key combo akan tetap berfungsi seperti biasa. Cara yang "tepat" untuk melakukannya adalah membuat akun pengguna untuk pekerja, dengan kebijakan grup yang mencegah mereka membuka / menginstal perangkat lunak apa pun selain dari yang disetujui. akun admin, yang dapat diakses pengawas, untuk menangani pemeliharaan apa pun.
Digital_Utopia

Jawaban:

275

WPF tidak memiliki properti bawaan untuk menyembunyikan tombol Tutup bilah judul, tetapi Anda dapat melakukannya dengan beberapa baris P / Invoke.

Pertama, tambahkan deklarasi ini ke kelas Window Anda:

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

Kemudian masukkan kode ini ke acara Window Loaded:

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

Dan begitulah: tidak ada lagi tombol Tutup. Anda juga tidak akan memiliki ikon jendela di sisi kiri bilah judul, yang berarti tidak ada menu sistem, bahkan ketika Anda mengklik kanan bilah judul - semuanya berjalan bersamaan.

Perhatikan bahwa Alt+ F4masih akan menutup Window. Jika Anda tidak ingin membiarkan jendela ditutup sebelum utas latar belakang selesai, maka Anda juga bisa mengganti OnClosingdan mengatur Cancelke true, seperti yang disarankan Gabe.

Joe White
sumber
5
Menurut dokumen yang seharusnya kita gunakan SetWindowLongPtr.
Jonathan Allen
15
Sebagian besar catatan untuk diri sendiri ... Namespace DllImport -> System.Runtime.InteropServices.DllImport. Namespace dari WindowInteropHelper -> System.Windows.Interop.WindowInteropHelper
doobop
3
Sebenarnya, pendekatan ini menyembunyikan ketiga tombol (Min, Max dan Close). Apakah mungkin menyembunyikan tombol Tutup?
pemain baru
4
@miliu, tidak. Anda dapat menonaktifkannya , tetapi Anda tidak dapat menyembunyikannya tanpa menyembunyikan Minimalkan / Maksimalkan juga. Saya menduga para pengembang Windows berpikir itu akan membingungkan jika Maximize berada di sebelah kanan tempat Close biasanya berada.
Joe White
3
Masukkan WindowStyle = "Tidak Ada" pada tag Window Anda di file XAML.
diegodsp
88

Saya baru saja mengalami masalah yang sama dan solusi Joe White bagi saya sederhana dan bersih. Saya menggunakannya kembali dan mendefinisikannya sebagai properti Window yang terlampir

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

}

Kemudian di XAML Anda cukup mengaturnya seperti ini:

<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>
SpudCZ
sumber
64

Setel WindowStyleproperti ke Tidak Ada yang akan menyembunyikan kotak kontrol bersama dengan bilah judul. Tidak perlu panggilan abadi.

Sriwantha Attanayake
sumber
20
Nah, ini akan menyembunyikan bilah judul jendela sepenuhnya. Itu berarti Anda tidak mendapatkan judul jendela dan pengguna tidak akan dapat memindahkan jendela.
pemain baru
8
Anda dapat membuat jendela bergerak dengan menambahkan this.DragMove();ke jendela MouseDownacara
paul
1
Untuk dialog modal yang harus murni bersifat informasi dan wajib, seperti kemajuan dalam meningkatkan basis data dengan skema lama yang telah dibuka, solusi ini sangat cocok.
The Lonely Coder
1
Saya pikir beberapa orang ingin memiliki perbatasan,
pjdupreez
2
Pasti solusi terbaik. Tidak ada masalah dengan menambahkan perbatasan ke panel, atau menerapkan pemindahan.
buks
50

Ini tidak akan menghilangkan tombol tutup, tetapi itu akan menghentikan seseorang menutup jendela.

Letakkan ini di kode Anda di belakang file:

protected override void OnClosing(CancelEventArgs e)
{
   base.OnClosing(e);
   e.Cancel = true;
}
flurbius
sumber
7
Ketahuilah bahwa melakukan ini dalam suatu Windowyang diatur sebagai dialog modal akan mengganggu Windowpengaturan DialogResultpropertinya dan mungkin membuatnya tidak dapat digunakan. stackoverflow.com/questions/898708/cant-set-dialogresult-in-wpf
Sheridan
4
Saya mendapatkan overflow menggunakan metode ini, saya mengambil basis. Menutup (e) dan kemudian bekerja
jacobsgriffith
8
Sebagai pengguna saya akan membenci programmer yang memasukkan ini ke dalam aplikasi mereka
UrbanEsc
2
@UrbanEsc Saya cenderung setuju bahwa itu hal yang mengganggu untuk dilakukan, tetapi ketika saya melakukan ini - dan itu hanya satu kali - itu adalah persyaratan wajib, dan itu adalah kejahatan yang diperlukan, ada beberapa proses yang sangat penting terjadi itu tidak dapat terganggu dan aplikasi tidak dapat melanjutkan sampai selesai. Ada cara lain yang bisa dilakukan (utas latar belakang, dengan UI dinonaktifkan hingga siap), tetapi bos dan klien sama-sama menyukainya karena ini menekankan pentingnya proses.
flurbius
15

Untuk menonaktifkan tombol tutup, Anda harus menambahkan kode berikut ke kelas Window Anda (kode diambil dari sini , diedit dan diformat ulang sedikit):

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

Kode ini juga menonaktifkan item dekat di menu Sistem dan melarang menutup dialog menggunakan Alt + F4.

Anda mungkin ingin menutup jendela secara terprogram. Hanya menelepon Close()tidak akan berhasil. Lakukan sesuatu seperti ini:

allowClosing = true;
Close();
Viachaslau Tysianchuk
sumber
Di Windows 7: Di atas juga menonaktifkan (tetapi tidak menghapus) item Tutup di menu Sistem drop-down. Tombol Close sendiri dinonaktifkan (terlihat abu-abu), tetapi tidak dihapus. Trik ini tidak berfungsi untuk item Minimalkan / Maksimalkan / tombol - Saya menduga WPF mengaktifkannya kembali.
3
Menonaktifkan tombol lebih baik daripada hanya menghapusnya, itu membuat nuansa yang konsisten sambil membiarkan pengguna tahu bahwa operasi penting sedang berjalan.
Robert Baker
10

Saya sedang mencoba jawaban Viachaslau karena saya suka ide untuk tidak melepas tombol tetapi menonaktifkannya, tetapi untuk beberapa alasan itu tidak selalu berhasil: tombol tutup masih diaktifkan tetapi tidak ada kesalahan apa pun.

Di sisi lain, ini selalu berhasil (pengecekan kesalahan dihilangkan):

[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 );
}
stijn
sumber
1
Sempurna! Ditambahkan sebagai Windowmetode ekstensi dalam proyek saya.
Matt Davis
8

Properti yang akan diatur adalah => 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">
daniele3004
sumber
4
Ini juga menyembunyikan tombol maks / mnt
VoteCoffee
3
Ini menghapus seluruh bilah judul, menjadikan kotak itu jelek dan tanpa deskripsi. Pendekatan shotgun dan jawaban rangkap. Downvote.
vapcguy
Ini adalah solusi terbaik untuk aplikasi kios yang selalu membutuhkan aplikasi untuk dimaksimalkan dan seharusnya tidak memungkinkan pelanggan untuk menutup aplikasi. So UpVote
Rajon Tanducar
8

Saya hanya menambahkan implementasi saya atas jawaban Joe White menggunakan Perilaku Interaktivitas (Anda perlu merujuk System.Windows.Interactivity).

kode:

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

pemakaian:

<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>
tom.maruska
sumber
2

Biarkan pengguna "menutup" jendela tetapi benar-benar hanya menyembunyikannya.

Di acara Tutupan jendela, sembunyikan jendela jika sudah terlihat:

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

Setiap kali utas latar dijalankan, tampilkan kembali jendela UI latar belakang:

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

Saat mengakhiri eksekusi program, pastikan semua jendela dapat ditutup:

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

Jadi, ini masalah Anda. Tombol tutup di kanan atas bingkai jendela bukan bagian dari jendela WPF, tetapi milik bagian bingkai jendela yang dikendalikan oleh OS Anda. Ini berarti Anda harus menggunakan Win32 interop untuk melakukannya.

secara alternatif, Anda dapat menggunakan noframe dan memberikan "bingkai" sendiri atau tidak memiliki bingkai sama sekali.

Muad'Dib
sumber
1

Berikut ini adalah tentang menonaktifkan tombol Tutup dan Maksimalkan / Minimalkan, itu tidak benar benar menghapus tombol (tetapi itu menghapus item menu!). Tombol-tombol pada bilah judul digambar dalam keadaan dinonaktifkan / abu-abu. (Saya sendiri belum siap untuk mengambil alih semua fungsionalitasnya ^^)

Ini sedikit berbeda dari solusi Virgoss karena ia menghilangkan item menu (dan pemisah trailing, jika diperlukan) alih-alih hanya menonaktifkannya. Ini berbeda dari solusi Joe Whites karena tidak menonaktifkan seluruh menu sistem dan, dalam kasus saya, saya dapat menyimpan sekitar tombol dan ikon Perkecil.

Kode tindak juga mendukung penonaktifan tombol Maximize / Minimize karena, tidak seperti tombol Close, menghapus entri dari menu tidak menyebabkan sistem membuat tombol "dinonaktifkan" meskipun menghapus entri menu tidak menonaktifkan fungsionalitas tombol.

Ini bekerja untuk saya. 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);
            }
        }
    }

Penggunaan: Ini harus dilakukan SETELAH sumber diinisialisasi. Tempat yang baik adalah menggunakan acara SourceInitialized of the Window:

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
}

Untuk menonaktifkan fungsionalitas Alt + F4 metode mudah adalah dengan memasang acara Membatalkan dan menggunakan mengatur bendera ketika Anda benar-benar ingin menutup jendela.

daniele3004
sumber
0

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

harus bekerja

Sunting - untuk instan Anda Thread ini menunjukkan bagaimana hal itu dapat dilakukan tetapi saya tidak berpikir Window memiliki properti untuk mendapatkan apa yang Anda inginkan tanpa kehilangan bilah judul normal.

Sunting 2 Thread ini menunjukkan cara untuk melakukannya, tetapi Anda harus menerapkan gaya Anda sendiri ke menu sistem dan itu menunjukkan cara bagaimana Anda bisa melakukannya.

TStamper
sumber
untuk beberapa alasan "harus bekerja" baru saja ditampilkan, tetapi sekarang diperbarui telah terjadi
TStamper
3
Saya berbicara tentang status Window, yang ada di bilah judul. Ini seperti mengedit tombol sederhana.
Michael Hedgpeth
@TStamper, bagaimana cara saya menggunakan cuplikan Anda? Saya menggunakan gaya Window global (dan templat).
Shimmy Weitzhandler
@ Shimmy- yang mana yang Anda maksud?
TStamper
0

Coba tambahkan acara Penutupan ke jendela. Tambahkan kode ini ke pengendali acara.

e.Cancel = true;

Ini akan mencegah jendela dari menutup. Ini memiliki efek yang sama dengan menyembunyikan tombol tutup.

Dennis R
sumber
1
"Ini memiliki efek yang sama dengan menyembunyikan tombol tutup." kecuali bahwa tombol tersebut masih terlihat dan dapat diklik, yaitu itu dianimasikan dan ditekan secara visual ketika Anda mengkliknya - yang menentang POLA .
rory.ap
0

Gunakan ini, dimodifikasi dari 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);
        }  

    }
}
vapcguy
sumber
0

Ini tidak menyembunyikan tombol tetapi akan mencegah pengguna bergerak maju dengan mematikan jendela.

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

properti jendela goto diatur

window style = none;

kamu tidak akan mendapatkan tombol tutup ...

Pavan R Bhupalam
sumber
Downvote. Sebenarnya WindowStyle = "None"- perhatikan sintaks Anda. Untuk yang lain, ini adalah pendekatan shotgun yang juga menghilangkan bilah judul, membuat kotak itu jelek dan kurang judul, ketika ada begitu banyak cara yang lebih baik untuk menangani ini (sebagaimana dibuktikan oleh jawaban lain), dan merupakan jawaban rangkap.
vapcguy
-1

Seperti yang dinyatakan dalam jawaban lain, Anda dapat menggunakan WindowStyle="None"untuk menghapus Judul Bar sama sekali.

Dan, seperti yang dinyatakan dalam komentar untuk jawaban-jawaban lainnya, ini mencegah jendela menjadi tidak dapat diseret sehingga sulit untuk memindahkannya dari posisi awalnya.

Namun, Anda dapat mengatasi ini dengan menambahkan satu baris kode ke Konstruktor di file Window Behind Code:

MouseDown += delegate { DragMove(); };

Atau, jika Anda lebih menyukai Sintaks Lambda:

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

Ini membuat seluruh Window dapat diseret. Kontrol interaktif apa pun yang ada di Window, seperti Buttons, akan tetap berfungsi seperti biasa dan tidak akan bertindak sebagai drag-handle untuk Window.

Serigala
sumber
Masih ide yang buruk. Itu menghapus seluruh judul bar, menjadikan ini pendekatan senapan, dan membuat kotak terlihat jelek dan berarti tidak ada judul / deskripsi untuk itu. Ada banyak alternatif yang lebih baik.
vapcguy
@vapcguy Menghapus seluruh judul bar. Ini adalah pendekatan senapan. Membuat kotak itu terlihat jelek? Pendapat Anda. Alternatif yang jauh lebih baik? Untuk Anda, mungkin. Tidak untuk semua orang. :-)
Serigala
-1

Setelah banyak mencari jawaban untuk ini, saya mengerjakan solusi sederhana ini yang akan saya bagikan di sini dengan harapan dapat membantu orang lain.

Saya mengatur WindowStyle=0x10000000.

Ini mengatur WS_VISIBLE (0x10000000)dan WS_OVERLAPPED (0x0)nilai-nilai untuk Gaya Jendela. "Tumpang tindih" adalah nilai yang diperlukan untuk menampilkan bilah judul dan batas jendela. Dengan menghapus WS_MINIMIZEBOX (0x20000), WS_MAXIMIZEBOX (0x10000)dan WS_SYSMENU (0x80000)nilai-nilai dari nilai gaya saya, semua tombol dari bilah judul telah dihapus, termasuk tombol Tutup.

Joe Horr
sumber
Dalam WPF WindowStyleadalah enumerasi yang nilainya tidak sesuai dengan konstanta Windows API; paksaan nilai untuk WindowStylepencacahan tidak akan berhasil. Yang pasti, saya telah memeriksa kode sumber .NET di ILSpy; nilai enum diterjemahkan ke Windows API di fungsi privat CreateWindowStyle, dan jika fungsi menemukan WindowStylenilai yang tidak diketahui , itu hanya berlaku WindowStyle.None. (Satu-satunya cara adalah dengan menggunakan properti internal _Styledan _StyleExmenggunakan refleksi, yang saya sangat sarankan menentang.)
Mike Rosoft
-2

Gunakan WindowStyle="SingleBorderWindow", ini akan menyembunyikan tombol max dan min dari WPF Window.

Vishal Nayan
sumber
1
tidak memecahkan masalah menyembunyikan closetombol
memori mimpi
-2

Jika kebutuhan hanya untuk melarang pengguna menutup jendela, ini adalah solusi sederhana.

Kode XAML: IsCloseButtonEnabled="False"

Filipe Piletti Plucenio
sumber