回答編集履歴

1

GetMaximum を調整

2023/07/24 17:29

投稿

KOZ6.0
KOZ6.0

スコア2721

test CHANGED
@@ -1,56 +1,64 @@
1
1
  VScrollBar と FlowLayoutPanel のスクロールが同期できているなら、FlowLayoutPanel の MouseWheel イベントでは、VScrollBar の Value プロパティを操作します。
2
2
  MouseEventArgs.Delta の値の大小は無視し、プラスかマイナスかで判定してください。
3
3
 
4
- ```ここに言語を入力
4
+ ```cs
5
- using System.Runtime.InteropServices;
5
+ using System.Runtime.InteropServices;
6
6
 
7
- public partial class Form1 : Form
7
+ public partial class Form1 : Form
8
- {
8
+ {
9
- public Form1() {
9
+ public Form1() {
10
- InitializeComponent();
10
+ InitializeComponent();
11
- Shown += Form1_Shown;
11
+ Shown += Form1_Shown;
12
- vScrollBar1.ValueChanged += VScrollBar1_ValueChanged;
12
+ vScrollBar1.ValueChanged += VScrollBar1_ValueChanged;
13
- flowLayoutPanel1.MouseWheel += FlowLayoutPanel1_MouseWheel;
13
+ flowLayoutPanel1.MouseWheel += FlowLayoutPanel1_MouseWheel;
14
+ }
15
+
16
+ private void Form1_Shown(object? sender, EventArgs e) {
17
+ vScrollBar1.Minimum = 0;
18
+ vScrollBar1.Maximum = GetMaximum(flowLayoutPanel1, 10);
19
+ vScrollBar1.Value = 0;
20
+ flowLayoutPanel1.VerticalScroll.Minimum = vScrollBar1.Minimum;
21
+ flowLayoutPanel1.VerticalScroll.Maximum = vScrollBar1.Maximum;
22
+ flowLayoutPanel1.VerticalScroll.Value = vScrollBar1.Value;
23
+ }
24
+
25
+ private static int GetMaximum(Control control, int margin) {
26
+ int maxBottom = 0;
27
+ foreach (Control child in control.Controls) {
28
+ if (child.Bottom > maxBottom) {
29
+ maxBottom = child.Bottom;
30
+ }
31
+ }
32
+ int pageHeight = control.ClientSize.Height;
33
+ if (maxBottom <= pageHeight) {
34
+ return 0;
35
+ }
36
+ return maxBottom - pageHeight + margin;
37
+ }
38
+
39
+ [DllImport("user32.dll")]
40
+ static extern bool LockWindowUpdate(IntPtr hWndLock);
41
+
42
+ private void VScrollBar1_ValueChanged(object? sender, EventArgs e) {
43
+ LockWindowUpdate(flowLayoutPanel1.Handle);
44
+ flowLayoutPanel1.Visible = false;
45
+ flowLayoutPanel1.VerticalScroll.Value = vScrollBar1.Value;
46
+ flowLayoutPanel1.Visible = true;
47
+ LockWindowUpdate(IntPtr.Zero);
48
+ }
49
+
50
+ private void FlowLayoutPanel1_MouseWheel(object? sender, MouseEventArgs e) {
51
+ SetScroll(e.Delta > 0 ? -1 : 1);
52
+ }
53
+
54
+ private void SetScroll(int changeValue) {
55
+ var tmpValue = vScrollBar1.Value + changeValue;
56
+ vScrollBar1.Value = Math.Min(
57
+ Math.Max(tmpValue, vScrollBar1.Minimum),
58
+ vScrollBar1.Maximum);
59
+ }
60
+
14
61
  }
15
-
16
- private void Form1_Shown(object? sender, EventArgs e) {
17
- vScrollBar1.Minimum = 0;
18
- vScrollBar1.Maximum = GetMaximum(flowLayoutPanel1, vScrollBar1.LargeChange);
19
- vScrollBar1.Value = 0;
20
- flowLayoutPanel1.VerticalScroll.Minimum = vScrollBar1.Minimum;
21
- flowLayoutPanel1.VerticalScroll.Maximum = vScrollBar1.Maximum;
22
- flowLayoutPanel1.VerticalScroll.Value = vScrollBar1.Value;
23
- }
24
-
25
- private int GetMaximum(Control control, int largeChange) {
26
- int maxBottom = 0;
27
- foreach (Control child in control.Controls) {
28
- if (child.Bottom > maxBottom) {
29
- maxBottom = child.Bottom;
30
- }
31
- }
32
- int pageHeight = control.ClientSize.Height;
33
- return (maxBottom + pageHeight - 1) * largeChange / pageHeight;
34
- }
35
-
36
- [DllImport("user32.dll")]
37
- static extern bool LockWindowUpdate(IntPtr hWndLock);
38
-
39
- private void VScrollBar1_ValueChanged(object? sender, EventArgs e) {
40
- LockWindowUpdate(flowLayoutPanel1.Handle);
41
- flowLayoutPanel1.Visible = false;
42
- flowLayoutPanel1.VerticalScroll.Value = vScrollBar1.Value;
43
- flowLayoutPanel1.Visible = true;
44
- LockWindowUpdate(IntPtr.Zero);
45
- }
46
-
47
- private void FlowLayoutPanel1_MouseWheel(object? sender, MouseEventArgs e) {
48
- var tmpValue = vScrollBar1.Value + (e.Delta > 0 ? -1 : 1);
49
- vScrollBar1.Value = Math.Min(
50
- Math.Max(tmpValue, vScrollBar1.Minimum),
51
- vScrollBar1.Maximum);
52
- }
53
- }
54
62
  ```
55
63
 
56
64
  VScrollBar を操作すると、FlowLayoutPanel のスクロールバーが一瞬表示されることがあるので、LockWindowUpdate で描画を抑止しています。