解説

実例で学ぶWindowsプログラミング

第2回 継承と属性プログラミングで実現するRAD開発 

デジタルアドバンテージ
2004/12/11
Page1 Page2 Page3 Page4

コントロール・ライブラリの作成

 今回作成するコントロールはすべて「コントロール・ライブラリ」にまとめる。コントロール・ライブラリとは、複数のコントロールを1つのDLLファイルにまとめることができるVS.NETのプロジェクトだ。このようにすることで、作成したコントロールがほかのプロジェクトでも利用可能になり、再利用性が高まる。

 ここでは、前回作成した既存の「Kokyaku.NET」ソリューション内にコントロール・ライブラリのプロジェクトを新規作成する。

 これを行う手順は、前回説明した「[新しいプロジェクトの追加]ダイアログによるプロジェクトの追加」とほぼ同じである。よって、ここではあらためて解説しない(前回の手順内容を参照されたい)。ここでは、「src」フォルダ(本稿の例では「C:\Insider.NET\Kokyaku.NET\src」)の中に、「Insiders.Windows.Forms」という名前の[Windows コントロール ライブラリ]プロジェクトを新規作成した。

 コントロール・ライブラリが作成されると、そのプロジェクト内に自動的に「UserControl1.cs」というファイルが作成されるが、このファイルは使わないのですぐに完全に削除しよう。このファイルを削除するには、ソリューション・エクスプローラで[Delete]キーを押すだけだ。

 さらに前回で説明した「[プロパティ ページ]ダイアログによるプログラム出力先の設定」と同じように、プログラムの出力先を変更しておこう。ここでは、Debugビルドの出力先は「..\..\bin\Debug\」、Releaseビルドの出力先は「..\..\bin\Release\」を指定した。

 以上でコントロール・ライブラリのプロジェクトは作成完了だ。次に、このプロジェクトにコントロールを追加していく。まずは、コントロールの拡張が比較的単純なパネルから作成していくことにしよう。

拡張Windowsコントロールの作成

■拡張パネル・コントロール「MenuPanelコントロール」の作成

 新規にコントロールを作成するには、コントロール用のクラスを新規作成する必要がある。しかし、VS.NETには、ユーザー・コントロールやカスタム・コントロールに対して適切なテンプレートが用意されているが、拡張Windowsコントロールには用意されていない。テンプレートの中に[継承されたユーザー コントロール]というのはあるが、これは既存のWindowsコントロールではなく、既存のユーザー・コントロールを継承したコントロールを新規作成するためのものだ。

 そこでここでは、カスタム・コントロール用のテンプレートを代用して、コントロールの新規作成を行う。作成手順は次の画面のとおりだ。

カスタム・コントロールの新規作成(拡張Windowsコントロールを作成するための代用)
[新しい項目の追加]ダイアログを使って、新たなWindowsコントロール(この例では「MenuPanel.cs」)を追加する。
  VS.NET IDEの[ソリューション エクスプローラ]にある「Insiders.Windows.Forms」プロジェクトを右クリックしてコンテキスト・メニューを表示し、そのメニューから[追加]−[新しい項目の追加])を選択すると、[新しい項目の追加]ダイアログが表示される。なお、メニュー項目にある[継承コントロールの追加]は、(既存のWindowsコントロールではなく)既存のユーザー・コントロールを継承したコントロールを作成するためのものなので注意してほしい。
  [テンプレート]から[カスタム コントロール]を選択する。今回作成するコントロールは、既存のWindowsフォーム・コントロールを継承したものだが、それに該当するテンプレートが存在しないため、ここでは代用としてカスタム・コントロール用のテンプレートを使用している。
  [ファイル名]にファイルの名前(本稿では「MenuPanel.cs」)を入力する。これにより、MenuPanel.csファイルが作成され、そのファイル内に「MenuPanel」というクラスが作成される。
  [開く]ボタンをクリックすると、新しいカスタム・コントロールが作成される。

 カスタム・コントロール用の新規ファイル(この例では「MenuPanel.cs」)が作成されたら、そのファイルをコード・エディタで開いてみよう(これには、[ソリューション・エクスプローラ]にある「MenuPanel.cs」ファイルをダブルクリックすると、デザイナ・エディタが開いて表示されるので、そこで[F7]キーを押してコード・エディタに切り替えればよい)。

 そのファイル内に自動生成されたMenuPanelクラスのひな形コードを参照すると、カスタム・コントロールのベース・クラスであるControlクラス(System.Windows.Forms名前空間)を継承したクラスとなっている。この基本クラスの記述を、次のコード例のように、Panelコントロール(System.Windows.Forms名前空間)に書き換える。

public class MenuPanel : System.Windows.Forms.Control
                  
