WPF penceresinde kapat düğmesi nasıl gizlenir?


204

WPF'de kalıcı bir iletişim kutusu yazıyorum. WPF penceresini kapatma düğmesi olmayacak şekilde nasıl ayarlarım? Hala onun için istiyorumWindowState normal bir başlık çubuğuna sahip .

Ben buldum ResizeMode, WindowStateve WindowStylefakat bu özelliklerin hiçbiri bana kapatma düğmesini gizlemek için izin ancak kalıcı diyaloglar gibi başlık çubuğunu gösterir.


9
İptal işlemini desteklemeyen bir arka plan iş parçacığı çalıştıran bir ilerleme iletişim kutusu; Sanırım sadece bunu yapmaya çalışıyorum, bu yüzden iptal etmeyi (henüz) desteklemem gerekmiyor. Yine de muhtemelen haklısın.
Michael Hedgpeth

1
Ayrıca pencere kromunu kaldırmaya çalışan uygulamalardan da nefret ediyorum. Bir ilerleme iletişim kutusu oluşturursam, her zaman Kapat penceresini gerçek İptal düğmesine tıklatmakla aynı mantığı yaparım.
Christian Hayter

13
Chris için: Yazılımınızın Video Surveillance için olduğunu düşünelim. Gece boyunca bir güvenlik ajanı HAS (bu onun işi) pencereleri açık tutmak için ... ama bazen işleri sıkıcı ve herhangi bir nedenle internette sörf yapmak veya Video Matrisler pencerelerini kapatmak istiyorlar, windows düğmelerini kaldırmak doğru yoldur yapmak için.
Jean-Marie

7
@ChrisUpchurch, "Neden bunu yapmak istiyorsun? Bana gerçekten berbat UI tasarımı olarak dikkat çekiyor ." - gerçekten "berbat UI tasarımı" bir programın OK ile bir iletişim kutusu sunmasıdır ; İptal ve Kapat düğmeleri. Bir kullanıcı için Close'un ne yaptığı açık olmayabilir . O mu iptal veya göndermek ? Fikir birliği diyaloglarda kapatma düğmeleri içermez , bu yüzden
MickyD

1
@ Jean-Marie Ancak kapat düğmesini gizlemek bunun olmasını engellemez, sadece bilgisiz ve tembel olmayı kandırır (Google'a). Kapat düğmesini gizlemek yalnızca bu düğmeyi tıklamayı önler. Win tuşu ve alt tuş kombinasyonları normal olarak çalışacaktır "Bunu yapmanın" uygun "yolu, onaylananlar dışında herhangi bir yazılımı açmalarını / yüklemelerini engelleyen bir grup politikası ile çalışanlar için bir kullanıcı hesabı oluşturmaktır. herhangi bir bakım işleminin gerçekleştirilmesi için süpervizörlerin erişebildiği yönetici hesabı.
Digital_Utopia

Yanıtlar:


275

WPF, başlık çubuğunun Kapat düğmesini gizlemek için yerleşik bir özelliğe sahip değildir, ancak bunu birkaç satır P / Invoke ile yapabilirsiniz.

İlk olarak, bu bildirimleri Window sınıfınıza ekleyin:

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

Sonra bu kodu Window Loadedetkinliğine koyun :

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

Ve işte gidiyorsunuz: artık Kapat düğmesi yok. Ayrıca başlık çubuğunun sol tarafında bir pencere simgesi olmayacaktır, bu da başlık çubuğuna sağ tıklasanız bile sistem menüsü olmadığı anlamına gelir - hepsi birlikte gider.

Alt+ F4Öğesinin yine de Pencereyi kapatacağını unutmayın . Arka plan iş parçacığı tamamlanmadan pencerenin kapanmasına izin vermek istemiyorsanız , Gabe'nin önerdiği gibi geçersiz kılabilir OnClosingve Canceltrue olarak ayarlayabilirsiniz .


5
Dokümanlara göre SetWindowLongPtrbunun yerine kullanmalıyız.
Jonathan Allen

15
Çoğunlukla kendine not ... DllImport ad alanı -> System.Runtime.InteropServices.DllImport. WindowInteropHelper Ad Alanı -> System.Windows.Interop.WindowInteropHelper
doobop 28:10

3
Aslında, bu yaklaşım her üç düğmeyi de gizler (Min, Maks ve Kapat). Kapat düğmesini gizlemek mümkün mü?
newman

4
Miliu, hayır. Devre dışı bırakabilirsiniz , ancak Küçült / Büyüt'ü de gizlemeden gizleyemezsiniz. Windows geliştiricilerinin, Maximize'ın genellikle Close'un olduğu yerde sağda olmasının kafa karıştırıcı olacağını düşündüğünden şüpheleniyorum.
Joe White

3
XAML dosyasındaki Window etiketinize WindowStyle = "None" koyun.
diegodsp

88

Benzer bir problemle karşılaştım ve Joe White'ın çözümü bana basit ve temiz görünüyor. Yeniden kullandım ve Window'un ekli özelliği olarak tanımladım

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

}

