WPF 창에서 닫기 버튼을 숨기는 방법?


204

WPF에서 모달 대화 상자를 작성 중입니다. 닫기 버튼이 없도록 WPF 창을 어떻게 설정합니까? 나는 여전히 WindowState일반적인 제목 표시 줄을 갖고 싶습니다 .

내가 발견 ResizeMode, WindowState그리고 WindowStyle하지만 이러한 속성 중 어느 것도 나를 닫기 버튼을 숨길 수 없지만 모달 대화 상자에서 같은 제목 표시 줄을 보여줍니다.


9
취소를 지원하지 않는 백그라운드 스레드를 실행하는 진행률 대화 상자입니다. 나는 그것을 취소하려고 노력하고 있다고 생각하므로 취소를 아직 지원하지 않아도됩니다. 그래도 아마 맞을 것입니다.
Michael Hedgpeth 2009

1
나는 또한 윈도우 크롬을 제거하려는 앱이 싫어. 진행률 대화 상자를 만들면 항상 창 닫기 버튼이 실제 취소 버튼을 클릭하는 것과 동일한 논리를 수행합니다.
Christian Hayter

13
Chris의 경우 : 귀하의 소프트웨어가 비디오 감시 용이라고 가정 해 봅시다. 밤 동안 보안 요원이 창을 열어 두어야했습니다 ...하지만 때로는 작업이 지루하며 어떤 이유로 든 인터넷을 서핑하거나 비디오 매트릭스 창을 닫으려고합니다. 창 버튼을 제거하는 것이 올바른 방법입니다 그것을하기 위해.
Jean-Marie

7
@ChrisUpchurch, "왜 이렇게 하시겠습니까? 정말 UI 디자인이 엉망인 것 같습니다." - "UI UI 디자인"은 프로그램이 대화 상자를 OK 로 표시 할 때입니다 . 취소닫기 버튼. 사용자에게는 Close의 기능 이 명확하지 않을 수 있습니다 . 그렇습니다 취소 또는 제출 ? 컨센서스는 대화 상자에 닫기 버튼을 포함시키지 않기 때문에
MickyD

1
@ Jean-Marie 그러나 닫기 버튼을 숨겨도이를 막을 수는 없지만 정보를 얻지 못하고 게으른 (Google에게) 바보입니다. 닫기 버튼을 숨기면 해당 버튼을 클릭 할 수 없습니다. Win 키 및 Alt 키 콤보는 여전히 정상적으로 작동합니다.이를 수행하는 "적절한"방법은 승인 된 것 이외의 소프트웨어를 열거 나 설치하지 못하게하는 그룹 정책을 사용하여 작업자의 사용자 계정을 만드는 것입니다. 관리자가 모든 유지 관리를 위해 액세스 할 수있는 관리자 계정
Digital_Utopia

답변:


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하고 Canceltrue로 설정할 수도 있습니다 .


5
문서에 따르면 SetWindowLongPtr대신 사용해야합니다 .
Jonathan Allen

15
대부분 자체 참고 사항 ... DllImport의 네임 스페이스-> System.Runtime.InteropServices.DllImport. WindowInteropHelper의 네임 스페이스-> System.Windows.Interop.WindowInteropHelper
doobop

3
실제로이 방법은 세 개의 버튼 (최소, 최대 및 닫기)을 모두 숨 깁니다. 닫기 버튼 만 숨길 수 있습니까?
newman

4
@miliu, 아뇨. 당신은 할 수 비활성화 ,하지만 당신은 그것을 숨길 수없이 숨어 최소화 / 최대화뿐만 아니라. Windows 개발자가 Maximize가 Close가있는 곳의 오른쪽에 있으면 혼란 스러울 것이라고 생각한 것 같습니다.
Joe White

3
XAML 파일의 Window 태그에 WindowStyle = "None"을 입력하십시오.
diegodsp

88

방금 비슷한 문제가 발생하여 Joe White의 솔루션 이 간단하고 깨끗해 보입니다. 재사용하고 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
글쎄, 이것은 창 제목 표시 줄을 완전히 숨길 것입니다. 그것은 당신이 창 제목을 얻지 못하고 사용자가 창을 이동할 수 없다는 것을 의미합니다.
newman

6
this.DragMove();MouseDown이벤트 에 추가하여 창을 움직일 수 있습니다.
paul

1
열려있는 오래된 스키마로 데이터베이스를 업그레이드하는 과정과 같이 정보를 제공하고 필수적이어야하는 모달 대화 상자의 경우이 솔루션은 완벽합니다.
외로운 코더

1
하지만 어떤 사람들은 국경을 갖고 싶어합니다
pjdupreez

