Advanced   Java   Services Disable and Enable Systembuttons in WPF Back Next Up Home


Die Möglichkeiten von C#

Normalerweise sind alle drei SystemButtons vorhanden und aktiv. Das Setzen der folgenden Styles bzw. Modes ändert nichts an den drei SystemButtons. this bezeichne hier und im folgenden ein TopLevel-Fenster. Mit den Properties ResizeMode und WindowStyle kann man die folgenden Einstellungen vornehmen.

ms-windowstyles-1.jpg

this.ResizeMode = ResizeMode.CanResize;  // ändert nichts
this.WindowStyle = WindowStyle.SingleBorderWindow;  // ändert nichts
this.ResizeMode = ResizeMode.CanResizeWithGrip;  // zeigt den grip

Min- und MaxSystembutton entfernen, CloseButton bleibt aktiv

ms-windowstyles-2.jpg

this.ResizeMode = ResizeMode.NoResize;  // verschwindet Min- und MaxSystembutton
this.WindowStyle = WindowStyle.ToolWindow; // verschwindet Min- und MaxSystembutton, Titelzeile wird etwas kleiner

MaxSystemButton deaktivieren, Min- und CloseSystemButton aktiv

ms-windowstyles-3.jpg

this.ResizeMode = ResizeMode.CanMinimize;  // disables MaxSystemButton

Es gibt kein CanMaximize...


Ganze Titelzeile verschwinden lassen

ms-windowstyles-4.jpg

this.WindowStyle = WindowStyle.None;  // ganze Titelzeile weg

Anwendung kann noch mit ALT+F4 beendet werden.


Zugriff auf die WinApi-Funktionen

Für weitere Einstellungen muß man WinApi-Funktionen benützen, die man in C# relativ leicht importieren kann. Hier zunächst das Vorgehen für den Zugriff auf die WinApi-Funktionen.


Notwendige usings

Wir brauchen die folgenden zwei using-Anweisungen

using System.Runtime.InteropServices;
using System.Windows.Interop;

WinApi-Funktionen importieren

Die WinApi-Funktionen werden als statische externe Funktionen vorgestellt. Es folgen die Funktionen, die für das Manipulieren der Systembuttons gebraucht werden. das Schema ist aber immer das gleiche.

[DllImport("User32.dll", EntryPoint = "GetWindowLong")]
private extern static Int32 GetWindowLongPtr(IntPtr hWnd, Int32 nIndex);

[DllImport("User32.dll", EntryPoint = "SetWindowLong")]
private extern static Int32 SetWindowLongPtr(IntPtr hWnd, Int32 nIndex, Int32 dwNewLong);

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

[DllImport("user32.dll")]
static extern uint RemoveMenu(IntPtr hMenu, uint nPosition, uint wFlags);

Die später vorgestellte Hilfsklasse SysMenuUtil verwendet auch noch die folgende Funktion.

[DllImport("user32.dll")]
static extern bool DrawMenuBar(IntPtr hWnd);

OnSourceInitialized(EventArgs e)

Will man die Änderungen am Systemmenu dauerhaft einrichten, so überschreibt man die Methode OnSourceInitialized(EventArgs e). Diese Methode wird nach dem Konstruktor gerufen, aber ausgeführt bevor das Fenster sichtbar wird. Im Konstruktor sind diese Aufrufe wirkungslos, da die Titelzeile des Fensters noch nicht im Hauptspeicher angelegt ist. Um die WinApi-Funktionen aufzurufen braucht man einen Pointer (Handle //2) auf das Fenster, den man über eine Instanz vom Typ WindowInteropHelper (//1)erhält. Danach ruft man die WinApi-Funktionen als klassische Funktionen ohne Klassenbezug auf (//3 und //4). Die Werte der Konstanten folgen in den nächsten Beispielen.

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

  WindowInteropHelper wih = new WindowInteropHelper(this); //1
  IntPtr hWnd = wih.Handle;  //2

  Int32 windowStyle = GetWindowLongPtr(hWnd, GWL_STYLE); //3
  // MaxSysbutton disabled
  SetWindowLongPtr(hWnd, GWL_STYLE, windowStyle & ~WS_MAXIMIZEBOX); //4

  //...
}






MinSystemButton deaktivieren, Max- und CloseSystemButton aktiv

ms-windowstyles-5.jpg

Für diese und die nächste Konfiguration brauchen wir die Funktionen GetWindowLongPtr() und SetWindowLongPtr() und drei Konstanten. Die Funktionen müssen in der Methode OnSourceInitialized() aufgerufen werden. Diese Methode wird nach dem Konstruktor abgearbeitet. Im Konstruktor sind diese Methoden wirkungslos.

using System.Runtime.InteropServices;
using System.Windows.Interop;
...

