何とも長い表題です。
まずは、今回作るプログラムの実行結果を見てみましょう。
ボタンの外観がフラットになりました。そして、カラフルです。
ボタンに表示されているテキストも大きめですね。かつ色が白い。
また、マウスをのせると、カーソルが指型になります。
ボタンを押すと、どのボタンを押したのか、メッセージボックスで表示します。
同時に、クライアント領域にも表示されます。
さらに、フォームのサイズが縮小されて全部が表示されなくなったら、スクロールバーが出てきます。
まずは、ボタンをフラットにする方法ですが、これはButtonクラスのFlatStyleをFlatSytle.Flatに設定するだけです。FlatSytleプロパティはButtonBaseクラスからの軽症です。
public FlatStyle FlatStyle { get; set; }
戻り値のFlatStyleは、FlatStyle列挙体でメンバは次の通りです。
| メンバ | 意味 | 
|---|---|
| Flat | コントロールがフラットに表示される | 
| Popup | マウスでポイントされると立体的に表示される | 
| Standard | 立体表示 | 
| System | 外観はOSにより決定される | 
次に、ボタンに自分で描画するには、ButtonクラスのOnPaintメソッドをオーバーライドします。Buttonクラスから継承したクラスを作らなかった場合はPaintイベントと自作ハンドラを関連づける必要があります。
protected override void OnPaint(PaintEventArgs pevent)
{
    base.OnPaint(pevent);
    string title = "ボタン";
    Graphics g = pevent.Graphics;
    Brush br;
        
    switch (no)
    {
        case 0:
            br = Brushes.Red;
            title += "1";
            break;
        case 1:
            br = Brushes.Blue;
            title += "2";
            break;
        case 2:
            br = Brushes.Brown;
            title += "3";
            break;
        case 3:
            br = Brushes.Gold;
            title += "4";
            break;
        default:
            br = Brushes.Black;
            break;
    }
        
    g.FillRectangle(br, 
        new Rectangle(5, 5, this.Width - 10, this.Height - 10));
    Font font = new Font("MS ゴシック", 14);
    SizeF sz = g.MeasureString(title, font);
    Single x = (this.Width - sz.Width) / 2.0F;
    Single y = (this.Height - sz.Height) / 2.0F;
    g.DrawString(title, font, Brushes.White, x, y);
}
背景をいろいろな色で塗るならBackColorプロパティを設定すればいいんじゃないか、と思われる方もいると思いますが、そうすると外観が図で示したようにはなりません。(ボタンの周りもその色になる、ボタン境界の内側も塗りつぶされるなど)そこで、自力でFillRectangleメソッドで矩形に塗りつぶしています。Graphics.FillRectangleメソッドには、4つのオーバーロードバージョンがあります。
public void FillRectangle ( Brush brush, Rectangle rect ) public void FillRectangle ( Brush brush, RectangleF rect ) public void FillRectangle ( Brush brush, int x, int y, int width, int height ) public void FillRectangle ( Brush brush, float x, float y, float width, float height )最初の引数は、塗りつぶすブラシを指定します。後の引数は矩形を左上隅の座標で示して、幅・高さを指定するか、Rectangleまたは、RectangleF構造体で指定します。
RectangleF構造体は第6章ですでに解説しています。Rectangle構造体は、これのint版です。
Rectangle構造体のコンストラクタはオーバーロードされていて、次のようなものがあります。
public Rectangle ( Point location, Size size ) public Rectangle ( int x, int y, int width, int height )Rectangle構造体の、主なプロパティにはX,Y(左上隅のx,y座標)、Size(この四角形のサイズ)、 Width(幅)、Height(高さ)などがあります。
Point構造体は、第3章ですでに出てきました。
さて、四角形を描画したらその上からDrawStringメソッドでテキストを描画します。
MeasureStringメソッドで、表示するテキストの計測を行います。描画開始の左上隅の座標は
Single x = (this.Width - sz.Width) / 2.0F; Single y = (this.Height - sz.Height) / 2.0F;で求まります。szは文字列の計測結果を持っているSizeF構造です。
次に、マウスでポイントされたときの挙動はButtonクラスのOnMouseHoverメソッドをバーライドして記述します。このメソッドはControlクラスからの継承です。
protected override void OnMouseHover(EventArgs e)
{
    base.OnMouseHover(e);
    this.Cursor = Cursors.Hand;
}
ButtonクラスのCursorプロパティを指型のカーソルに設定します。
public virtual Cursor Cursor { get; set; }
Cursorを設定するには、Cursorオブジェクトのコレクションを提供するCursorsクラスを利用すると便利です。Cursorsクラスのstaticなプロパティでよく使われると思われるものには、次のようなものがあります。
| プロパティ | 意味 | 
|---|---|
| Arrow | 矢印カーソル | 
| Cross | 十字カーソル | 
| Default | 規定のカーソル(通常矢印) | 
| Hand | 指型のカーソル | 
| Help | 矢印と疑問符のカーソル | 
| WaitCursor | 待機カーソル | 
これらは、全部読み取り専用です。他にも多数定義されています。
では、プログラムを見てみましょう。
// button04
using System;
using System.Drawing;
using System.Windows.Forms;
class button04
{
    public static string str;
    public static void Main()
    {
        Size sz = new Size(120, 50);
        MyForm mf = new MyForm(sz);
        MyButton mybtn1 = new MyButton(mf, 
            new Point(10, 10), sz, 0);
        MyButton mybtn2 = new MyButton(mf,
            new Point(20 + mybtn1.Width, 10), sz, 1);
        MyButton mybtn3 = new MyButton(mf,
            new Point(10, 20 + mybtn1.Height), sz, 2);
        MyButton mybtn4 = new MyButton(mf,
            new Point(20 + mybtn1.Width, 20 + mybtn1.Height), 
            sz, 3);
        Application.Run(mf);
    }
}
class MyForm : Form
{
    Size bSize;
    public MyForm(Size sz)
    {
        Text = "猫でもわかるプログラミング";
        BackColor = SystemColors.Window;
        bSize = sz;
        AutoScroll = true;
        AutoScrollMinSize = new Size(sz.Width * 2 + 20, sz.Height * 2 + 60);
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        Graphics g = e.Graphics;
        int x = 10;
        int y = bSize.Height * 2 + 30;
        Font font = new Font("MS ゴシック", 14);
        g.DrawString(button04.str, font, Brushes.Black, 
            x + AutoScrollPosition.X,
            y + AutoScrollPosition.Y);
    }
}
class MyButton : Button
{
    int no;
    
