<>
C# WindowsFormsでスクロールバーを表示させフォーム上にコントロールを動的に追加します。
デザイナで以下のようなものを作ります。Panel(panel1)を追加し、そのなかにさらにPanel(panel2)を追加します。追加ボタンをクリックするとPanelのなかにボタンが追加されます。フォームよりも下にボタンが生成されてもそれをクリックできるようにスクロールバーを表示させてクリックできるようにします。
Contents
Panelを二重にして対応
PanelのAutoSizeプロパティをtrueにするとスクロールバーが表示されますが、それだけだと適切な位置にボタンを表示させるのが難しくなるのでPanelを二重構造にしています。内側のPanelにボタンを追加し、このパネルを外側のPanelのなかに表示させます。そして内側のPanelを自動でサイズ変更可能にし、外側のPanelのAutoSizeプロパティをtrueにしてスクロール可能にすることで目的達成を目指します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); panel1.Resize += Panel1_Resize; // フォームのサイズ変更に伴って外側のPanelをサイズ変更できるようにする // 外側のPanelにスクロールバーをつける panel1.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right; panel1.VerticalScroll.Visible = true; // 内側のPanelを自動でサイズ変更可能に panel2.AutoSize = true; panel2.AutoSizeMode = AutoSizeMode.GrowOnly; panel2.Location = new Point(0, 0); // 表示場所を重ねる panel2.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top; } } |
フォームのサイズ変更に伴って外側のPanelがサイズ変更されたときの処理を示します。
内側のPanelのサイズ変更をおこなっています。内側のPanelにはAnchorプロパティを設定していますが、これだけだといったんPanelのサイズが大きくなるとそのままになるので外側と同じサイズをセットしています。また常に縦のスクロールバーを表示させるために高さを少し大きめにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public partial class Form1 : Form { private void Panel1_Resize(object sender, EventArgs e) { Size size = panel1.ClientSize; size.Height += 10; panel2.Size = size; // 常に縦のスクロールバーを表示させるためにはその都度プロパティを設定する panel1.VerticalScroll.Visible = true; panel1.AutoScroll = true; } } |
追加時の処理
追加ボタンをクリックしたときの処理を示します。
追加されるボタンを生成してサイズと追加する位置をセットします。そのあとPanelのサイズ変更に対応できるようにAnchorプロパティを設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public partial class Form1 : Form { int _newPosition = 0; // 次に追加されるボタンのY座標 private void button1_Click(object sender, EventArgs e) { // 追加されるボタンを生成する Button button = new Button(); button.Text = DateTime.Now.ToLongTimeString(); // ボタンに表示される文字列(現在時刻を使う) button.Location = new Point(0, _newPosition); // ボタンを追加すべき位置にセット button.Width = panel2.Size.Width; // 幅は内側のPanelに合わせる button.Height = 40; // Panelのサイズ変更に対応する button.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; panel2.Controls.Add(button); _newPosition += 50; // 50ピクセルごとに配置する } } |
削除時の処理
削除ボタンがクリックされたときはボタンが存在する場合は一番上のボタンを削除します。上にあるボタンが削除されたらその部分が空白になるので上に詰める処理をしています。内側のPanelはAutoSizeプロパティがtrueに設定されているため、自動的にサイズが縮小されています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public partial class Form1 : Form { private void button2_Click(object sender, EventArgs e) { // Panelに追加されているコントロール(この場合はButton)を集める List<Button> buttons = new List<Button>(); foreach (var obj in panel2.Controls) { if (obj.GetType() == typeof(Button)) buttons.Add((Button)obj); } // 存在する場合は一番上のボタンを削除する if (buttons.Count > 0) { panel2.Controls.Remove(buttons[0]); buttons.RemoveAt(0); } // 空白部分を上に詰める _newPosition = 0; foreach (Button button in buttons) { button.Location = new Point(0, _newPosition); _newPosition += 50; } } } |