namespace WpfApplication1
{
  public partial class Window1 : Window
  {
    private const Int32 GWL_STYLE = -16;
    private const Int32 WS_MAXIMIZEBOX = 0x00010000;
    private const Int32 WS_MINIMIZEBOX = 0x00020000;
    private const Int32 WS_SYSMENU = 0x80000;


    [DllImport("User32.dll", EntryPoint = "GetWindowLong")]
    private extern static Int32 GetWindowLongPtr(IntPtr hWnd, Int32 nIndex);

    [DllImport("User32.dll", EntryPoint = "SetWindowLong")]
    private extern static Int32 SetWindowLongPtr(IntPtr hWnd, Int32 nIndex, Int32 dwNewLong);


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

      WindowInteropHelper wih = new WindowInteropHelper(this);
      IntPtr hWnd = wih.Handle;
      Int32 windowStyle = GetWindowLongPtr(hWnd, GWL_STYLE);

      //MinSysbutton disabled
      SetWindowLongPtr(hWnd, GWL_STYLE, windowStyle & ~WS_MINIMIZEBOX);
    }
    ...
  }
  ...
}

Keine SystemButtons

ms-windowstyles-6.jpg

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

      WindowInteropHelper wih = new WindowInteropHelper(this);
      IntPtr hWnd = wih.Handle;
      Int32 windowStyle = GetWindowLongPtr(hWnd, GWL_STYLE);

      //MinSysbutton disabled
      SetWindowLongPtr(hWnd, GWL_STYLE, windowStyle & ~WS_SYSMENU);
    }
    ...
  }
  ...
}

Bemerkung: Die Anwendung kann noch mit ALT+F4 beendet werden.


CloseSystemButton deaktiviert

Um an den CloseButton heranzukommen braucht man die WinAPI-Funktionen GetSystemMenu() und RemoveMenu().

ms-windowstyles-7.jpg

using System.Runtime.InteropServices;
using System.Windows.Interop;
...

namespace WpfApplication1
{
  public partial class Window1 : Window
  {
    private const Int32 GWL_STYLE = -16;
    private const uint MF_BYCOMMAND  = 0x00000000;
    private const uint MF_BYPOSITION = 0x00000400;
    private const uint SC_CLOSE      = 0xF060;

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

    [DllImport("user32.dll")]
    static extern uint RemoveMenu(IntPtr hMenu, uint nPosition, uint wFlags);


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

      WindowInteropHelper wih = new WindowInteropHelper(this);
      IntPtr hWnd = wih.Handle;
      IntPtr hMenu = GetSystemMenu(hWnd, false);

      // CloseButton disabled
      RemoveMenu(hMenu, SC_CLOSE, MF_BYCOMMAND);
    }
    ...
  }
  ...
}

Anwendung kann noch mit ALT+F4 beendet werden.


Max- und CloseSystemButton deaktiviert

ms-windowstyles-8.jpg

using System.Runtime.InteropServices;
using System.Windows.Interop;
...

namespace WpfApplication1
{
  public partial class Window1 : Window
  {
    private const Int32 GWL_STYLE = -16;
    private const uint MF_BYCOMMAND  = 0x00000000;
    private const uint MF_BYPOSITION = 0x00000400;
    private const uint SC_CLOSE      = 0xF060;

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

    [DllImport("user32.dll")]
    static extern uint RemoveMenu(IntPtr hMenu, uint nPosition, uint wFlags);

    public Window1()  // Konstruktor
    {
      InitializeComponent();
      this.ResizeMode = ResizeMode.CanMinimize;  // disables MaxSystembutton
    }


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

      WindowInteropHelper wih = new WindowInteropHelper(this);
      IntPtr hWnd = wih.Handle;
      IntPtr hMenu = GetSystemMenu(hWnd, false);

      // CloseButton disabled
      RemoveMenu(hMenu, SC_CLOSE, MF_BYCOMMAND);
    }
    ...
  }
  ...
}

Min- und CloseSystemButton deaktiviert

ms-windowstyles-9.jpg

using System.Runtime.InteropServices;
using System.Windows.Interop;
...

namespace WpfApplication1
{
  public partial class Window1 : Window
  {
    private const Int32 GWL_STYLE = -16;
    private const Int32 WS_MAXIMIZEBOX = 0x00010000;
    private const Int32 WS_MINIMIZEBOX = 0x00020000;
    private const Int32 WS_SYSMENU = 0x80000;

    private const uint MF_BYCOMMAND  = 0x00000000;
    private const uint MF_BYPOSITION = 0x00000400;
    private const uint SC_CLOSE      = 0xF060;

