Advanced Java Services | Disable and Enable Systembuttons in WPF |
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.
this.ResizeMode = ResizeMode.CanResize; // ändert nichts this.WindowStyle = WindowStyle.SingleBorderWindow; // ändert nichts this.ResizeMode = ResizeMode.CanResizeWithGrip; // zeigt den grip
this.ResizeMode = ResizeMode.NoResize; // verschwindet Min- und MaxSystembutton this.WindowStyle = WindowStyle.ToolWindow; // verschwindet Min- und MaxSystembutton, Titelzeile wird etwas kleiner
this.ResizeMode = ResizeMode.CanMinimize; // disables MaxSystemButton
Es gibt kein CanMaximize...
this.WindowStyle = WindowStyle.None; // ganze Titelzeile weg
Anwendung kann noch mit ALT+F4 beendet werden.
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.
Wir brauchen die folgenden zwei using-Anweisungen
using System.Runtime.InteropServices; using System.Windows.Interop;
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);
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 //... }
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); } ... } ... }
// 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.
Um an den CloseButton heranzukommen braucht man die WinAPI-Funktionen GetSystemMenu() und RemoveMenu().
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.
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); } ... } ... }
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.
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); } } }
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