Sonra XAML'de şöyle ayarladınız:

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

63

WindowStyleÖzelliği başlık çubuğuyla birlikte denetim kutusunu gizleyecek Yok olarak ayarlayın . Çekirdek çağrılara gerek yok.


20
Bu, pencere başlık çubuğunu tamamen gizleyecektir. Bu, pencere başlığı alamayacağınız ve kullanıcının pencereyi taşıyamayacağı anlamına gelir.
newman

7
this.DragMove();Pencerenin MouseDownetkinliğine ekleyerek pencereyi hareket ettirebilirsiniz
paul

1
Tamamen bilgilendirici ve zorunlu olması gereken kalıcı bir iletişim kutusu için, bir veritabanını açılmış eski bir şema ile yükseltme konusundaki ilerleme gibi, bu çözüm mükemmeldir.
Yalnız Kodlayıcı

1
Sanırım bazı insanlar bir sınır var istiyorum
pjdupreez

2
Kesinlikle en iyi çözüm. Panele kenarlık ekleme veya taşıma uygulamada sorun yoktur.
49'da satın alıyor

50

Bu, kapatma düğmesinden kurtulmaz, ancak birinin pencereyi kapatmasını durduracaktır.

Bunu dosyanın arkasındaki kodunuza yerleştirin:

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

7
WindowKalıcı bir iletişim kutusu olarak ayarlanan bir pencerede bunu yapmanın Window, DialogResultözelliğinin ayarına müdahale edeceğini ve kullanılamaz hale getirebileceğini unutmayın. stackoverflow.com/questions/898708/cant-set-dialogresult-in-wpf
Sheridan

4
Ben bu yöntemi kullanarak bir taşma başlamıştı, ben işe yaradı sonra base.OnClosing (e) çıkardı ve
jacobsgriffith

8
Bir kullanıcı olarak, bunu uygulamalarına koyan programcıdan nefret ediyorum
UrbanEsc

2
@UrbanEsc Yapmak için can sıkıcı bir şey olduğunu kabul etme eğilimindeydim, ama bunu yaptığımda - ve sadece bir kez - zorunlu bir gereklilikti ve gerekli bir kötüydü, devam eden çok önemli bir süreç vardı bu kesilemedi ve uygulama tamamlanana kadar devam edemedi. Yapılması gereken başka yollar da vardı (UI hazır olana kadar devre dışı bırakılmış bir arka plan iş parçacığı), ancak patron ve müşteri bunu sevdi, çünkü sürecin yerçekimini vurguladı.
flurbius

15

Kapat düğmesini devre dışı bırakmak için Window sınıfınıza aşağıdaki kodu eklemeniz gerekir (kod buradan alınmıştır , düzenlenmiştir ve yeniden biçimlendirilmiştir):

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

Bu kod ayrıca Sistem menüsündeki yakın öğeyi devre dışı bırakır ve Alt + F4 kullanarak iletişim kutusunun kapatılmasına izin vermez.

Muhtemelen pencereyi programlı olarak kapatmak isteyeceksiniz. Sadece aramak Close()işe yaramaz. Bunun gibi bir şey yapın:

allowClosing = true;
Close();

Windows 7'de: Yukarıdakiler, açılır menü menüsündeki Kapat öğesini de devre dışı bırakır (ancak kaldırmaz). Kapat düğmesinin kendisi devre dışıdır (gri görünür), ancak kaldırılmaz. Bu hile Küçült / Ekranı Kapla öğesi / düğmesi için çalışmaz - WPF'nin bunları yeniden etkinleştirdiğinden şüpheleniyorum.

3
Düğmeyi devre dışı bırakmak, onları kaldırmaktan daha iyidir, kullanıcıya önemli bir işlemin çalıştığını bildirirken tutarlı bir his verir.
Robert Baker

10

Viachaslau'nun yanıtını, düğmeyi kaldırmama ama devre dışı bırakma fikrini sevdiğimden beri deniyordum, ancak bir nedenle her zaman işe yaramadı: kapat düğmesi hala etkinleştirildi, ancak hata yok.

