C#プログラミングTips

コントロールの位置や大きさを自動的に調整可能にする

デジタルアドバンテージ
2001/03/30


 グラフィカル・インターフェイスを持つWindowsアプリケーションを記述する場合に、避けて通れない処理の1つにコントロールのレイアウトがある。具体的には、ウィンドウがリサイズされたときに、ウィンドウの大きさに従ってコントロールの位置や大きさを調整することだ。

 例えば次の画面は、今回サンプルとして作成するイベント・ビューア・プログラムである。

今回作成するインベント・ビューア・プログラム
今回は、イベント・ログを表示するビューア・プログラムを作成する。ウィンドウの下部にある[System]、[Application]、[Security]のボタンをクリックすることで、それらに対応するイベント・ログを表示することができる。これだけなら、見慣れたいつものWindowsアプリケーションでしかないが…。
  インベントの内容を列挙するリストボックス。
  上のリストボックスに表示するイベント・ログの種類を切り替えるためのプッシュ・ボタン。

 このウィンドウだけなら、見慣れたいつものWindowsアプリケーションだろう。しかしここで、ウィンドウの枠をマウスでドラッグして、ウィンドウ・サイズを拡大したら次のようになった。ウィンドウ・サイズが変更されたにもかかわらず、リストボックスとプッシュ・ボタンのサイズと位置関係は従来のまま変わらない、何とも間抜けな状態になってしまう。

ウィンドウの枠をマウスでドラッグし、サイズを変更したところ
ウィンドウ・サイズが拡大されたにもかかわらず、リストボックスやプッシュ・ボタンのサイズや位置関係が変わらないため、右と下に空きスペースができてしまった。何とも間抜けな状態である。
  ウィンドウ・サイズが拡大されてできた空きスペース。

 こうした問題を避けるために、例えばVisual Basicなどでは、ウィンドウのリサイズ時にクライアント領域のサイズを取得し、それに基づいて、例えばこのプログラムの場合ならプッシュ・ボタン群を右下隅に移動し、リストボックスを画面いっぱいに拡大するという具合にコントロールのサイズや位置を調整する必要があった。

Anchorプロパティ

 これに対し.NET FrameworkのWindows Formsでは、各コントロールに“Anchor”というプロパティが導入され、このプロパティをあらかじめ設定しておくだけで、ウィンドウ・サイズの変更時でも、自動的にコントロールのレイアウト調整を行えるようになった(正確には、各コントロールに共通のベース・クラスであるSystem.WinForms.RichControlクラスがAnchorプロパティを持っている)。

 このAnchorプロパティは、コントロールの4辺とフォーム(あるいはそのコントロールが載っているコンテナとなるコントロール。フォームもコンテナ・コントロールとしての機能を持つ)の端との距離を固定する機能だ。例えば今回のサンプル・プログラムでは、次のようにしてリストボックスとボタンのAnchorプロパティを設定している(プログラム・コード全体はすぐ次に掲載する)。

20: listbox1.Anchor = AnchorStyles.All;
36: button1.Anchor  = AnchorStyles.BottomRight;
43: button2.Anchor  = AnchorStyles.BottomRight;
50: button3.Anchor  = AnchorStyles.BottomRight;

Anchorのスタイル

 Anchorプロパティには、列挙型(enum型)として定義されている(System.WinFormsネームスペースの)AnchorStylesのメンバを設定する。今回の例では、リストボックスのAnchorプロパティには4辺をすべて固定するAnchorStyles.Allを、3つのボタンにはそれぞれ右辺と下辺を固定するAnchorStyles.BottomRightを設定する。これらを設定するだけで、リストボックスは常に画面いっぱいに表示されるようにフォームの大きさに従ってサイズが変更され、ボタンはそのサイズを変えずにウィンドウの下端と右端からの距離を一定に保ちながら位置が変更されるようになる。

 AnchorStylesには、次のように16通りのすべての組み合わせが定義されている。Anchorプロパティのデフォルト値はAnchorStyles.TopLeftである。

プロパティの設定値 固定されるコントロールの辺
All
Bottom
BottomLeft
BottomLeftRight
BottomRight
Left
LeftRight
None
Right
Top
TopBottom
TopBottomLeft
TopBottomRight
TopLeft
TopLeftRight
TopRight
AnchorStylesの種類と固定位置の関係
AllやBottomLeftRightなど、向かい合った辺が固定される場合には、そのコントロールのコンテナのサイズ変更にともなってコントロール自体のサイズも変更される。

3のボタンに1つイベント・ハンドラ

 サンプル・プログラムについて、もう少し解説しておこう。このプログラムでは3つのプッシュ・ボタンを使っているが、内部的にはすべて同じイベント・ハンドラを設定している。次のコードは、イベント・ハンドラの一部とClickイベントにイベント・ハンドラを設定している部分だけを抜き出したものだ。

