第10章のプログラムを見てください。ちょっと不満がありませんか。
表示する文字列が長い場合、フォームのサイズを大きくしないと全部を読むことができません。やはり、スクロールバーが欲しいですね。
この章の表題は、ちょっと正しくありません。 Formクラスの継承関係が第2章に書いてあります。2代前のクラスがScrollableControlクラスです。名前からしてスクロールできそうですね。スクロールバーを新たにつけるのではなく、Formクラスには最初からスクロールバーの機能が備わっているのです。
スクロールさせるのは実に簡単です。
スクロールさせたいFormクラスのAutoScrollプロパティをtrueにします。
public override bool AutoScroll { get; set; }
次に、表示矩形がこれより小さくなると、スクロールバーを出すよ、という最小の矩形をAutoScrollMinSizeに指定します。
public Size AutoScrollMinSize { get; set; }
Size構造体は第7章で出てきました。さて、次に筆者は大失敗をして、時間を浪費してしまいました。(どのような失敗かは恥ずかしいので省略します)
OnPaintメソッドで再描画をするとき、スクロール位置に合わせた座標でDrawStringメソッドを呼び出さなくてはなりません。あれこれ、計算する必要はありません。
AutoScrollPositionプロパティで取得したPoint構造体を利用すればよいのです。
public Point AutoScrollPosition { get; set; }
Point構造体については第3章でやりました。表示する文字列をすべて含む最小の四角形を求めて、これをAutoScrollMinSizeに指定すればよいですね。 こういった、矩形を求めるには、GraphicsクラスのMeasureStringメソッドを使います。 調べる文字列が複数行になっていても大丈夫です。
public SizeF MeasureString ( string text, Font font )fontには、文字列を表示するフォントを指定します。
さて、今まではGraphicsオブジェクトは全部メソッドの引数でもらってきていました。 おそらく、今回は文字列の計測はコンストラクタ内で行うことになるでしょう。
すると、引数からもらってくることはできません。自分で作ることになります。 これには、ControlクラスのCreateGraphicsメソッドを使います。
public Graphics CreateGraphics ()このようにして作成したGraphicsは、不要になったらDisposeメソッドで破棄しなくてはいけません。(C#なんだから、これも自動で破棄してくれればよさようなもんですが・・)
public void Dispose ()これで、Graphicsで使用したすべてのリソースを解放します。
では、サンプルを見てみましょう。
// scroll01.cs
using System;
using System.Drawing;
using System.Windows.Forms;
class scroll01 : Form
{
    string str = "今日はよい天気です。\n" +
        "明日もよい天気でしょう。\n" +
        "しかし明後日はどうなるかどうなるかわかりません。\n" +
        "明日は明日の風が吹きます。";
    Font font;
    public static void Main()
    {
        scroll01 s1 = new scroll01();
        Application.Run(s1);
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        Graphics g = e.Graphics;
        
        StringFormat strformat = new StringFormat();
        strformat.Alignment = StringAlignment.Near;
        Point pt = AutoScrollPosition;
        g.DrawString(str, font, Brushes.Black, pt.X, pt.Y, strformat);
    }
    public scroll01()
    {
        Size size = new Size();
        Text = "猫でもわかるプログラミング";
        BackColor = SystemColors.Window;
        font = new Font("MS ゴシック", 14);
        AutoScroll = true;
        Graphics g = CreateGraphics();
        SizeF s = g.MeasureString(str, font);
        size.Width = (int)s.Width;
        size.Height = (int)s.Height;
        AutoScrollMinSize = size;
        g.Dispose();
    }
}
実行結果は次のようになります。
すでに、すべての文字列を表示するにはクライアント領域の幅が足りないので、
水平スクロールバーが出現しています。
フォームを小さくして、高さも不足させると・・・
垂直スクロールバーも出現しました。
スクロールバーを操作すると正しくスクロールして、文字列すべてを読むことができます。
Update 25/Oct/2006 By Y.Kumei