初めてのカスタムコントロール
前回作成した、文字列を表示するカスタムコントロールを拡張してみましょう。
まずは、Textを変更した時にフォームデザイナー上ですぐに反映されるようにします。そのためには、Textを変更した時に呼び出されるOnTextChangedメソッドをオーバーライドし、そこでInvalidateを呼び出すようにします。
protected override void OnTextChanged(EventArgs e) { base.OnTextChanged(e); Invalidate(); }
Protected Overrides Sub OnTextChanged(e As EventArgs) MyBase.OnTextChanged(e) Invalidate() End Sub
Invalidateは、コントロールの外観に変更があった場合、システムに再描画を促すためのメソッドです。これによって、システムはコントロールに対して再描画せよと通知してきます。その通知は.NETフレームワークによって補足され、最終的にOnPaintが呼び出されます。ここで直接OnPaintを呼び出したいところですが、そうしてはいけないというWindowsプログラミングのルールがあるのでだめです。よく使うメソッドなので、覚えておきましょう。
Fontを変更した時に呼び出されるOnFontChangedにこの処理を書かなくていい理由は、継承元であるControlクラスのOnFontChangedで、Invalidateを呼び出すコードがすでに書かれているためです。
次に、ForeColorプロパティに対応し、色を変更できるようにしてみましょう。そのためには、OnPaintメソッドでBrushを作成しなければなりません。Brushは、文字列を書いたり、線を描いたり、面を塗りつぶしたりする時に使う情報が入っているオブジェクトです。文字列を書く時に使用するのはSolidBrushです。
protected override void OnPaint(PaintEventArgs pe) { base.OnPaint(pe); Brush brush = new SolidBrush(ForeColor); pe.Graphics.DrawString(Text, Font, brush, 0, 0); brush.Dispose(); }
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs) MyBase.OnPaint(e) Dim brush As Brush = New SolidBrush(ForeColor) e.Graphics.DrawString(Text, Font, brush, 0, 0) brush.Dispose() End Sub
ただし、VB.NETではソースの行頭に次の一行を追加しなければなりません。
Imports System.Drawing
作成したbrushは使い終わったら必ずDisposeしましょう。または、次のようにusingを使って書けば、Disposeが自動的に呼ばれます。
using (Brush brush = new SolidBrush(ForeColor)) { pe.Graphics.DrawString(Text, Font, brush, 0, 0); }
Using brush As Brush = New SolidBrush(ForeColor) pe.Graphics.DrawString(Text, Font, brush, 0, 0) End Using
ControlクラスのOnForeColorChangedメソッドでInvalidateが呼ばれているので、Fontと同じように、特にコードを追加しなくてもすぐに反映されます。
では、F6キーを押してコンパイルして、フォームに貼り付けたカスタムコントロールのForeColorを変更してみてください。色が変わりましたね。
カスタムコントロールの作り方の基本は理解していただけたでしょうか。いいアイディアが浮かんだ方は、OnPaintにいろいろ処理を加えて試してみてください。
ここでは、文字に影を付けてみます。元の文字列から1ドットずつずらして、暗い色で描画するだけです。
protected override void OnPaint(PaintEventArgs pe) { base.OnPaint(pe); Brush brush = new SolidBrush(SystemColors.GrayText); for (int i = 1; i <= 4; i++) { pe.Graphics.DrawString(Text, Font, brush, i, i); } brush.Dispose(); brush = new SolidBrush(ForeColor); pe.Graphics.DrawString(Text, Font, brush, 0, 0); brush.Dispose(); }
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs) MyBase.OnPaint(e) Dim brush As Brush = New SolidBrush(SystemColors.GrayText) For i As Integer = 1 To 4 e.Graphics.DrawString(Text, Font, brush, i, i) Next brush.Dispose() brush = New SolidBrush(ForeColor) e.Graphics.DrawString(Text, Font, brush, 0, 0) brush.Dispose() End Sub
F6キーでコンパイルします。影の深さが4なので、デフォルトの文字サイズではなんだかわかりませんね。文字のサイズを大きくして、前景色を明るいものに変えてみてください。影付きの文字列が表示されましたでしょうか。
ところで、今まで当たり前のように使ってきたPaintEventArgs(C#の’pe’やVB.NETの’e’)とはなんでしょうか。フォームのPaintイベントを使ったことがある方にはおなじみでしょうが、初めてという方のために簡単に説明します。
PaintEventArgsには、描画に必要な情報が入っています。と言っても使用できる情報は2つだけで、ClipRectangleとGraphicsです。
ClipRectangleは再描画が必要な部分の矩形情報で、通常コントロールのClientRectangleと同じですが、例えばコントロールの一部だけが隠された後に、その部分だけ再描画が必要になった時には、隠されていた部分だけの矩形情報が入っています。複雑な描画を行うコントロールでは、この情報を使用することによって描画を高速化できます。
Graphicsは描画を行うためのグラフィックスオブジェクトです。今まで使用してきたDrawStringメソッドや、線や曲線を描くメソッド、四角形や円を描いたり塗りつぶしたりするメソッド、画像を描画するメソッドなどが豊富に揃っています。OnPaintでカスタムコントロールの描画をする時には必ず使用することになりますので、一度ヘルプを見てみることをおすすめします。
2013年12月31日
« 作成環境の準備 新規プロパティの実装 »