    public MyButton(Form parent, Point pt, Size sz, int n)
    {
        no = n;
        Parent = parent;
        Location = pt;
        Size = sz;
        BackColor = SystemColors.Control;
        FlatStyle = FlatStyle.Flat;
    }
    protected override void OnClick(EventArgs e)
    {
        base.OnClick(e);
        string str = "ボタン" + (no + 1) + "を押したね";
        button04.str = str;
        Parent.Invalidate();
        MessageBox.Show(str, "猫でもわかるプログラミング",
            MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
    }
    protected override void OnMouseHover(EventArgs e)
    {
        base.OnMouseHover(e);
        this.Cursor = Cursors.Hand;
    }
    protected override void OnPaint(PaintEventArgs pevent)
    {
        base.OnPaint(pevent);
        string title = "ボタン";
        Graphics g = pevent.Graphics;
        Brush br;
        
        switch (no)
        {
            case 0:
                br = Brushes.Red;
                title += "1";
                break;
            case 1:
                br = Brushes.Blue;
                title += "2";
                break;
            case 2:
                br = Brushes.Brown;
                title += "3";
                break;
            case 3:
                br = Brushes.Gold;
                title += "4";
                break;
            default:
                br = Brushes.Black;
                break;
        }
        
        g.FillRectangle(br, 
            new Rectangle(5, 5, this.Width - 10, this.Height - 10));
        Font font = new Font("MS ゴシック", 14);
        SizeF sz = g.MeasureString(title, font);
        Single x = (this.Width - sz.Width) / 2.0F;
        Single y = (this.Height - sz.Height) / 2.0F;
        g.DrawString(title, font, Brushes.White, x, y);
    }
}
ちょっと長いですが、順番に見ていくとわかると思います。(特に、クラス間の連絡に注意して読んでみてください。)
Update 29/Oct/2006 By Y.Kumei