    [DllImport("User32.dll", EntryPoint = "GetWindowLong")]
    private extern static Int32 GetWindowLongPtr(IntPtr hWnd, Int32 nIndex);

    [DllImport("User32.dll", EntryPoint = "SetWindowLong")]
    private extern static Int32 SetWindowLongPtr(IntPtr hWnd, Int32 nIndex, Int32 dwNewLong);

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

    [DllImport("user32.dll")]
    static extern uint RemoveMenu(IntPtr hMenu, uint nPosition, uint wFlags);


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

      WindowInteropHelper wih = new WindowInteropHelper(this);
      IntPtr hWnd = wih.Handle;
      Int32 windowStyle = GetWindowLongPtr(hWnd, GWL_STYLE);
      IntPtr hMenu = GetSystemMenu(hWnd, false);

      // CloseButton disabled
      RemoveMenu(hMenu, SC_CLOSE, MF_BYCOMMAND);

      //MinSysbutton disabled
      SetWindowLongPtr(hWnd, GWL_STYLE, windowStyle & ~WS_MINIMIZEBOX);
    }
    ...
  }
  ...
}

Fenster ist resizable, beenden mit ALT+F4.


Die Hilfsklasse SysMenuUtils

Wendet man die WinApi-SysMenu-Funktionen außerhalb von OnSourceInitialized() an, so muß man selbst dafür sorgen, daß das SysMenu neu gezeichnet wird. Dies wird durch den Aufruf von DrawMenuBar(hWnd) erreicht. Die Klasse hat auch Methoden mit denen man die Veränderungen rückgängig machen kann. Auch dazu benötigt man die Funktion DrawMenuBar(hWnd).

using System;
using System.Windows;
using System.Windows.Interop;
using System.Runtime.InteropServices;

namespace WpfApplication1
{
    class SysMenuUtils
    {
        private const Int32 GWL_STYLE = -16;
        private const Int32 WS_MAXIMIZEBOX = 0x00010000;
        private const Int32 WS_MINIMIZEBOX = 0x00020000;
        private const Int32 WS_SYSMENU     = 0x00080000;
        private const Int32 WS_OVERLAPPED  = 0x00000000;

        private const uint MF_REMOVE     = 0x00001000;
        private const uint MF_DISABLED   = 0x00000002;
        private const uint MF_BYCOMMAND  = 0x00000000;
        private const uint MF_BYPOSITION = 0x00000400;
        private const uint MF_GRAYED     = 0x00000001;
        private const uint MF_ENABLED    = 0x00000000;

        private const uint SC_CLOSE      = 0x0000F060;
        private const uint SC_SIZE       = 0x0000F000; //61440
        private const uint SC_MOVE       = 0x0000F010; //61456

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

        [DllImport("user32.dll")]
        static extern int GetMenuItemCount(IntPtr hMenu);

        [DllImport("user32.dll")]
        static extern uint RemoveMenu(IntPtr hMenu, uint nPosition, uint wFlags);

        [DllImport("user32.dll")]
        static extern bool DrawMenuBar(IntPtr hWnd);

        [DllImport("User32.dll", EntryPoint = "GetWindowLong")]
        private extern static Int32 GetWindowLongPtr(IntPtr hWnd, Int32 nIndex);

        [DllImport("User32.dll", EntryPoint = "SetWindowLong")]
        private extern static Int32 SetWindowLongPtr(IntPtr hWnd, Int32 nIndex, Int32 dwNewLong);


        private SysMenuUtils()
        {}


        public static void disableCloseButton(Window window)
        {
            Console.WriteLine("disableCloseButton");
            WindowInteropHelper wih = new WindowInteropHelper(window);
            IntPtr hWnd = wih.Handle;
            IntPtr hMenu = GetSystemMenu(hWnd, false);
            RemoveMenu(hMenu, SC_CLOSE, MF_BYCOMMAND);
            //oder
            //RemoveMenu(hMenu, menuItemCount-1 , MF_DISABLED | MF_BYPOSITION);
            // es geht nur -1
            DrawMenuBar(hWnd);  // braucht man, wenn man nach OnSourceInitialized arbeitet
        }

        public static void enableCloseButton(Window window)
        {
            WindowInteropHelper wih = new WindowInteropHelper(window);
            IntPtr hWnd = wih.Handle;
            IntPtr hMenu = GetSystemMenu(hWnd, true);  // beachte true
            DrawMenuBar(hWnd);
        }

        public static void disableMaximizeButton(Window window)
        {
            WindowInteropHelper wih = new WindowInteropHelper(window);
            IntPtr hWnd = wih.Handle;
            Int32 windowStyle = GetWindowLongPtr(hWnd, GWL_STYLE);
            SetWindowLongPtr(hWnd, GWL_STYLE, windowStyle & ~WS_MAXIMIZEBOX);
            DrawMenuBar(hWnd);
        }