public class MenuPanel : System.Windows.Forms.Panel
MenuPanelクラスの書き換え(C#)

 これだけで、新規作成したMenuPanelクラスにPanelコントロールとしての基本機能が備わることになる。

■描画処理のカスタマイズ

 次に、冒頭で紹介した仕様に基づき、このMenuPanelコントロールの描画処理をカスタマイズしよう。パネルの具体的な描画手順は次のとおりだ。

パネルの独自描画の仕様
MenuPanelコントロールでは、パネルを以下のように描画する。
  左上から右下へのグラデーションを描画する。左上の色は基本クラスのBackColorプロパティの色を使用し、右下の色は白色を使う。描画範囲はコントロールの上下左右の端から2ピクセル小さくした(Inflateした)部分である。
  コントロールの上下左右の端から1ピクセル小さくした部分に1ピクセル幅の白い四角形の線を引く。
  コントロールの上下左右の端から1ピクセル小さくした部分にBackColorプロパティの色の1ピクセル幅の四角形の線を引く。
  パネルのタイトル・テキストを左端から10ピクセル、右端から10ピクセルの位置を起点として描画する。テキストの色は基本クラスのForeColorプロパティの色を使い、テキストのフォントは基本クラスのFontプロパティの値を使用する。

 コントロールの描画処理をカスタマイズするには、そのコントロールのクラスのOnPaintメソッドをオーバーライドする必要がある。実際には、カスタム・コントロールを新規作成した段階で、このOnPaintメソッドのひな形が作成されるので、メソッド自体を新たに追加する必要はない。

 そのOnPaintメソッド内では、基本クラスのOnPaintメソッド(base.OnPaintメソッド)を呼び出してデフォルトの描画処理を実現しているが、これをコメントアウトにより無効化して、独自の描画処理を実装すればよい。本稿では次のようなコードを実装した。

using System.Drawing.Drawing2D;
using System.Drawing.Text;

protected override void OnPaint(PaintEventArgs pe)
{
  // パネルを描画する
  DrawPanel(pe.Graphics);

  // 基本クラスのOnPaintメソッドは実行しない
  //base.OnPaint(pe);
}

private void DrawPanel(Graphics g)
{
  Rectangle rectPaint = this.ClientRectangle;
  if ((rectPaint.Width <= 0) || (rectPaint.Height <= 0))
  {
    return;  // 描画しない
  }

  //  内部の背景を描画
  rectPaint.Inflate(-2, -2);
  LinearGradientBrush brushBackground =
    new LinearGradientBrush(
    rectPaint, this.BackColor, Color.White,
    LinearGradientMode.ForwardDiagonal);
  g.FillRectangle(brushBackground, rectPaint);
  brushBackground.Dispose();

  // 描画時に線幅分右にはみ出るので、それを差し引いておく
  rectPaint.Width -= 1;
  rectPaint.Height -= 1;

  //  内枠の白線を描画

  rectPaint.Inflate(1, 1);
  g.DrawRectangle(new Pen(Color.White, 1), rectPaint);

  //  外枠の背景色の線を描画
  rectPaint.Inflate(1, 1);
  g.DrawRectangle(new Pen(this.BackColor, 1), rectPaint);

  //  文字列を描画
  SolidBrush brushText = new SolidBrush(ForeColor);
  g.TextRenderingHint = TextRenderingHint.AntiAlias;
  g.DrawString(this.panelTitleText, this.Font, brushText, 10, 10);
  brushText.Dispose();
}
独自の描画処理を行うOnPaintメソッドとDrawPanelメソッド(C#)
基本クラスのデフォルトの描画処理であるbase.OnPaintメソッドをコメントアウトして無効化し、その代わりに独自の描画処理を行うDrawPanelメソッドを呼び出している。DrawPanelメソッドのコメントにある番号は、上記の「パネルの独自描画の仕様」の説明に対応している。DrawPanelメソッド内では、まずGraphicsオブジェクト(System.Drawing名前空間)のFillRectangleメソッドで長方形領域を塗りつぶし、次にDrawRectangleメソッドで四角形の線を描画し、最後にDrawStringメソッドでテキストを描画している。

 Windowsアプリケーションにおける描画は、基本的に次の手順で行う。

  1. ブラシやペンなどを生成する
     →例えば、SolidBrushクラスやPenクラスのインスタンスを生成する。
  2. しかるべき描画処理を行う
     →例えば、GraphicsオブジェクトのFillRectangleメソッドを呼び出す。
  3. 生成したブラシやペンを破棄する
     →例えば、1で生成したブラシオブジェクトのDisposeメソッドを呼び出す。

 上記コードを見れば、この3段階の手順を踏んで実装されていることが分かるだろう。


 INDEX
  解説:実例で学ぶWindowsプログラミング
  第2回 継承と属性プログラミングで実現するRAD開発
    1.スタート・メニュー画面の構築について
  2.拡張Windowsコントロールの作成
    3.属性プログラミングの実践
    4.拡張Windowsコントロールの利用方法

インデックス・ページヘ  「解説:実例で学ぶWindowsプログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第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用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

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