12: protected void button1_Click(object sender, System.EventArgs e) {
13:     EventLog log = new EventLog();
14:
15:     log.Log = ((Button)sender).Text;
        ・・・
21: }
        ・・・
37: button1.Click    += new EventHandler(button1_Click);
44: button2.Click    += new EventHandler(button1_Click);
51: button3.Click    += new EventHandler(button1_Click);

 イベント・ハンドラでは、第1引数であるsenderにイベントを発生させたオブジェクトが入るため(12行目)、このように複数のコントロールに1つのイベント・ハンドラを指定してもイベントの発生元を区別できる。ここでは少しトリッキーだが、読み込むイベント・ログの種類を文字列として指定するLogプロパティに、クリックされたボタンのキャプション文字列を設定している(15行目)。もちろんこれが正しく機能するためには、3つのボタンのキャプションをイベント・ログの名称である“System”、“Application”、“Security”にしておく必要がある。

ソースコードとコンパイル方法

 最後に、今回のサンプル・プログラムの全コードとコンパイル方法を示しておく。

 1: // anchor.cs
 2:
 3: using System;
 4: using System.Drawing;
 5: using System.WinForms;
 6: using System.Diagnostics;
 7:
 8: public class AnchorSample : Form {
 9:     private ListBox listbox1;
10:     private Button  button1, button2, button3;
11:
12:     protected void button1_Click(object sender, System.EventArgs e) {
13:         EventLog log = new EventLog();
14:
15:         log.Log = ((Button)sender).Text;
16:
17:         listbox1.Items.Clear();
18:         foreach (EventLogEntry entry in log.Entries) {
19:             listbox1.Items.Insert(0, entry.TimeWritten + " : " + entry.Message);
20:         }
21:     }
22:
23:     public AnchorSample() {
24:         this.ClientSize = new Size(640, 480);
25:         this.Text       = "アンカー・サンプル";
26:
27:         this.listbox1     = new ListBox();
28:         listbox1.Location = new Point(10, 10);
29:         listbox1.Size     = new Size(620, 420);
20:         listbox1.Anchor   = AnchorStyles.All;
31:
32:         this.button1      = new Button();
33:         button1.Location  = new Point(310, 440);
34:         button1.Size      = new Size(100, 30);
35:         button1.Text      = "System";
36:         button1.Anchor    = AnchorStyles.BottomRight;
37:         button1.Click    += new EventHandler(button1_Click);
38:
39:         this.button2      = new Button();
30:         button2.Location  = new Point(420, 440);
41:         button2.Size      = new Size(100, 30);
42:         button2.Text      = "Application";
43:         button2.Anchor    = AnchorStyles.BottomRight;
44:         button2.Click    += new EventHandler(button1_Click);
45:
46:         this.button3      = new Button();
47:         button3.Location  = new Point(530, 440);
48:         button3.Size      = new Size(100, 30);
49:         button3.Text      = "Security";
40:         button3.Anchor    = AnchorStyles.BottomRight;
51:         button3.Click    += new EventHandler(button1_Click);
52:
53:         this.Controls.Add(listbox1);
54:         this.Controls.Add(button1);
55:         this.Controls.Add(button2);
56:         this.Controls.Add(button3);
57:     }
58:
59:     public static void Main() {
60:         Application.Run(new AnchorSample());
61:     }
62: }
anchor.csのソースコード
15行目: Logプロパティには対象となるイベント・ログの名称を設定する。
17行目: リストボックスの項目をすべてクリアする。
18行目: 対象となるイベント・ログの各エントリを順に取り出す。
19行目: 各エントリの出力された日時とメッセージをリストボックスの先頭に追加する。

 このプログラムをコンパイルするには、コマンド・プロンプトから次のコマンドを実行する。

csc /r:Microsoft.Win32.Interop.DLL /r:System.DLL
  /r:System.WinForms.DLL /r:System.Drawing.DLL
  /r:System.Diagnostics.DLL anchor.cs

プログラム中で使用したEventLogクラスとEventLogEntryクラスはSystem.Diagnostics.DLLに含まれている。End of Article

「C#プログラミングTips」

 


@IT Special

- PR -

TechTargetジャパン

Insider.NET フォーラム 新着記事
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
  • 第7回 Windowsアプリのデバッグ&リリース (2017/7/14)
     バグはどうやってつぶせばいいのか? 完成したアプリケーションはどうやってリリースすればいいのか? VS 2017入門の最終回
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

イベントカレンダー

PickUpイベント

- PR -

アクセスランキング

もっと見る

ホワイトペーパーTechTargetジャパン

注目のテーマ

Insider.NET 記事ランキング

本日 月間
ソリューションFLASH