改ページ

タグの編集
投稿者 うさぎ  (学生) 投稿日時 2012/2/7 14:55:53
いつもお世話になっています。VB2005を勉強中のものです。
只今印刷について勉強しています。
文字の大きさ行数をコンボボックスで指定し、リッチテキストボックスに文章を書き込めば内容を繁栄するメモ帳みたいなものをつくりたいのですが、リッチテキストボックスに入れた内容がコンボボックスで指定した行数をこえた場合改ページしたいのですがどうしたらいいのかわかりません。
よろしくお願いします。


いまできているコード
Public Class Form1
    
    Dim currentpage As Integer
    Private flg As Boolean = False
    Dim bityouseisita As Integer = 0
    Dim bityouseimigi As Integer
   

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        
        Combohaba.Items.Add("22")
        Combohaba.Items.Add("27")
        Combohaba.Items.Add("38")
        Combohaba.Items.Add("44")

        Combokazu.Items.Add("5")
        Combokazu.Items.Add("10")
        Combokazu.Items.Add("20")


    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        PrintDocument1.Print()
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        
        PrintPreviewDialog1.ShowDialog()

    End Sub

    Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
        Dim g As Graphics = e.Graphics
        Dim okisa As Single
        If Combohaba.SelectedIndex = 0 Then
            okisa = 14
        ElseIf Combohaba.SelectedIndex = 1 Then
            okisa = 17
        ElseIf Combohaba.SelectedIndex = 2 Then
            okisa = 24
        ElseIf Combohaba.SelectedIndex = 3 Then
            okisa = 28
        End If

        'フォントスタイル
        Dim ItemFont As Font = New Drawing.Font("MS Pゴシック", okisa, FontStyle.Bold)




        Dim haba As String = 0         '行幅
        Dim kazu As String = 0         '行数
        Dim waku As Integer = 0        '全体の枠の大きさ

        haba = Combohaba.SelectedItem
        kazu = Combokazu.SelectedItem

        waku = haba * kazu           '全体の枠=行数*行幅



        '**************************
        '         改行
        '**************************     

        Dim a As String = ""        '文字の幅
        Dim tasugyou As Integer = 0 '次の行へ

        For moji As Integer = 0 To RichTextBox1.Text.Length - 1  'リッチテキストのなかの文字全部


            a &= RichTextBox1.Text(moji)  'リッチテキストのなかの文字一つ一つaという変数に入れる

            If RichTextBox1.Text(moji) = ControlChars.Lf Then '改行させれれば書き込み
                e.Graphics.DrawString(a, ItemFont, Brushes.Black, 30, 340 + bityouseisita + (tasugyou * haba))
                a = ""
                tasugyou += 1

            End If


            Dim sTest As Single = g.MeasureString(a, ItemFont).Width
            If sTest > 760 Then          'aの文字幅が印刷ページの横幅よりもおおきくなったら書き込み改行
                e.Graphics.DrawString(a, ItemFont, Brushes.Black, 30, 340 + bityouseisita + (tasugyou * haba))
                a = ""
                tasugyou += 1
            End If
        Next


        '行幅、行数を指定して印刷内容に反映 

        haba = Combohaba.SelectedItem
        kazu = Combokazu.SelectedItem

        Dim n As Integer
        Dim gyousuu As Integer = 340 + haba '指定された幅を足し行間とする
        'Dim sotowaku As Integer
        For n = 0 To kazu       '指定されたkazuの行数繰り返し線を引く

            If n = 0 Then
                gyousuu = 340 + haba - haba
                e.Graphics.DrawLine(New Pen(Color.Black), 20, gyousuu, 810, gyousuu)
            Else
                gyousuu = gyousuu + haba

                e.Graphics.DrawLine(New Pen(Color.Black), 20, gyousuu, 810, gyousuu)

            End If
        Next
       

        e.HasMorePages = False



  End Sub



End Class
投稿者 shu  (社会人) 投稿日時 2012/2/7 16:16:50
PrintDocument1.Print()
をする前に描画ページ毎のデータに分割する必要があります。
分割したデータはPrivate変数にでも設定しておくと良いと思います。
この場合、行毎にした方が良いかもしれません。

ページ描画をしながら次のデータを描画するとそのページ内に収まらない
状態になるか分割したデータが最後までいったらループを終了して
データが最後までいっていたらe.HasMorePages = FalseをFalse、最後まで
いっていなかったらe.HasMorePages = Trueとするとよいと思います。
なお分割したデータの位置を記憶するのにもPrivate変数があると便利です。

PrintDocumentを使ったコーディングをする場合、PrintDocumentからの派生クラス
またはPrintDocumentをメンバに持つクラスを別に作成された方が処理が分かりやすく
なると思います。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2012/2/7 16:36:22
VB6 の RichTextBox には印刷機能があったのですが、
VB.NET では何故か無くなっているのですよね…。