2
확실히 최고의 솔루션입니다. 패널에 테두리를 추가하거나 이동을 구현하는 데 아무런 문제가 없습니다.
buks

50

이것은 닫기 버튼을 제거하지는 않지만 누군가가 창을 닫는 것을 막을 것입니다.

이것을 코드 뒤에 파일 뒤에 넣으십시오.

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

7
Window모달 대화 상자로 설정된 에서이 작업을 수행하면 속성 Window설정 이 방해되어 DialogResult사용할 수 없게 될 수 있습니다. stackoverflow.com/questions/898708/cant-set-dialogresult-in-wpf
Sheridan

4
나는이 방법을 사용하여 오버 플로우를 얻고 있었다, 나는 일 다음 base.OnClosing (예) 꺼내서
jacobsgriffith

8
사용자로서 나는 이것을 응용 프로그램에 넣은 프로그래머를 싫어할 것입니다
UrbanEsc

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
버튼을 사용하지 않는 것이 버튼을 제거하는 것보다 낫습니다. 중요한 조작이 실행 중임을 사용자에게 알리면서 일관된 느낌을 유지합니다.
Robert Baker

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내 프로젝트에서 확장 방법 으로 추가되었습니다 .
Matt Davis

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

3
제목 표시 줄 전체를 제거하여 상자를 설명없이 표시합니다. 산탄 총 접근 및 중복 답변. 공감.
vapcguy

항상 애플리케이션을 최대화해야하고 고객이 앱을 닫을 수 없어야하는 키오스크 애플리케이션에 가장 적합한 솔루션입니다. 그래서 UpVote
Rajon Tanducar

8

Interactivity Behavior (System.Windows.Interactivity를 참조해야 함)를 사용하여 Joe White의 답변 구현을 추가 합니다.

암호:

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

백그라운드 스레드가 실행될 때마다 백그라운드 UI 창을 다시 표시하십시오.

    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 창의 일부가 아니지만 OS에서 제어하는 ​​창 프레임의 일부에 속합니다. 즉, 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 이벤트를 연결하고 실제로 창을 닫고 싶을 때 플래그 설정을 사용하는 것입니다.


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
제목 표시 줄에있는 창 상태에 대해 이야기하고 있습니다. 간단한 버튼을 편집하는 것처럼 보입니다.
Michael Hedgpeth 2009

@TStamper, 스 니펫은 어떻게 사용하나요? 전역 창 스타일 (및 템플릿)을 사용하고 있습니다.
Shimmy Weitzhandler가

@ Shimmy- 당신은 어느 것을 언급하고 있습니까?
TStamper

0

창에 Closing 이벤트를 추가하십시오. 이 코드를 이벤트 핸들러에 추가하십시오.

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"-구문을보십시오. 또 다른 방법으로는 샷 막대 방식으로 제목 표시 줄을 제거하고 상자를 못 생기게하고 제목이 부족한 경우 (다른 답변에서 입증 된 것처럼)이를 처리하는 더 많은 방법이 있고 중복 답변입니다.
vapcguy

-1

다른 답변에서 언급했듯이 WindowStyle="None"제목 표시 줄을 모두 제거하는 데 사용할 수 있습니다 .

그리고 다른 답변에 대한 주석에서 언급했듯이 창을 드래그 할 수 없으므로 초기 위치에서 창을 옮기기가 어렵습니다.

그러나 Window의 Code Behind 파일에서 생성자에 한 줄의 코드를 추가하여이를 극복 할 수 있습니다.

MouseDown += delegate { DragMove(); };

또는 Lambda 구문을 선호하는 경우 :

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

그러면 전체 창을 드래그 할 수 있습니다. 버튼과 같이 윈도우에 존재하는 모든 대화 형 컨트롤은 여전히 ​​정상적으로 작동하며 윈도우의 드래그 핸들로 작동하지 않습니다.


여전히 나쁜 생각입니다. 전체 제목 표시 줄을 제거하여 샷건 방식으로 만들고 상자를보기 흉하게 보이게하고 제목 / 설명이 없음을 의미합니다. 훨씬 더 나은 대안이 있습니다.
vapcguy

@vapcguy 전체 제목 표시 줄을 제거합니다. 샷건 접근 방식입니다. 상자를 못 생겼습니까? 당신의 의견. 훨씬 더 나은 대안? 아마도 당신을 위해. 모두를위한 것은 아닙니다. :-)
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

-2

를 사용 WindowStyle="SingleBorderWindow"하면 WPF 창에서 최대 및 최소 버튼이 숨겨집니다.


1
close버튼을 숨기는 문제를 해결하지 못함
꿈의 기억

-2

사용자가 창을 닫는 것을 금지해야하는 경우 이는 간단한 해결책입니다.

XAML 코드 : IsCloseButtonEnabled="False"

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.