teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

見直しキャンペーン中

2023/07/29 09:04

投稿

TN8001
TN8001

スコア10111

answer CHANGED
@@ -1,4 +1,4 @@
1
- 歴史的経緯により最小化・最大化は、`SetWindowLong`してください。
1
+ 歴史的経緯により最小化・最大化は、`SetWindowLong`してください。
2
2
 
3
3
  [How do I enable and disable the minimize, maximize, and close buttons in my caption bar? - The Old New Thing](https://devblogs.microsoft.com/oldnewthing/20100604-00/?p=13803)
4
4
 

2

見直しキャンペーン中

2023/07/29 09:03

投稿

TN8001
TN8001

スコア10111

answer CHANGED
@@ -1,179 +1,174 @@
1
- 歴史的経緯により最小化・最大化は、`SetWindowLong`してください。
2
-
3
- [How do I enable and disable the minimize, maximize, and close buttons in my caption bar? - The Old New Thing](https://devblogs.microsoft.com/oldnewthing/20100604-00/?p=13803)
4
-
5
- [WPF: Disabling or Hiding the Minimize, Maximize or Close Button Of a Window - TechNet Articles - United States (English) - TechNet Wiki](https://social.technet.microsoft.com/wiki/contents/articles/29183.wpf-disabling-or-hiding-the-minimize-maximize-or-close-button-of-a-window.aspx)
6
-
7
-
8
- ~~コードも書いてみようと思ったんですが、ちゃんとやろうとすると時間がかかりそうなので取り急ぎ情報だけ^^;~~
9
-
10
- ---
11
-
12
- 参考コードは最初からfalseだった時の手当てがないですね。
13
-
14
- ---
15
-
16
- 個別設定できたほうが一般向けだろうと思うので3つに分けました(一括切り替えも用意しようかとも思いましたが、バインドするとなると煩雑なので省略)
17
-
18
- [NuGet Gallery | Microsoft.Windows.CsWin32 0.1.619-beta](https://www.nuget.org/packages/Microsoft.Windows.CsWin32/0.1.619-beta)
19
- [NuGet Gallery | Microsoft.Xaml.Behaviors.Wpf 1.1.39](https://www.nuget.org/packages/Microsoft.Xaml.Behaviors.Wpf/1.1.39)
20
-
21
- ```xaml
22
- <Window
23
- x:Class="Questions370772.MainWindow"
24
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
25
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
26
- xmlns:Behaviors="http://schemas.microsoft.com/xaml/behaviors"
27
- xmlns:local="clr-namespace:Questions370772"
28
- Width="800"
29
- Height="450">
30
- <Behaviors:Interaction.Behaviors>
31
- <local:WindowButtonBehavior
32
- CloseButtonEnabled="{Binding IsChecked, ElementName=close}"
33
- MaximizeButtonEnabled="{Binding IsChecked, ElementName=maximize}"
34
- MinimizeButtonEnabled="{Binding IsChecked, ElementName=minimize}" />
35
- </Behaviors:Interaction.Behaviors>
36
-
37
- <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
38
- <CheckBox
39
- x:Name="minimize"
40
- VerticalContentAlignment="Center"
41
- Content="最小化ボタンを有効にする" />
42
- <CheckBox
43
- x:Name="maximize"
44
- VerticalContentAlignment="Center"
45
- Content="最大化ボタンを有効にする" />
46
- <CheckBox
47
- x:Name="close"
48
- VerticalContentAlignment="Center"
49
- Content="閉じるボタンを有効にする" />
50
- </StackPanel>
51
- </Window>
52
- ```
53
-
54
- ```C#
55
- using System;
56
- using System.Windows;
57
- using System.Windows.Interop;
58
- using Microsoft.Xaml.Behaviors;
59
- using Windows.Win32.Foundation;
60
-
61
- using static Windows.Win32.PInvoke;
62
- using static Windows.Win32.UI.WindowsAndMessaging.MENU_ITEM_FLAGS;
63
- using static Windows.Win32.UI.WindowsAndMessaging.WINDOW_LONG_PTR_INDEX;
64
- using static Windows.Win32.UI.WindowsAndMessaging.WINDOW_STYLE;
65
-
66
- namespace Questions370772
67
- {
68
- public class WindowButtonBehavior : Behavior<Window>
69
- {
70
- public bool MinimizeButtonEnabled { get => (bool)GetValue(MinimizeButtonEnabledProperty); set => SetValue(MinimizeButtonEnabledProperty, value); }
71
- public static readonly DependencyProperty MinimizeButtonEnabledProperty
72
- = DependencyProperty.Register(nameof(MinimizeButtonEnabled), typeof(bool), typeof(WindowButtonBehavior),
73
- new PropertyMetadata(true, new PropertyChangedCallback(OnMinimizeButtonEnabledChanged)));
74
- private static void OnMinimizeButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
75
- => (d as WindowButtonBehavior)?.OnMinimizeButtonEnabledChanged();
76
-
77
- public bool MaximizeButtonEnabled { get => (bool)GetValue(MaximizeButtonEnabledProperty); set => SetValue(MaximizeButtonEnabledProperty, value); }
78
- public static readonly DependencyProperty MaximizeButtonEnabledProperty
79
- = DependencyProperty.Register(nameof(MaximizeButtonEnabled), typeof(bool), typeof(WindowButtonBehavior),
80
- new PropertyMetadata(true, new PropertyChangedCallback(OnMaximizeButtonEnabledChanged)));
81
- private static void OnMaximizeButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
82
- => (d as WindowButtonBehavior)?.OnMaximizeButtonEnabledChanged();
83
-
84
- public bool CloseButtonEnabled { get => (bool)GetValue(CloseButtonEnabledProperty); set => SetValue(CloseButtonEnabledProperty, value); }
85
- public static readonly DependencyProperty CloseButtonEnabledProperty
86
- = DependencyProperty.Register(nameof(CloseButtonEnabled), typeof(bool), typeof(WindowButtonBehavior),
87
- new PropertyMetadata(true, new PropertyChangedCallback(OnCloseButtonEnabledChanged)));
88
- private static void OnCloseButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
89
- => (d as WindowButtonBehavior)?.OnCloseButtonEnabledChanged();
90
-
91
-
92
- private IntPtr hwnd;
93
-
94
- protected override void OnAttached()
95
- => AssociatedObject.SourceInitialized += AssociatedObject_SourceInitialized;
96
-
97
- private void AssociatedObject_SourceInitialized(object? sender, EventArgs e)
98
- {
99
- AssociatedObject.SourceInitialized -= AssociatedObject_SourceInitialized;
100
-
101
- hwnd = new WindowInteropHelper(AssociatedObject).Handle;
102
-
103
- if (!MinimizeButtonEnabled) OnMinimizeButtonEnabledChanged();
104
- if (!MaximizeButtonEnabled) OnMaximizeButtonEnabledChanged();
105
- if (!CloseButtonEnabled) OnCloseButtonEnabledChanged();
106
- }
107
-
108
- private void OnMinimizeButtonEnabledChanged()
109
- {
110
- if (hwnd == IntPtr.Zero) return;
111
-
112
- if (MinimizeButtonEnabled)
113
- {
114
- SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) | (int)WS_MINIMIZEBOX);
115
- }
116
- else
117
- {
118
- SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) & ~(int)WS_MINIMIZEBOX);
119
- //if (AssociatedObject.WindowState == WindowState.Minimized)
120
- //{
121
- // AssociatedObject.WindowState = WindowState.Normal;
122
- //}
123
- }
124
- }
125
-
126
- private void OnMaximizeButtonEnabledChanged()
127
- {
128
- if (hwnd == IntPtr.Zero) return;
129
-
130
- if (MaximizeButtonEnabled)
131
- {
132
- SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) | (int)WS_MAXIMIZEBOX);
133
- }
134
- else
135
- {
136
- SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) & ~(int)WS_MAXIMIZEBOX);
137
- //if (AssociatedObject.WindowState == WindowState.Maximized)
138
- //{
139
- // AssociatedObject.WindowState = WindowState.Normal;
140
- //}
141
- }
142
- }
143
-
144
- private void OnCloseButtonEnabledChanged()
145
- {
146
- if (hwnd == IntPtr.Zero) return;
147
-
148
- var hMenu = GetSystemMenu((HWND)hwnd, false);
149
- if (hMenu != IntPtr.Zero)
150
- {
151
- EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | (CloseButtonEnabled ? MF_ENABLED : MF_GRAYED));
152
- }
153
- }
154
- }
155
-
156
- public partial class MainWindow : Window
157
- {
158
- public MainWindow() => InitializeComponent();
159
- }
160
- }
161
- ```
162
-
163
- NativeMethods.txt
164
- ```EnableMenuItem
165
- GetSystemMenu
166
- GetWindowLong
167
- SetWindowLong
168
- SC_CLOSE
169
- WS_MAXIMIZEBOX
170
- WS_MINIMIZEBOX
171
- ```
172
-
173
- ---
174
-
175
- 最小化・最大化両方禁止した場合は、ボタン自体が消える(Windowsがそういう仕様)
176
-
177
- すでに最大化(最小化)されている状態で、最大化(最小化)を禁止した場合元に戻るべきかどうか。
178
-
1
+ 歴史的経緯により最小化・最大化は、`SetWindowLong`してください。
2
+
3
+ [How do I enable and disable the minimize, maximize, and close buttons in my caption bar? - The Old New Thing](https://devblogs.microsoft.com/oldnewthing/20100604-00/?p=13803)
4
+
5
+ [WPF: Disabling or Hiding the Minimize, Maximize or Close Button Of a Window - TechNet Articles - United States (English) - TechNet Wiki](https://social.technet.microsoft.com/wiki/contents/articles/29183.wpf-disabling-or-hiding-the-minimize-maximize-or-close-button-of-a-window.aspx)
6
+
7
+
8
+ ~~コードも書いてみようと思ったんですが、ちゃんとやろうとすると時間がかかりそうなので取り急ぎ情報だけ^^;~~
9
+
10
+ 参考コードは最初からfalseだった時の手当てがないですね。
11
+
12
+ ---
13
+
14
+ 個別設定できたほうが一般向けだろうと思うので3つに分けました(一括切り替えも用意しようかとも思いましたが、バインドするとなると煩雑なので省略)
15
+
16
+ [NuGet Gallery | Microsoft.Windows.CsWin32 0.1.619-beta](https://www.nuget.org/packages/Microsoft.Windows.CsWin32/0.1.619-beta)
17
+ [NuGet Gallery | Microsoft.Xaml.Behaviors.Wpf 1.1.39](https://www.nuget.org/packages/Microsoft.Xaml.Behaviors.Wpf/1.1.39)
18
+
19
+ ```xml
20
+ <Window
21
+ x:Class="Questions370772.MainWindow"
22
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
23
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
24
+ xmlns:Behaviors="http://schemas.microsoft.com/xaml/behaviors"
25
+ xmlns:local="clr-namespace:Questions370772"
26
+ Width="800"
27
+ Height="450">
28
+ <Behaviors:Interaction.Behaviors>
29
+ <local:WindowButtonBehavior
30
+ CloseButtonEnabled="{Binding IsChecked, ElementName=close}"
31
+ MaximizeButtonEnabled="{Binding IsChecked, ElementName=maximize}"
32
+ MinimizeButtonEnabled="{Binding IsChecked, ElementName=minimize}" />
33
+ </Behaviors:Interaction.Behaviors>
34
+
35
+ <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
36
+ <CheckBox
37
+ x:Name="minimize"
38
+ VerticalContentAlignment="Center"
39
+ Content="最小化ボタンを有効にする" />
40
+ <CheckBox
41
+ x:Name="maximize"
42
+ VerticalContentAlignment="Center"
43
+ Content="最大化ボタンを有効にする" />
44
+ <CheckBox
45
+ x:Name="close"
46
+ VerticalContentAlignment="Center"
47
+ Content="閉じるボタンを有効にする" />
48
+ </StackPanel>
49
+ </Window>
50
+ ```
51
+
52
+ ```cs
53
+ using System;
54
+ using System.Windows;
55
+ using System.Windows.Interop;
56
+ using Microsoft.Xaml.Behaviors;
57
+ using Windows.Win32.Foundation;
58
+
59
+ using static Windows.Win32.PInvoke;
60
+ using static Windows.Win32.UI.WindowsAndMessaging.MENU_ITEM_FLAGS;
61
+ using static Windows.Win32.UI.WindowsAndMessaging.WINDOW_LONG_PTR_INDEX;
62
+ using static Windows.Win32.UI.WindowsAndMessaging.WINDOW_STYLE;
63
+
64
+ namespace Questions370772
65
+ {
66
+ public class WindowButtonBehavior : Behavior<Window>
67
+ {
68
+ public bool MinimizeButtonEnabled { get => (bool)GetValue(MinimizeButtonEnabledProperty); set => SetValue(MinimizeButtonEnabledProperty, value); }
69
+ public static readonly DependencyProperty MinimizeButtonEnabledProperty
70
+ = DependencyProperty.Register(nameof(MinimizeButtonEnabled), typeof(bool), typeof(WindowButtonBehavior),
71
+ new PropertyMetadata(true, new PropertyChangedCallback(OnMinimizeButtonEnabledChanged)));
72
+ private static void OnMinimizeButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
73
+ => (d as WindowButtonBehavior)?.OnMinimizeButtonEnabledChanged();
74
+
75
+ public bool MaximizeButtonEnabled { get => (bool)GetValue(MaximizeButtonEnabledProperty); set => SetValue(MaximizeButtonEnabledProperty, value); }
76
+ public static readonly DependencyProperty MaximizeButtonEnabledProperty
77
+ = DependencyProperty.Register(nameof(MaximizeButtonEnabled), typeof(bool), typeof(WindowButtonBehavior),
78
+ new PropertyMetadata(true, new PropertyChangedCallback(OnMaximizeButtonEnabledChanged)));
79
+ private static void OnMaximizeButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
80
+ => (d as WindowButtonBehavior)?.OnMaximizeButtonEnabledChanged();
81
+
82
+ public bool CloseButtonEnabled { get => (bool)GetValue(CloseButtonEnabledProperty); set => SetValue(CloseButtonEnabledProperty, value); }
83
+ public static readonly DependencyProperty CloseButtonEnabledProperty
84
+ = DependencyProperty.Register(nameof(CloseButtonEnabled), typeof(bool), typeof(WindowButtonBehavior),
85
+ new PropertyMetadata(true, new PropertyChangedCallback(OnCloseButtonEnabledChanged)));
86
+ private static void OnCloseButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
87
+ => (d as WindowButtonBehavior)?.OnCloseButtonEnabledChanged();
88
+
89
+
90
+ private IntPtr hwnd;
91
+
92
+ protected override void OnAttached()
93
+ => AssociatedObject.SourceInitialized += AssociatedObject_SourceInitialized;
94
+
95
+ private void AssociatedObject_SourceInitialized(object? sender, EventArgs e)
96
+ {
97
+ AssociatedObject.SourceInitialized -= AssociatedObject_SourceInitialized;
98
+
99
+ hwnd = new WindowInteropHelper(AssociatedObject).Handle;
100
+
101
+ if (!MinimizeButtonEnabled) OnMinimizeButtonEnabledChanged();
102
+ if (!MaximizeButtonEnabled) OnMaximizeButtonEnabledChanged();
103
+ if (!CloseButtonEnabled) OnCloseButtonEnabledChanged();
104
+ }
105
+
106
+ private void OnMinimizeButtonEnabledChanged()
107
+ {
108
+ if (hwnd == IntPtr.Zero) return;
109
+
110
+ if (MinimizeButtonEnabled)
111
+ {
112
+ SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) | (int)WS_MINIMIZEBOX);
113
+ }
114
+ else
115
+ {
116
+ SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) & ~(int)WS_MINIMIZEBOX);
117
+ //if (AssociatedObject.WindowState == WindowState.Minimized)
118
+ //{
119
+ // AssociatedObject.WindowState = WindowState.Normal;
120
+ //}
121
+ }
122
+ }
123
+
124
+ private void OnMaximizeButtonEnabledChanged()
125
+ {
126
+ if (hwnd == IntPtr.Zero) return;
127
+
128
+ if (MaximizeButtonEnabled)
129
+ {
130
+ SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) | (int)WS_MAXIMIZEBOX);
131
+ }
132
+ else
133
+ {
134
+ SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) & ~(int)WS_MAXIMIZEBOX);
135
+ //if (AssociatedObject.WindowState == WindowState.Maximized)
136
+ //{
137
+ // AssociatedObject.WindowState = WindowState.Normal;
138
+ //}
139
+ }
140
+ }
141
+
142
+ private void OnCloseButtonEnabledChanged()
143
+ {
144
+ if (hwnd == IntPtr.Zero) return;
145
+
146
+ var hMenu = GetSystemMenu((HWND)hwnd, false);
147
+ if (hMenu != IntPtr.Zero)
148
+ {
149
+ EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | (CloseButtonEnabled ? MF_ENABLED : MF_GRAYED));
150
+ }
151
+ }
152
+ }
153
+
154
+ public partial class MainWindow : Window
155
+ {
156
+ public MainWindow() => InitializeComponent();
157
+ }
158
+ }
159
+ ```
160
+
161
+ ```txt:NativeMethods.txt
162
+ EnableMenuItem
163
+ GetSystemMenu
164
+ GetWindowLong
165
+ SetWindowLong
166
+ SC_CLOSE
167
+ WS_MAXIMIZEBOX
168
+ WS_MINIMIZEBOX
169
+ ```
170
+
171
+ 最小化・最大化両方禁止した場合は、ボタン自体が消える(Windowsがそういう仕様)
172
+ すでに最大化(最小化)されている状態で、最大化(最小化)を禁止した場合元に戻るべきかどうか。
173
+
179
174
  2つ目のリンクでは`menuHandle`を使いまわし最後に`DestroyMenu`しろと言っているが、都度取得しないと動作しなかった。`

1

コード追記

2021/11/24 23:46

投稿

TN8001
TN8001

スコア10111

answer CHANGED
@@ -5,8 +5,175 @@
5
5
  [WPF: Disabling or Hiding the Minimize, Maximize or Close Button Of a Window - TechNet Articles - United States (English) - TechNet Wiki](https://social.technet.microsoft.com/wiki/contents/articles/29183.wpf-disabling-or-hiding-the-minimize-maximize-or-close-button-of-a-window.aspx)
6
6
 
7
7
 
8
- コードも書いてみようと思ったんですが、ちゃんとやろうとすると時間がかかりそうなので取り急ぎ情報だけ^^;
8
+ ~~コードも書いてみようと思ったんですが、ちゃんとやろうとすると時間がかかりそうなので取り急ぎ情報だけ^^;~~
9
9
 
10
10
  ---
11
11
 
12
- 参考コードは最初からfalseだった時の手当てがないですね。
12
+ 参考コードは最初からfalseだった時の手当てがないですね。
13
+
14
+ ---
15
+
16
+ 個別設定できたほうが一般向けだろうと思うので3つに分けました(一括切り替えも用意しようかとも思いましたが、バインドするとなると煩雑なので省略)
17
+
18
+ [NuGet Gallery | Microsoft.Windows.CsWin32 0.1.619-beta](https://www.nuget.org/packages/Microsoft.Windows.CsWin32/0.1.619-beta)
19
+ [NuGet Gallery | Microsoft.Xaml.Behaviors.Wpf 1.1.39](https://www.nuget.org/packages/Microsoft.Xaml.Behaviors.Wpf/1.1.39)
20
+
21
+ ```xaml
22
+ <Window
23
+ x:Class="Questions370772.MainWindow"
24
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
25
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
26
+ xmlns:Behaviors="http://schemas.microsoft.com/xaml/behaviors"
27
+ xmlns:local="clr-namespace:Questions370772"
28
+ Width="800"
29
+ Height="450">
30
+ <Behaviors:Interaction.Behaviors>
31
+ <local:WindowButtonBehavior
32
+ CloseButtonEnabled="{Binding IsChecked, ElementName=close}"
33
+ MaximizeButtonEnabled="{Binding IsChecked, ElementName=maximize}"
34
+ MinimizeButtonEnabled="{Binding IsChecked, ElementName=minimize}" />
35
+ </Behaviors:Interaction.Behaviors>
36
+
37
+ <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
38
+ <CheckBox
39
+ x:Name="minimize"
40
+ VerticalContentAlignment="Center"
41
+ Content="最小化ボタンを有効にする" />
42
+ <CheckBox
43
+ x:Name="maximize"
44
+ VerticalContentAlignment="Center"
45
+ Content="最大化ボタンを有効にする" />
46
+ <CheckBox
47
+ x:Name="close"
48
+ VerticalContentAlignment="Center"
49
+ Content="閉じるボタンを有効にする" />
50
+ </StackPanel>
51
+ </Window>
52
+ ```
53
+
54
+ ```C#
55
+ using System;
56
+ using System.Windows;
57
+ using System.Windows.Interop;
58
+ using Microsoft.Xaml.Behaviors;
59
+ using Windows.Win32.Foundation;
60
+
61
+ using static Windows.Win32.PInvoke;
62
+ using static Windows.Win32.UI.WindowsAndMessaging.MENU_ITEM_FLAGS;
63
+ using static Windows.Win32.UI.WindowsAndMessaging.WINDOW_LONG_PTR_INDEX;
64
+ using static Windows.Win32.UI.WindowsAndMessaging.WINDOW_STYLE;
65
+
66
+ namespace Questions370772
67
+ {
68
+ public class WindowButtonBehavior : Behavior<Window>
69
+ {
70
+ public bool MinimizeButtonEnabled { get => (bool)GetValue(MinimizeButtonEnabledProperty); set => SetValue(MinimizeButtonEnabledProperty, value); }
71
+ public static readonly DependencyProperty MinimizeButtonEnabledProperty
72
+ = DependencyProperty.Register(nameof(MinimizeButtonEnabled), typeof(bool), typeof(WindowButtonBehavior),
73
+ new PropertyMetadata(true, new PropertyChangedCallback(OnMinimizeButtonEnabledChanged)));
74
+ private static void OnMinimizeButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
75
+ => (d as WindowButtonBehavior)?.OnMinimizeButtonEnabledChanged();
76
+
77
+ public bool MaximizeButtonEnabled { get => (bool)GetValue(MaximizeButtonEnabledProperty); set => SetValue(MaximizeButtonEnabledProperty, value); }
78
+ public static readonly DependencyProperty MaximizeButtonEnabledProperty
79
+ = DependencyProperty.Register(nameof(MaximizeButtonEnabled), typeof(bool), typeof(WindowButtonBehavior),
80
+ new PropertyMetadata(true, new PropertyChangedCallback(OnMaximizeButtonEnabledChanged)));
81
+ private static void OnMaximizeButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
82
+ => (d as WindowButtonBehavior)?.OnMaximizeButtonEnabledChanged();
83
+
84
+ public bool CloseButtonEnabled { get => (bool)GetValue(CloseButtonEnabledProperty); set => SetValue(CloseButtonEnabledProperty, value); }
85
+ public static readonly DependencyProperty CloseButtonEnabledProperty
86
+ = DependencyProperty.Register(nameof(CloseButtonEnabled), typeof(bool), typeof(WindowButtonBehavior),
87
+ new PropertyMetadata(true, new PropertyChangedCallback(OnCloseButtonEnabledChanged)));
88
+ private static void OnCloseButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
89
+ => (d as WindowButtonBehavior)?.OnCloseButtonEnabledChanged();
90
+
91
+
92
+ private IntPtr hwnd;
93
+
94
+ protected override void OnAttached()
95
+ => AssociatedObject.SourceInitialized += AssociatedObject_SourceInitialized;
96
+
97
+ private void AssociatedObject_SourceInitialized(object? sender, EventArgs e)
98
+ {
99
+ AssociatedObject.SourceInitialized -= AssociatedObject_SourceInitialized;
100
+
101
+ hwnd = new WindowInteropHelper(AssociatedObject).Handle;
102
+
103
+ if (!MinimizeButtonEnabled) OnMinimizeButtonEnabledChanged();
104
+ if (!MaximizeButtonEnabled) OnMaximizeButtonEnabledChanged();
105
+ if (!CloseButtonEnabled) OnCloseButtonEnabledChanged();
106
+ }
107
+
108
+ private void OnMinimizeButtonEnabledChanged()
109
+ {
110
+ if (hwnd == IntPtr.Zero) return;
111
+
112
+ if (MinimizeButtonEnabled)
113
+ {
114
+ SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) | (int)WS_MINIMIZEBOX);
115
+ }
116
+ else
117
+ {
118
+ SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) & ~(int)WS_MINIMIZEBOX);
119
+ //if (AssociatedObject.WindowState == WindowState.Minimized)
120
+ //{
121
+ // AssociatedObject.WindowState = WindowState.Normal;
122
+ //}
123
+ }
124
+ }
125
+
126
+ private void OnMaximizeButtonEnabledChanged()
127
+ {
128
+ if (hwnd == IntPtr.Zero) return;
129
+
130
+ if (MaximizeButtonEnabled)
131
+ {
132
+ SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) | (int)WS_MAXIMIZEBOX);
133
+ }
134
+ else
135
+ {
136
+ SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) & ~(int)WS_MAXIMIZEBOX);
137
+ //if (AssociatedObject.WindowState == WindowState.Maximized)
138
+ //{
139
+ // AssociatedObject.WindowState = WindowState.Normal;
140
+ //}
141
+ }
142
+ }
143
+
144
+ private void OnCloseButtonEnabledChanged()
145
+ {
146
+ if (hwnd == IntPtr.Zero) return;
147
+
148
+ var hMenu = GetSystemMenu((HWND)hwnd, false);
149
+ if (hMenu != IntPtr.Zero)
150
+ {
151
+ EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | (CloseButtonEnabled ? MF_ENABLED : MF_GRAYED));
152
+ }
153
+ }
154
+ }
155
+
156
+ public partial class MainWindow : Window
157
+ {
158
+ public MainWindow() => InitializeComponent();
159
+ }
160
+ }
161
+ ```
162
+
163
+ NativeMethods.txt
164
+ ```EnableMenuItem
165
+ GetSystemMenu
166
+ GetWindowLong
167
+ SetWindowLong
168
+ SC_CLOSE
169
+ WS_MAXIMIZEBOX
170
+ WS_MINIMIZEBOX
171
+ ```
172
+
173
+ ---
174
+
175
+ 最小化・最大化両方禁止した場合は、ボタン自体が消える(Windowsがそういう仕様)
176
+
177
+ すでに最大化(最小化)されている状態で、最大化(最小化)を禁止した場合元に戻るべきかどうか。
178
+
179
+ 2つ目のリンクでは`menuHandle`を使いまわし最後に`DestroyMenu`しろと言っているが、都度取得しないと動作しなかった。`