VB.NET で、RichTextBox の内容を(書式付きで)印刷する方法が
以下に掲載されています。一応参考までに。
http://support.microsoft.com/kb/811401


> コンボボックスで指定した行数をこえた場合
この判定そのものは行えるのですよね?

改ページ位置の判定は、PrintPage イベントの中で行っても構いませんし、
印刷前にあらかじめ算出しておいても構わないと思いますが、事前に判定しておく場合は、
テキストデータを行単位に分割しておくと、印刷時に扱いやすいかも知れませんね。


> 改ページしたいのですが
PrintPage イベントを抜ける際に、「e.HasMorePages = True」にしておいてください。
そうすれば、次のページの印刷のために、もう一度 PrintPage イベントが呼び出されます。
(e.HasMorePages = False を指定するのは、最後のページを印刷し終わったときだけです)

結果として、PrintPage イベントは複数回呼ばれることになるため、
現在どのページを印刷しているのかは、Private 変数などで自己管理します。
(たとえば、Private currentPage As Integer など)

また、再度印刷したときのために、現在ページ位置をリセットできるよう、
BeginPrint/EndPrint イベントも利用してください。


以下、参考資料として:

[複数ページの印刷]
http://rucio.cloudapp.net/ThreadDetail.aspx?ThreadId=2220

[RichTextBoxの内容をA4の部分的範囲に印刷]
http://rucio.cloudapp.net/ThreadDetail.aspx?ThreadId=9730

[PrintPreviewDialogの印刷ボタンを使用不可にしたい。]
http://rucio.cloudapp.net/ThreadDetail.aspx?ThreadId=9987


--- 以下は、質問の本題とは関係ないところですが ---

> Dim g As Graphics = e.Graphics
変数 g を使って
 「Dim sTest As Single = g.MeasureString(a, ItemFont).Width」
のように処理している場所もあれば、
 「e.Graphics.DrawString(a, ItemFont, Brushes.Black, 30, 340 + bityouseisita + (tasugyou * haba))」
のように、e.Graphics を直接指定している個所もありますね。
今のままでも問題はありませんが、どちらかの表記に統一しておいた方がスマートかと。


> Dim ItemFont As Font = New Drawing.Font("MS Pゴシック", okisa, FontStyle.Bold)
上記の宣言は、下記のように記述する必要があります。

Using ItemFont As New Font("MS Pゴシック", okisa, FontStyle.Bold)

End Using



フォント名は、全角/半角や空白指定なども含めて正確に指定する必要があります。
今回の場合は、"MS Pゴシック" ではなく "MS Pゴシック" と指定せねばなりません。
(もしくは、英語名である "MS PGothic" でも良いですが)

フォント名が間違っていても動作はしますが、同じフォントが見つからない場合には
代替フォント(たとえば "Microsoft Sans Serif" など)に置き換えられてしまい、
正しく描画できない可能性があります。


また、印刷用に Font を New する場合は、Using ステートメントを利用するようにしましょう。
Using では都合が悪い場合には、最後に Dispose メソッドで破棄するようにします。
http://msdn.microsoft.com/ja-jp/library/system.drawing.font.dispose%28vs.80%29.aspx


> For moji As Integer = 0 To RichTextBox1.Text.Length - 1  'リッチテキストのなかの文字全部
個人的には
 RichTextBox1.Text.Length
よりも
 RichTextBox1.TextLength
を使う事をおすすめしておきます。意味は一緒なのですけれどね。
http://rucio.cloudapp.net/ThreadDetail.aspx?ThreadId=9187 


なお提示のサンプルだと、禁則処理や複合文字などの考慮が抜けているため、
たとえば文末に「ガ」や「ですが、」などの文章が来た場合において、位置によっては
濁点や句読点が次の行頭に送られてしまい、不自然な文章になってしまう点が
少し気になりました。あえてそうしているのであれば構わないのですけれども。


> e.Graphics.DrawLine(New Pen(Color.Black), 20, gyousuu, 810, gyousuu)
Font 同様、Pen や Brush も破棄すべきオブジェクトなので、この場合は、
Using p As New Pen(Color.Black)
    e.Graphics.DrawLine(p, 20, gyousuu, 810, gyousuu)
End Using
のように記述するか、または New せずに
e.Graphics.DrawLine(Pens.Black, 20, gyousuu, 810, gyousuu)
のように、出来合いのPenを利用するようにします。

ただし、Pens や Brushes の Shared ReadOnly なプロパティ群を使って描画する場合は、
それらの Pen や Brush を破棄しないように注意してください。
(Brushes.Black 等は自分で生成したものではないため、システム側に管理を任せた方が安全です)