Öte yandan bu her zaman işe yaradı (hata kontrolü atlandı):

[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
Mükemmel! Projeme bir Windowuzantı yöntemi olarak eklendi .
Matt Davis

8

Ayarlanacak özellik => 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
Bu aynı zamanda maks / min düğmelerini de gizler
VoteCoffee

3
Tüm başlık çubuğunu kaldırır, kutuyu çirkin ve açıklama olmadan oluşturur. Av tüfeği yaklaşımı ve yinelenen bir cevap. Downvote.
vapcguy

Bu, her zaman uygulamasının en üst düzeye çıkarılması gereken ve müşterilerin uygulamayı kapatmasına izin vermemesi gereken kiosk uygulamaları için en iyi çözümdür. So UpOy
Rajon Tanducar

8

Sadece uygulamamı ekliyorum Joe White'ın cevabını Etkileşim Davranışı'nı kullanarak (System.Windows.Interactivity'ye başvurmanız gerekir).

kod:

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

kullanımı:

<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

Kullanıcının pencereyi "kapatmasına" izin verin ama gerçekten gizleyin.

Pencerenin OnClosing etkinliğinde, zaten görünürse pencereyi gizleyin:

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

Arka plan iş parçacığı her yürütüldüğünde, arka plan kullanıcı arayüzü penceresini yeniden gösterin:

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

Programın yürütülmesini sonlandırırken, tüm pencerelerin kapalı olduğundan / kapatılabildiğinden emin olun:

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

Yani, hemen hemen burada probleminiz var. Bir pencere çerçevesinin sağ üstündeki kapat düğmesi WPF penceresinin bir parçası değildir, ancak pencere çerçevesinin işletim sisteminiz tarafından kontrol edilen kısmına aittir. Bu, Win32 birlikte çalışma özelliğini kullanmanız gerektiği anlamına gelir.

alternatif olarak noframe'i kullanabilir ve kendi "çerçevenizi" sağlayabilir veya hiç çerçeveniz olmayabilir.


1

Aşağıdaki öyle, yakın ve Ekranı Kapla / Minimize düğmeleri devre dışı bırakma hakkında değil aslında düğmeleri kaldırabilirsiniz (ama menü öğeleri kaldırmak değil!). Başlık çubuğundaki düğmeler devre dışı / gri renkte çizilir. (Tüm işlevselliği kendim devralmaya hazır değilim ^^)

Bu, Virgoss çözümünden biraz farklıdır, çünkü menü öğelerini (ve gerekirse arkadaki ayırıcıyı) yalnızca devre dışı bırakmak yerine kaldırır. Tüm sistem menüsünü devre dışı bırakmadığı için Joe Whites çözümünden farklıdır ve benim durumumda, Simge Durumuna Küçült düğmesini ve simgesini tutabilirim.

Aşağıdaki kod, Büyüt / Küçült düğmelerinin devre dışı bırakılmasını da destekler, çünkü Kapat düğmesinin aksine, menüden girişlerin kaldırılması, menü düğmelerinin kaldırılması düğmelerin işlevselliğini devre dışı bırakmasına rağmen sistemin düğmeleri "devre dışı bırakmasına" neden olmaz .

Benim için çalışıyor. 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);
            }
        }
    }

Kullanım: Bu, kaynak başlatıldıktan SONRA yapılmalıdır. Pencerenin SourceInitialized olayını kullanmak iyi bir yerdir:

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 işlevini devre dışı bırakmak için kolay yöntem, yalnızca İptal olayını bağlamak ve pencereyi gerçekten kapatmak istediğinizde bir bayrak ayarlamaktır.


0

XAML Kodu

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

çalışmalı

Düzenle - anında bu iş parçacığı nasıl yapılabilir gösterir ama normal başlık çubuğunu kaybetmeden istediğiniz bir pencere almak için bir özellik olduğunu sanmıyorum.

Düzenle 2 Bu İş Parçacığı bunun gerçekleştirilmesi için bir yol gösterir, ancak kendi stilinizi sistem menüsüne uygulamanız gerekir ve bunu nasıl yapabileceğinizi gösterir.


nedense "çalışması gerekir" görüntülendi, ancak şimdi güncellendi
TStamper

3
Başlık çubuğundaki Pencere durumundan bahsediyorum. Bu basit bir düğmeyi düzenlemek gibi görünüyor.
Michael Hedgpeth

@TStamper, snippet'inizi nasıl kullanırım? Genel bir Pencere stili (ve şablonu) kullanıyorum.
Shimmy Weitzhandler

