Q098. 最大化ボタンを有効にしながら、ユーザーによるサイズ変更を不可にするには?
A.WPF の Window は ResizeMode プロパティを NoResize にすると最大化ボタン等が非表示になります。Window.OnStateCnanged メソッドをオーバーライドするか、HwndSource クラスにメッセージを処理するウィンドウプロシージャを登録します。
本記事は、以下 MSDN フォーラムスレッドの備忘録です。ご了承ください。
関連記事:
Window の手動サイズ変更だけを不可にしたい
Window StateChanging event in WPF
Window.OnStateChanged をオーバーライド
Window.OnStateChanged メソッドをオーバーライドします。OnStateChanged 内で WindowState を設定しているため、OnStateChanged が再帰的に呼び出されますが、この手法を使わないとノーマル状態から最大化する際、画面の最大化ができません。ちょっとややこしいですね。// C# bool _isDuringMaximizing; protected override void OnStateChanged(EventArgs e) { if (WindowState == WindowState.Maximized) { MinWidth = 0; MinHeight = 0; MaxWidth = int.MaxValue; MaxHeight = int.MaxValue; if (!_isDuringMaximizing) { _isDuringMaximizing = true; WindowState = WindowState.Normal; WindowState = WindowState.Maximized; _isDuringMaximizing = false; } } else if (!_isDuringMaximizing) { MinWidth = 1024; MinHeight = 768; MaxWidth = 1024; MaxHeight = 768; } base.OnStateChanged(e); }
' VB.NET Private _isDuringMaximizing As Boolean Protected Overrides Sub OnStateChanged(e As EventArgs) If WindowState = WindowState.Maximized Then MinWidth = 0 MinHeight = 0 MaxWidth = Int32.MaxValue MaxHeight = Int32.MaxValue If Not _isDuringMaximizing Then _isDuringMaximizing = True WindowState = WindowState.Normal WindowState = WindowState.Maximized _isDuringMaximizing = False End If ElseIf Not _isDuringMaximizing Then MinWidth = 1024 MinHeight = 768 MaxWidth = 1024 MaxHeight = 768 End If MyBase.OnStateChanged(e) End Sub
ウィンドウプロシージャ版
メッセージに応じて MaxHeight・MinHeight・MaxWidth・MinWidth を設定するウィンドウプロシージャを作成し、HwndSource.AddHook メソッドにフックとして登録します。// C# using System; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Interop; namespace WpfApplication1 { public partial class MainWindow : Window { private static readonly int SYSCOMMAND = 0x0112; private static readonly int SC_MINIMIZE = 0xf020; private static readonly int SC_MAXIMIZE = 0xF030; private static readonly int SC_RESTORE = 0xf120; public MainWindow() { InitializeComponent(); this.SourceInitialized += Window1_SourceInitialized; } void Window1_SourceInitialized(object sender, EventArgs e) { HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle); source.AddHook(new HwndSourceHook(WndProc)); } private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { // 元のサイズに戻す if (msg == SYSCOMMAND && SC_RESTORE == wParam.ToInt32()) { this.MaxHeight = this.MinHeight = 350; this.MaxWidth = this.MinWidth = 525; } // 最小化 if (msg == SYSCOMMAND && SC_MINIMIZE == wParam.ToInt32()) { this.MaxHeight = this.MaxWidth = int.MaxValue; this.MinHeight = this.MinWidth = 0.0; } // 最大化 if (msg == SYSCOMMAND && SC_MAXIMIZE == wParam.ToInt32()) { this.MaxHeight = this.MaxWidth = int.MaxValue; this.MinHeight = this.MinWidth = 0.0; } handled = false; return IntPtr.Zero; } } }
' VB.NET Imports System.Runtime.InteropServices Imports System.Windows Imports System.Windows.Interop Class MainWindow Private Shared ReadOnly SYSCOMMAND As Int32 = &H112 Private Shared ReadOnly SC_MINIMIZE As Int32 = &HF020 Private Shared ReadOnly SC_MAXIMIZE As Int32 = &HF030 Private Shared ReadOnly SC_RESTORE As Int32 = &HF120 Public Sub New() InitializeComponent() AddHandler Me.SourceInitialized, AddressOf Window1_SourceInitialized End Sub Private Sub Window1_SourceInitialized(sender As Object, e As EventArgs) Dim source = HwndSource.FromHwnd(New WindowInteropHelper(Me).Handle) source.AddHook(New HwndSourceHook(AddressOf WndProc)) End Sub Private Function WndProc(hwnd As IntPtr, msg As Int32, wParam As IntPtr, lParam As IntPtr, ByRef handled As Boolean) As IntPtr ' 元のサイズに戻す If (msg = SYSCOMMAND And SC_RESTORE = wParam.ToInt32()) Then Me.MaxHeight = 350 : Me.MinHeight = 350 Me.MaxWidth = 525 : Me.MinWidth = 525 End If ' 最小化 If (msg = SYSCOMMAND And SC_MINIMIZE = wParam.ToInt32()) Then Me.MaxHeight = Int32.MaxValue : Me.MaxWidth = Int32.MaxValue Me.MinHeight = 0.0 : Me.MinWidth = 0.0 End If ' 最大化 If (msg = SYSCOMMAND And SC_MAXIMIZE = wParam.ToInt32()) Then Me.MaxHeight = Int32.MaxValue : Me.MaxWidth = Int32.MaxValue Me.MinHeight = 0.0 : Me.MinWidth = 0.0 End If handled = False Return IntPtr.Zero End Function End Class