回答編集履歴

3

見直しキャンペーン中

2023/07/29 09:04

投稿

TN8001
TN8001

スコア9357

test 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

スコア9357

test CHANGED
@@ -1,357 +1,174 @@
1
1
  歴史的経緯により最小化・最大化は、`SetWindowLong`してください。
2
2
 
3
-
4
-
5
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)
6
-
7
-
8
4
 
9
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)
10
6
 
11
7
 
12
-
13
-
14
-
15
8
  ~~コードも書いてみようと思ったんですが、ちゃんとやろうとすると時間がかかりそうなので取り急ぎ情報だけ^^;~~
16
9
 
17
-
10
+ 参考コードは最初からfalseだった時の手当てがないですね。
18
11
 
19
12
  ---
20
13
 
21
-
22
-
23
- 参考コードは最初からfalseだった時の手当てがないですね。
24
-
25
-
26
-
27
- ---
28
-
29
-
30
-
31
14
  個別設定できたほうが一般向けだろうと思うので3つに分けました(一括切り替えも用意しようかとも思いましたが、バインドするとなると煩雑なので省略)
32
15
 
33
-
34
-
35
16
  [NuGet Gallery | Microsoft.Windows.CsWin32 0.1.619-beta](https://www.nuget.org/packages/Microsoft.Windows.CsWin32/0.1.619-beta)
36
-
37
17
  [NuGet Gallery | Microsoft.Xaml.Behaviors.Wpf 1.1.39](https://www.nuget.org/packages/Microsoft.Xaml.Behaviors.Wpf/1.1.39)
38
18
 
39
-
40
-
41
- ```xaml
19
+ ```xml
42
-
43
20
  <Window
44
-
45
21
  x:Class="Questions370772.MainWindow"
46
-
47
22
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
48
-
49
23
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
50
-
51
24
  xmlns:Behaviors="http://schemas.microsoft.com/xaml/behaviors"
52
-
53
25
  xmlns:local="clr-namespace:Questions370772"
54
-
55
26
  Width="800"
56
-
57
27
  Height="450">
58
-
59
28
  <Behaviors:Interaction.Behaviors>
60
-
61
29
  <local:WindowButtonBehavior
62
-
63
30
  CloseButtonEnabled="{Binding IsChecked, ElementName=close}"
64
-
65
31
  MaximizeButtonEnabled="{Binding IsChecked, ElementName=maximize}"
66
-
67
32
  MinimizeButtonEnabled="{Binding IsChecked, ElementName=minimize}" />
68
-
69
33
  </Behaviors:Interaction.Behaviors>
70
34
 
71
-
72
-
73
35
  <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
74
-
75
36
  <CheckBox
76
-
77
37
  x:Name="minimize"
78
-
79
38
  VerticalContentAlignment="Center"
80
-
81
39
  Content="最小化ボタンを有効にする" />
82
-
83
40
  <CheckBox
84
-
85
41
  x:Name="maximize"
86
-
87
42
  VerticalContentAlignment="Center"
88
-
89
43
  Content="最大化ボタンを有効にする" />
90
-
91
44
  <CheckBox
92
-
93
45
  x:Name="close"
94
-
95
46
  VerticalContentAlignment="Center"
96
-
97
47
  Content="閉じるボタンを有効にする" />
98
-
99
48
  </StackPanel>
100
-
101
49
  </Window>
102
-
103
50
  ```
104
51
 
105
-
106
-
107
- ```C#
52
+ ```cs
108
-
109
53
  using System;
110
-
111
54
  using System.Windows;
112
-
113
55
  using System.Windows.Interop;
114
-
115
56
  using Microsoft.Xaml.Behaviors;
116
-
117
57
  using Windows.Win32.Foundation;
118
58
 
119
-
120
-
121
59
  using static Windows.Win32.PInvoke;
122
-
123
60
  using static Windows.Win32.UI.WindowsAndMessaging.MENU_ITEM_FLAGS;
124
-
125
61
  using static Windows.Win32.UI.WindowsAndMessaging.WINDOW_LONG_PTR_INDEX;
126
-
127
62
  using static Windows.Win32.UI.WindowsAndMessaging.WINDOW_STYLE;
128
63
 
129
-
130
-
131
64
  namespace Questions370772
132
-
133
65
  {
134
-
135
66
  public class WindowButtonBehavior : Behavior<Window>
136
-
137
67
  {
138
-
139
68
  public bool MinimizeButtonEnabled { get => (bool)GetValue(MinimizeButtonEnabledProperty); set => SetValue(MinimizeButtonEnabledProperty, value); }
140
-
141
69
  public static readonly DependencyProperty MinimizeButtonEnabledProperty
142
-
143
70
  = DependencyProperty.Register(nameof(MinimizeButtonEnabled), typeof(bool), typeof(WindowButtonBehavior),
144
-
145
71
  new PropertyMetadata(true, new PropertyChangedCallback(OnMinimizeButtonEnabledChanged)));
146
-
147
72
  private static void OnMinimizeButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
148
-
149
73
  => (d as WindowButtonBehavior)?.OnMinimizeButtonEnabledChanged();
150
74
 
151
-
152
-
153
75
  public bool MaximizeButtonEnabled { get => (bool)GetValue(MaximizeButtonEnabledProperty); set => SetValue(MaximizeButtonEnabledProperty, value); }
154
-
155
76
  public static readonly DependencyProperty MaximizeButtonEnabledProperty
156
-
157
77
  = DependencyProperty.Register(nameof(MaximizeButtonEnabled), typeof(bool), typeof(WindowButtonBehavior),
158
-
159
78
  new PropertyMetadata(true, new PropertyChangedCallback(OnMaximizeButtonEnabledChanged)));
160
-
161
79
  private static void OnMaximizeButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
162
-
163
80
  => (d as WindowButtonBehavior)?.OnMaximizeButtonEnabledChanged();
164
81
 
165
-
166
-
167
82
  public bool CloseButtonEnabled { get => (bool)GetValue(CloseButtonEnabledProperty); set => SetValue(CloseButtonEnabledProperty, value); }
168
-
169
83
  public static readonly DependencyProperty CloseButtonEnabledProperty
170
-
171
84
  = DependencyProperty.Register(nameof(CloseButtonEnabled), typeof(bool), typeof(WindowButtonBehavior),
172
-
173
85
  new PropertyMetadata(true, new PropertyChangedCallback(OnCloseButtonEnabledChanged)));
174
-
175
86
  private static void OnCloseButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
176
-
177
87
  => (d as WindowButtonBehavior)?.OnCloseButtonEnabledChanged();
178
-
179
-
180
-
181
88
 
182
89
 
183
90
  private IntPtr hwnd;
184
91
 
185
-
186
-
187
92
  protected override void OnAttached()
188
-
189
93
  => AssociatedObject.SourceInitialized += AssociatedObject_SourceInitialized;
190
94
 
191
-
192
-
193
95
  private void AssociatedObject_SourceInitialized(object? sender, EventArgs e)
194
-
195
96
  {
196
-
197
97
  AssociatedObject.SourceInitialized -= AssociatedObject_SourceInitialized;
198
-
199
-
200
98
 
201
99
  hwnd = new WindowInteropHelper(AssociatedObject).Handle;
202
100
 
203
-
204
-
205
101
  if (!MinimizeButtonEnabled) OnMinimizeButtonEnabledChanged();
206
-
207
102
  if (!MaximizeButtonEnabled) OnMaximizeButtonEnabledChanged();
208
-
209
103
  if (!CloseButtonEnabled) OnCloseButtonEnabledChanged();
210
-
211
104
  }
212
105
 
213
-
214
-
215
106
  private void OnMinimizeButtonEnabledChanged()
216
-
217
107
  {
218
-
219
108
  if (hwnd == IntPtr.Zero) return;
220
109
 
221
-
222
-
223
110
  if (MinimizeButtonEnabled)
224
-
225
111
  {
226
-
227
112
  SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) | (int)WS_MINIMIZEBOX);
228
-
229
113
  }
230
-
231
114
  else
232
-
233
115
  {
234
-
235
116
  SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) & ~(int)WS_MINIMIZEBOX);
236
-
237
117
  //if (AssociatedObject.WindowState == WindowState.Minimized)
238
-
239
118
  //{
240
-
241
119
  // AssociatedObject.WindowState = WindowState.Normal;
242
-
243
120
  //}
244
-
245
121
  }
246
-
247
122
  }
248
123
 
249
-
250
-
251
124
  private void OnMaximizeButtonEnabledChanged()
252
-
253
125
  {
254
-
255
126
  if (hwnd == IntPtr.Zero) return;
256
127
 
257
-
258
-
259
128
  if (MaximizeButtonEnabled)
260
-
261
129
  {
262
-
263
130
  SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) | (int)WS_MAXIMIZEBOX);
264
-
265
131
  }
266
-
267
132
  else
268
-
269
133
  {
270
-
271
134
  SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) & ~(int)WS_MAXIMIZEBOX);
272
-
273
135
  //if (AssociatedObject.WindowState == WindowState.Maximized)
274
-
275
136
  //{
276
-
277
137
  // AssociatedObject.WindowState = WindowState.Normal;
278
-
279
138
  //}
280
-
281
139
  }
282
-
283
140
  }
284
141
 
285
-
286
-
287
142
  private void OnCloseButtonEnabledChanged()
288
-
289
143
  {
290
-
291
144
  if (hwnd == IntPtr.Zero) return;
292
145
 
293
-
294
-
295
146
  var hMenu = GetSystemMenu((HWND)hwnd, false);
296
-
297
147
  if (hMenu != IntPtr.Zero)
298
-
299
148
  {
300
-
301
149
  EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | (CloseButtonEnabled ? MF_ENABLED : MF_GRAYED));
302
-
303
150
  }
304
-
305
151
  }
306
-
307
152
  }
308
153
 
309
-
310
-
311
154
  public partial class MainWindow : Window
312
-
313
155
  {
314
-
315
156
  public MainWindow() => InitializeComponent();
316
-
317
157
  }
318
-
319
158
  }
320
-
321
159
  ```
322
160
 
323
-
324
-
325
- NativeMethods.txt
161
+ ```txt:NativeMethods.txt
326
-
327
- ```EnableMenuItem
162
+ EnableMenuItem
328
-
329
163
  GetSystemMenu
330
-
331
164
  GetWindowLong
332
-
333
165
  SetWindowLong
334
-
335
166
  SC_CLOSE
336
-
337
167
  WS_MAXIMIZEBOX
338
-
339
168
  WS_MINIMIZEBOX
340
-
341
169
  ```
342
170
 
343
-
344
-
345
- ---
346
-
347
-
348
-
349
171
  最小化・最大化両方禁止した場合は、ボタン自体が消える(Windowsがそういう仕様)
350
-
351
-
352
-
353
172
  すでに最大化(最小化)されている状態で、最大化(最小化)を禁止した場合元に戻るべきかどうか。
354
173
 
355
-
356
-
357
174
  2つ目のリンクでは`menuHandle`を使いまわし最後に`DestroyMenu`しろと言っているが、都度取得しないと動作しなかった。`

1

コード追記

2021/11/24 23:46

投稿

TN8001
TN8001

スコア9357

test CHANGED
@@ -12,7 +12,7 @@
12
12
 
13
13
 
14
14
 
15
- コードも書いてみようと思ったんですが、ちゃんとやろうとすると時間がかかりそうなので取り急ぎ情報だけ^^;
15
+ ~~コードも書いてみようと思ったんですが、ちゃんとやろうとすると時間がかかりそうなので取り急ぎ情報だけ^^;~~
16
16
 
17
17
 
18
18
 
@@ -21,3 +21,337 @@
21
21
 
22
22
 
23
23
  参考コードは最初からfalseだった時の手当てがないですね。
24
+
25
+
26
+
27
+ ---
28
+
29
+
30
+
31
+ 個別設定できたほうが一般向けだろうと思うので3つに分けました(一括切り替えも用意しようかとも思いましたが、バインドするとなると煩雑なので省略)
32
+
33
+
34
+
35
+ [NuGet Gallery | Microsoft.Windows.CsWin32 0.1.619-beta](https://www.nuget.org/packages/Microsoft.Windows.CsWin32/0.1.619-beta)
36
+
37
+ [NuGet Gallery | Microsoft.Xaml.Behaviors.Wpf 1.1.39](https://www.nuget.org/packages/Microsoft.Xaml.Behaviors.Wpf/1.1.39)
38
+
39
+
40
+
41
+ ```xaml
42
+
43
+ <Window
44
+
45
+ x:Class="Questions370772.MainWindow"
46
+
47
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
48
+
49
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
50
+
51
+ xmlns:Behaviors="http://schemas.microsoft.com/xaml/behaviors"
52
+
53
+ xmlns:local="clr-namespace:Questions370772"
54
+
55
+ Width="800"
56
+
57
+ Height="450">
58
+
59
+ <Behaviors:Interaction.Behaviors>
60
+
61
+ <local:WindowButtonBehavior
62
+
63
+ CloseButtonEnabled="{Binding IsChecked, ElementName=close}"
64
+
65
+ MaximizeButtonEnabled="{Binding IsChecked, ElementName=maximize}"
66
+
67
+ MinimizeButtonEnabled="{Binding IsChecked, ElementName=minimize}" />
68
+
69
+ </Behaviors:Interaction.Behaviors>
70
+
71
+
72
+
73
+ <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
74
+
75
+ <CheckBox
76
+
77
+ x:Name="minimize"
78
+
79
+ VerticalContentAlignment="Center"
80
+
81
+ Content="最小化ボタンを有効にする" />
82
+
83
+ <CheckBox
84
+
85
+ x:Name="maximize"
86
+
87
+ VerticalContentAlignment="Center"
88
+
89
+ Content="最大化ボタンを有効にする" />
90
+
91
+ <CheckBox
92
+
93
+ x:Name="close"
94
+
95
+ VerticalContentAlignment="Center"
96
+
97
+ Content="閉じるボタンを有効にする" />
98
+
99
+ </StackPanel>
100
+
101
+ </Window>
102
+
103
+ ```
104
+
105
+
106
+
107
+ ```C#
108
+
109
+ using System;
110
+
111
+ using System.Windows;
112
+
113
+ using System.Windows.Interop;
114
+
115
+ using Microsoft.Xaml.Behaviors;
116
+
117
+ using Windows.Win32.Foundation;
118
+
119
+
120
+
121
+ using static Windows.Win32.PInvoke;
122
+
123
+ using static Windows.Win32.UI.WindowsAndMessaging.MENU_ITEM_FLAGS;
124
+
125
+ using static Windows.Win32.UI.WindowsAndMessaging.WINDOW_LONG_PTR_INDEX;
126
+
127
+ using static Windows.Win32.UI.WindowsAndMessaging.WINDOW_STYLE;
128
+
129
+
130
+
131
+ namespace Questions370772
132
+
133
+ {
134
+
135
+ public class WindowButtonBehavior : Behavior<Window>
136
+
137
+ {
138
+
139
+ public bool MinimizeButtonEnabled { get => (bool)GetValue(MinimizeButtonEnabledProperty); set => SetValue(MinimizeButtonEnabledProperty, value); }
140
+
141
+ public static readonly DependencyProperty MinimizeButtonEnabledProperty
142
+
143
+ = DependencyProperty.Register(nameof(MinimizeButtonEnabled), typeof(bool), typeof(WindowButtonBehavior),
144
+
145
+ new PropertyMetadata(true, new PropertyChangedCallback(OnMinimizeButtonEnabledChanged)));
146
+
147
+ private static void OnMinimizeButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
148
+
149
+ => (d as WindowButtonBehavior)?.OnMinimizeButtonEnabledChanged();
150
+
151
+
152
+
153
+ public bool MaximizeButtonEnabled { get => (bool)GetValue(MaximizeButtonEnabledProperty); set => SetValue(MaximizeButtonEnabledProperty, value); }
154
+
155
+ public static readonly DependencyProperty MaximizeButtonEnabledProperty
156
+
157
+ = DependencyProperty.Register(nameof(MaximizeButtonEnabled), typeof(bool), typeof(WindowButtonBehavior),
158
+
159
+ new PropertyMetadata(true, new PropertyChangedCallback(OnMaximizeButtonEnabledChanged)));
160
+
161
+ private static void OnMaximizeButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
162
+
163
+ => (d as WindowButtonBehavior)?.OnMaximizeButtonEnabledChanged();
164
+
165
+
166
+
167
+ public bool CloseButtonEnabled { get => (bool)GetValue(CloseButtonEnabledProperty); set => SetValue(CloseButtonEnabledProperty, value); }
168
+
169
+ public static readonly DependencyProperty CloseButtonEnabledProperty
170
+
171
+ = DependencyProperty.Register(nameof(CloseButtonEnabled), typeof(bool), typeof(WindowButtonBehavior),
172
+
173
+ new PropertyMetadata(true, new PropertyChangedCallback(OnCloseButtonEnabledChanged)));
174
+
175
+ private static void OnCloseButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
176
+
177
+ => (d as WindowButtonBehavior)?.OnCloseButtonEnabledChanged();
178
+
179
+
180
+
181
+
182
+
183
+ private IntPtr hwnd;
184
+
185
+
186
+
187
+ protected override void OnAttached()
188
+
189
+ => AssociatedObject.SourceInitialized += AssociatedObject_SourceInitialized;
190
+
191
+
192
+
193
+ private void AssociatedObject_SourceInitialized(object? sender, EventArgs e)
194
+
195
+ {
196
+
197
+ AssociatedObject.SourceInitialized -= AssociatedObject_SourceInitialized;
198
+
199
+
200
+
201
+ hwnd = new WindowInteropHelper(AssociatedObject).Handle;
202
+
203
+
204
+
205
+ if (!MinimizeButtonEnabled) OnMinimizeButtonEnabledChanged();
206
+
207
+ if (!MaximizeButtonEnabled) OnMaximizeButtonEnabledChanged();
208
+
209
+ if (!CloseButtonEnabled) OnCloseButtonEnabledChanged();
210
+
211
+ }
212
+
213
+
214
+
215
+ private void OnMinimizeButtonEnabledChanged()
216
+
217
+ {
218
+
219
+ if (hwnd == IntPtr.Zero) return;
220
+
221
+
222
+
223
+ if (MinimizeButtonEnabled)
224
+
225
+ {
226
+
227
+ SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) | (int)WS_MINIMIZEBOX);
228
+
229
+ }
230
+
231
+ else
232
+
233
+ {
234
+
235
+ SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) & ~(int)WS_MINIMIZEBOX);
236
+
237
+ //if (AssociatedObject.WindowState == WindowState.Minimized)
238
+
239
+ //{
240
+
241
+ // AssociatedObject.WindowState = WindowState.Normal;
242
+
243
+ //}
244
+
245
+ }
246
+
247
+ }
248
+
249
+
250
+
251
+ private void OnMaximizeButtonEnabledChanged()
252
+
253
+ {
254
+
255
+ if (hwnd == IntPtr.Zero) return;
256
+
257
+
258
+
259
+ if (MaximizeButtonEnabled)
260
+
261
+ {
262
+
263
+ SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) | (int)WS_MAXIMIZEBOX);
264
+
265
+ }
266
+
267
+ else
268
+
269
+ {
270
+
271
+ SetWindowLong((HWND)hwnd, GWL_STYLE, GetWindowLong((HWND)hwnd, GWL_STYLE) & ~(int)WS_MAXIMIZEBOX);
272
+
273
+ //if (AssociatedObject.WindowState == WindowState.Maximized)
274
+
275
+ //{
276
+
277
+ // AssociatedObject.WindowState = WindowState.Normal;
278
+
279
+ //}
280
+
281
+ }
282
+
283
+ }
284
+
285
+
286
+
287
+ private void OnCloseButtonEnabledChanged()
288
+
289
+ {
290
+
291
+ if (hwnd == IntPtr.Zero) return;
292
+
293
+
294
+
295
+ var hMenu = GetSystemMenu((HWND)hwnd, false);
296
+
297
+ if (hMenu != IntPtr.Zero)
298
+
299
+ {
300
+
301
+ EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | (CloseButtonEnabled ? MF_ENABLED : MF_GRAYED));
302
+
303
+ }
304
+
305
+ }
306
+
307
+ }
308
+
309
+
310
+
311
+ public partial class MainWindow : Window
312
+
313
+ {
314
+
315
+ public MainWindow() => InitializeComponent();
316
+
317
+ }
318
+
319
+ }
320
+
321
+ ```
322
+
323
+
324
+
325
+ NativeMethods.txt
326
+
327
+ ```EnableMenuItem
328
+
329
+ GetSystemMenu
330
+
331
+ GetWindowLong
332
+
333
+ SetWindowLong
334
+
335
+ SC_CLOSE
336
+
337
+ WS_MAXIMIZEBOX
338
+
339
+ WS_MINIMIZEBOX
340
+
341
+ ```
342
+
343
+
344
+
345
+ ---
346
+
347
+
348
+
349
+ 最小化・最大化両方禁止した場合は、ボタン自体が消える(Windowsがそういう仕様)
350
+
351
+
352
+
353
+ すでに最大化(最小化)されている状態で、最大化(最小化)を禁止した場合元に戻るべきかどうか。
354
+
355
+
356
+
357
+ 2つ目のリンクでは`menuHandle`を使いまわし最後に`DestroyMenu`しろと言っているが、都度取得しないと動作しなかった。`