        public static void enableMaximizeButton(Window window)
        {
            WindowInteropHelper wih = new WindowInteropHelper(window);
            IntPtr hWnd = wih.Handle;
            Int32 windowStyle = GetWindowLongPtr(hWnd, GWL_STYLE);
            SetWindowLongPtr(hWnd, GWL_STYLE, windowStyle | WS_MAXIMIZEBOX);
            DrawMenuBar(hWnd);
        }


        public static void disableMinimizeButton(Window window)
        {
            WindowInteropHelper wih = new WindowInteropHelper(window);
            IntPtr hWnd = wih.Handle;
            Int32 windowStyle = GetWindowLongPtr(hWnd, GWL_STYLE);
            SetWindowLongPtr(hWnd, GWL_STYLE, windowStyle & ~WS_MINIMIZEBOX);
            DrawMenuBar(hWnd);
        }

        public static void enableMinimizeButton(Window window)
        {
            WindowInteropHelper wih = new WindowInteropHelper(window);
            IntPtr hWnd = wih.Handle;
            Int32 windowStyle = GetWindowLongPtr(hWnd, GWL_STYLE);
            SetWindowLongPtr(hWnd, GWL_STYLE, windowStyle | WS_MINIMIZEBOX);
            DrawMenuBar(hWnd);
        }

        public static void hideSysButtons(Window window)
        {
            WindowInteropHelper wih = new WindowInteropHelper(window);
            IntPtr hWnd = wih.Handle;
            Int32 windowStyle = GetWindowLongPtr(hWnd, GWL_STYLE);
            SetWindowLongPtr(hWnd, GWL_STYLE, windowStyle & ~WS_SYSMENU);
            DrawMenuBar(hWnd);
        }

        public static void showSysButtons(Window window)
        {
            WindowInteropHelper wih = new WindowInteropHelper(window);
            IntPtr hWnd = wih.Handle;
            Int32 windowStyle = GetWindowLongPtr(hWnd, GWL_STYLE);
            SetWindowLongPtr(hWnd, GWL_STYLE, windowStyle | WS_SYSMENU);
            DrawMenuBar(hWnd);
        }

        public static void disableMove(Window window)
        {
            Console.WriteLine("disableCloseButton");
            WindowInteropHelper wih = new WindowInteropHelper(window);
            IntPtr hWnd = wih.Handle;
            IntPtr hMenu = GetSystemMenu(hWnd, false);
            RemoveMenu(hMenu, SC_MOVE, MF_BYCOMMAND);
            //oder
            //RemoveMenu(hMenu, menuItemCount-1 , MF_DISABLED | MF_BYPOSITION);
            // es geht nur -1
            DrawMenuBar(hWnd);  // braucht man, wenn man nach OnSourceInitialized arbeitet
        }

        public static void enableMove(Window window)
        {
            WindowInteropHelper wih = new WindowInteropHelper(window);
            IntPtr hWnd = wih.Handle;
            // Damit wird der Defaultzustand wieder hergestellt
            // für die Veränderungen, die mit RemoveMenu gemacht wurden
            IntPtr hMenu = GetSystemMenu(hWnd, true);  // beachte true
            DrawMenuBar(hWnd);
        }

        public static void disableResizing(Window window)
        {
            Console.WriteLine("disableCloseButton");
            WindowInteropHelper wih = new WindowInteropHelper(window);
            IntPtr hWnd = wih.Handle;
            IntPtr hMenu = GetSystemMenu(hWnd, false);
            RemoveMenu(hMenu, SC_SIZE, MF_BYCOMMAND);
            DrawMenuBar(hWnd);  // braucht man, wenn man nach OnSourceInitialized arbeitet
        }

        public static void enableResizing(Window window)
        {
            WindowInteropHelper wih = new WindowInteropHelper(window);
            IntPtr hWnd = wih.Handle;
            IntPtr hMenu = GetSystemMenu(hWnd, true);  // beachte true
            DrawMenuBar(hWnd);
        }
    }
}

Quellen

stackoverflow.com/questions/743906/how-to-hide-close-button-in-wpf-window
coderelief.net/2010/04/19/wpf-window-disable-minimize-and-maximize-buttons-through-attached-properties-from-xaml/
social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/d4cdd362-b9c6-4a10-990c-e2d9fc3e2b03/
techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/tsleft.web+winbatch/Hiding-Disabling~Apps~to~Prevent~User~Intervention+Disable~an~Apps~Close~Menu~Item.txt
msdn.microsoft.com/en-us/library/windows/desktop/ms633584%28v=vs.85%29.aspx

Valid XHTML 1.0 Strict top Back Next Up Home