DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

文字列を印刷する

文字列の印刷も「印刷する」と同様にして、PrintDocumentクラスPrintPageイベントハンドラ内で、PrintPageEventArgsオブジェクトのGraphicsにDrawStringで描画するだけです。なおDrawStringにつきましては、「文字を描く」をご覧ください。

しかし複数行の文字列を印刷するとなると、多少面倒なことになります。ヘルプの「PrintDocument クラス」にも複数行のテキストを印刷する例が載っていますが、文字数の長い行の右端で折り返す処理を怠っているため、実用的ではありません。

そこで複数行のテキストを右側で折り返して印刷するサンプルを私なりに書いてみましたので、参考にしてください。下の例ではフォームにあるボタン(Button1)をクリックすると、テキストボックス(TextBox1)に入力されている文字列を印刷します。

VB.NET
コードを隠すコードを選択
'Imports System.Drawing

Private printingText As String
Private printingPosition As Integer
Private printFont As Font

'Button1のClickイベントハンドラ
Private Sub Button1_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles Button1.Click
    '印刷する文字列と位置を設定する
    printingText = TextBox1.Text
    printingPosition = 0
    '印刷に使うフォントを指定する
    printFont = New Font("MS Pゴシック", 10)
    'PrintDocumentオブジェクトの作成
    Dim pd As New System.Drawing.Printing.PrintDocument
    'PrintPageイベントハンドラの追加
    AddHandler pd.PrintPage, AddressOf pd_PrintPage
    '印刷を開始する
    pd.Print()
End Sub

Private Sub pd_PrintPage(ByVal sender As Object, _
        ByVal e As System.Drawing.Printing.PrintPageEventArgs)
    If printingPosition = 0 Then
        '改行記号を'\n'に統一する
        printingText = printingText.Replace(vbCrLf, vbLf)
        printingText = printingText.Replace(vbCr, vbLf)
    End If

    '印刷する初期位置を決定
    Dim x As Integer = e.MarginBounds.Left
    Dim y As Integer = e.MarginBounds.Top

    '1ページに収まらなくなるか、印刷する文字がなくなるかまでループ
    While e.MarginBounds.Bottom > y + printFont.Height AndAlso _
            printingPosition < printingText.Length
        Dim line As String = ""

        While True
            '印刷する文字がなくなるか、
            '改行の時はループから抜けて印刷する
            If printingPosition >= printingText.Length OrElse _
                    printingText.Chars(printingPosition) = vbLf Then
                printingPosition += 1
                Exit While
            End If
            '一文字追加し、印刷幅を超えるか調べる
            line += printingText.Chars(printingPosition)
            If e.Graphics.MeasureString(line, printFont).Width _
                    > e.MarginBounds.Width Then
                '印刷幅を超えたため、折り返す
                line = line.Substring(0, line.Length - 1)
                Exit While
            End If
            '印刷文字位置を次へ
            printingPosition += 1
        End While
        '一行書き出す
        e.Graphics.DrawString(line, printFont, Brushes.Black, x, y)
        '次の行の印刷位置を計算
        y += printFont.GetHeight(e.Graphics)
    End While

    '次のページがあるか調べる
    If printingPosition >= printingText.Length Then
        e.HasMorePages = False
        '初期化する
        printingPosition = 0
    Else
        e.HasMorePages = True
    End If
End Sub
C#
コードを隠すコードを選択
//using System.Drawing;

private string printingText;
private int printingPosition;
private Font printFont;

//Button1のClickイベントハンドラ
private void Button1_Click(object sender, System.EventArgs e)
{
    //印刷する文字列と位置を設定する
    printingText = TextBox1.Text;
    printingPosition = 0;
    //印刷に使うフォントを指定する
    printFont = new Font("MS Pゴシック", 10);
    //PrintDocumentオブジェクトの作成
    System.Drawing.Printing.PrintDocument pd =
        new System.Drawing.Printing.PrintDocument();
    //PrintPageイベントハンドラの追加
    pd.PrintPage +=
        new System.Drawing.Printing.PrintPageEventHandler(pd_PrintPage);
    //印刷を開始する
    pd.Print();
}

private void pd_PrintPage(object sender,
    System.Drawing.Printing.PrintPageEventArgs e)
{
    if (printingPosition == 0)
    {
        //改行記号を'\n'に統一する
        printingText = printingText.Replace("\r\n", "\n");
        printingText = printingText.Replace("\r", "\n");
    }

    //印刷する初期位置を決定
    int x = e.MarginBounds.Left;
    int y = e.MarginBounds.Top;

    //1ページに収まらなくなるか、印刷する文字がなくなるかまでループ
    while (e.MarginBounds.Bottom > y + printFont.Height &&
        printingPosition < printingText.Length)
    {
        string line = "";
        for (;;)
        {
            //印刷する文字がなくなるか、
            //改行の時はループから抜けて印刷する
            if (printingPosition >= printingText.Length || 
                printingText[printingPosition] == '\n')
            {
                printingPosition++;
                break;
            }
            //一文字追加し、印刷幅を超えるか調べる
            line += printingText[printingPosition];
            if (e.Graphics.MeasureString(line, printFont).Width
                > e.MarginBounds.Width)
            {
                //印刷幅を超えたため、折り返す
                line = line.Substring(0, line.Length - 1);
                break;
            }
            //印刷文字位置を次へ
            printingPosition++;
        }
        //一行書き出す
        e.Graphics.DrawString(line, printFont, Brushes.Black, x, y);
        //次の行の印刷位置を計算
        y += (int) printFont.GetHeight(e.Graphics);
    }

    //次のページがあるか調べる
    if (printingPosition >= printingText.Length)
    {
        e.HasMorePages = false;
        //初期化する
        printingPosition = 0;
    }
    else
        e.HasMorePages = true;
}
  • 履歴:
  • 2007/1/5 1ページに収まらなくなるかの判別を修正。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。