@ Shimmy- hangisine atıfta bulunuyorsun?
TStamper

0

Pencereye bir Kapanış olayı eklemeyi deneyin. Bu kodu olay işleyicisine ekleyin.

e.Cancel = true;

Bu pencerenin kapanmasını önleyecektir. Bu, kapat düğmesini gizlemekle aynı etkiye sahiptir.


1
"Bu, kapat düğmesini gizlemekle aynı etkiye sahiptir." , düğme hala görülebilir ve tıklanabilir olduğunu hariç animasyonlu ve bunu tıkladığınızda görsel karartıyor oluyor - yani meydan okuyan hangi Pola .
rory.ap

0

Bunu https://stephenhaunts.com/2014/09/25/remove-the-close-button-from-a-wpf-window adresinden değiştirilmiş olarak kullanın :

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

Bu düğmeyi gizlemez, ancak pencereyi kapatarak kullanıcının ilerlemesini önler.

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

-1

pencere özellikleri kümesine git

window style = none;

u yakın düğmeleri almak alışkanlık ...


Downvote. Aslında WindowStyle = "None"- sentaksını izle. Bir diğeri için, başlık çubuğunu da kaldıran, kutuyu çirkin hale getiren ve bir başlıktan yoksun, (diğer cevaplar tarafından kanıtlandığı gibi) bunu işlemek için çok daha iyi yollar olduğunda ve mükerrer bir cevap olan bir av tüfeği yaklaşımıdır.
vapcguy

-1

Diğer yanıtlarda belirtildiği gibi WindowStyle="None", Başlık Çubuğunu tamamen kaldırmak için kullanabilirsiniz .

Ve bu diğer cevapların yorumlarında belirtildiği gibi, bu pencerenin sürüklenebilir olmasını önler, böylece ilk konumundan hareket ettirmek zordur.

Ancak, Window'un Arkasındaki Kod dosyasındaki Yapıcıya tek bir kod satırı ekleyerek bunun üstesinden gelebilirsiniz:

MouseDown += delegate { DragMove(); };

Veya Lambda Sözdizimini tercih ediyorsanız:

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

Bu, tüm Pencereyi sürüklenebilir hale getirir. Pencerede bulunan Düğmeler gibi etkileşimli denetimler normal olarak çalışmaya devam eder ve Pencere için sürükleme tutamağı işlevi görmez.


Hala kötü bir fikir. Tüm başlık çubuğunu kaldırır, bu da bir av tüfeği yaklaşımı yapar ve kutuyu çirkin gösterir ve bunun için başlık / açıklama olmadığı anlamına gelir. Çok daha iyi alternatifler var.
vapcguy

@vapcguy Başlık çubuğunun tamamını kaldırır. Bir av tüfeği yaklaşımıdır. Kutuyu çirkin gösteriyor mu? Senin görüşün. Çok daha iyi alternatifler? Belki senin için. Herkes için değil. :-)
Holf

-1

Bunun cevabını aradıktan sonra, burada başkalarına yardımcı olması umuduyla paylaşacağım bu basit çözümü buldum.

Ben ayarladım WindowStyle=0x10000000.

Bu , Pencere Stili için WS_VISIBLE (0x10000000)ve WS_OVERLAPPED (0x0)değerlerini ayarlar . "Üst üste binmiş" başlık çubuğunu ve pencere kenarlığını göstermek için gerekli değerdir. Kaldırarak WS_MINIMIZEBOX (0x20000), WS_MAXIMIZEBOX (0x10000)ve WS_SYSMENU (0x80000)benim tarzım değerinden değerleri başlık çubuğundan tüm düğmeleri Kapat düğmesi de dahil olmak üzere kaldırılmıştır.


WPF'de WindowStyledeğerleri Windows API sabitleriyle eşleşmeyen bir numaralandırmadır; değeri WindowStylenumaralandırmaya zorlamak işe yaramaz. Emin olmak için, ILSpy .NET kaynak kodunu kontrol ettim; enum değeri özel işlevde Windows API'sine çevrilir CreateWindowStyleve işlev bilinmeyen bir WindowStyledeğerle karşılaşırsa uygulanır WindowStyle.None. (Tek yolu iç özelliklerini kullanmak olacaktır _Styleve _StyleExşiddetle karşı tavsiye hangi kullanılarak yansıma.)
Mike Rosoft


-2

İhtiyaç sadece kullanıcının pencereyi kapatmasını engellemekse, bu basit bir çözümdür.

XAML kodu: IsCloseButtonEnabled="False"

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.