複数ページにわたる画像の印刷処理について

タグの編集
投稿者 ミニオン  (学生) 投稿日時 2018/11/23 19:55:42
データを読み込み、そのデータをグラフとして描画し、印刷したいのですが
データ量によって画像の幅が変わる為、複数ページに分割して印刷する処理を
色々考えたのですが上手くいかず、困っています。

やりたい事は
A4横の用紙に、
①用紙上部は「現在ページ数/総ページ数」、「印刷日」といった情報を印字
②用紙左部はグラフのY座標の目盛等の情報を印字
→①②はヘッダとして、各ページに印字
③読み込んだデータをグラフとして、左から右へ印字し、
グラフがページの印刷可能な範囲を超えた場合、次ページへ続きから印字
という処理です。

ネットで印刷処理について、調べているうちに、
プリンタの解像度や、印刷範囲を取得して、その情報によって処理を行うような事が
書いてあり、正直自分の手に負えなくなってきました。

お手数ですが、ご教示の程、宜しくお願い致します。
(一応以下に、考えたコードを載せておきます)

'Button1のClickイベントハンドラ
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        'PrintDocumentオブジェクトの作成
        Dim pd As New System.Drawing.Printing.PrintDocument

        '用紙:横向き
        pd.DefaultPageSettings.Landscape = True

        'PrintPageイベントハンドラの追加
        AddHandler pd.PrintPage, AddressOf pd_PrintPage

        '印刷を開始する
        pd.Print()

End Sub

'PrintPage処理
Private Sub pd_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)

        '※ここに処理を追加し、下記処理「DrawGraph」をページ毎に制御できないかと考えています。

        '画像を描画する
        DrawGraph(e)


End Sub

'画像(グラフ)描画処理
Private Sub DrawGraph(ByVal e As System.Drawing.Printing.PrintPageEventArgs)

        '共通部(ヘッダ)の描画
        e.Graphics.DrawString("ヘッダ部", New Font("MS ゴシック", 20), Brushes.Black, 10, 10)

        '共通部(Y軸、X軸)の描画
        e.Graphics.DrawLine(Pens.Black, 80, 100, 80, 660)
        e.Graphics.DrawLine(Pens.Black, 80, 660, 1168, 660)

        '共通部(Y軸の目盛、補助線)の描画
        e.Graphics.DrawString("(℃)", New Font("MS ゴシック", 10), Brushes.Black, 50, 100)
        e.Graphics.DrawString("35", New Font("MS ゴシック", 10), Brushes.Black, 60, 150)
        e.Graphics.DrawString("30", New Font("MS ゴシック", 10), Brushes.Black, 60, 200)
        e.Graphics.DrawString("25", New Font("MS ゴシック", 10), Brushes.Black, 60, 250)
        e.Graphics.DrawString("20", New Font("MS ゴシック", 10), Brushes.Black, 60, 300)
        e.Graphics.DrawString("15", New Font("MS ゴシック", 10), Brushes.Black, 60, 350)
        e.Graphics.DrawString("10", New Font("MS ゴシック", 10), Brushes.Black, 60, 400)
        e.Graphics.DrawString("5", New Font("MS ゴシック", 10), Brushes.Black, 65, 450)
        e.Graphics.DrawString("0", New Font("MS ゴシック", 10), Brushes.Black, 65, 500)
        e.Graphics.DrawString("-5", New Font("MS ゴシック", 10), Brushes.Black, 60, 550)
        e.Graphics.DrawString("-10", New Font("MS ゴシック", 10), Brushes.Black, 55, 600)
        e.Graphics.DrawString("-15", New Font("MS ゴシック", 10), Brushes.Black, 55, 650)

        e.Graphics.DrawLine(Pens.Gray, 80, 160, 1168, 160)
        e.Graphics.DrawLine(Pens.Gray, 80, 210, 1168, 210)
        e.Graphics.DrawLine(Pens.Gray, 80, 260, 1168, 260)
        e.Graphics.DrawLine(Pens.Gray, 80, 310, 1168, 310)
        e.Graphics.DrawLine(Pens.Gray, 80, 360, 1168, 360)
        e.Graphics.DrawLine(Pens.Gray, 80, 410, 1168, 410)
        e.Graphics.DrawLine(Pens.Gray, 80, 460, 1168, 460)
        e.Graphics.DrawLine(Pens.Gray, 80, 510, 1168, 510)
        e.Graphics.DrawLine(Pens.Gray, 80, 560, 1168, 560)
        e.Graphics.DrawLine(Pens.Gray, 80, 610, 1168, 610)


        'グラフデータ部の描画
            '※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
        '※実際は、この部分の処理を
        '①foreach等のループ処理を用いて、実際のデータ(データテーブル等)を描画する。
        '②データの描画が、ページの描画範囲を超えた場合、次ページへ

        e.Graphics.DrawString("12/1", New Font("MS ゴシック", 8), Brushes.Black, 95, 670)
        e.Graphics.DrawLine(Pens.Black, 100, 410, 200, 390)
        e.Graphics.DrawString("12/2", New Font("MS ゴシック", 8), Brushes.Black, 195, 670)
        e.Graphics.DrawLine(Pens.Black, 200, 390, 300, 411)
        e.Graphics.DrawString("12/3", New Font("MS ゴシック", 8), Brushes.Black, 295, 670)

        '※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※


 End Sub
投稿者 shu  (社会人) 投稿日時 2018/11/24 19:51:15
だいぶ端折ってますが以下のような感じで処理を行います。
(1)BeginPrintでデータをページ毎に分割、総ページ数を求める
(2)PrintPageにて最終ページに達していない間e.HasMorePageをTrueにする
(3)グラフ描画部分はそのページ分を取得して描画を行う。

    Private Const XZero As Integer = 80
    Private Const XInt As Integer = 100
    Private Const XMin As Integer = 80
    Private Const XMax As Integer = 700
    Private Const YZero As Integer = 500
    Private Const YInt As Integer = 50
    Private Const YMin As Integer = 100
    Private Const YMax As Integer = 660
    Private Const YMin2 As Integer = 160
    Private Const YMax2 As Integer = 610
    Private Const XAxisY As Integer = 670

    Private FntHeader As Font
    Private FntYAxis As Font
    Private FntXAxis As Font

    Private DataGrps As List(Of Single())
    Private Data As List(Of Single)
    Private XNumPage As Integer
    Private Idx As Integer
    Private Pages As Integer

    Private Sub pd_QueryPageSettings(sender As Object, e As QueryPageSettingsEventArgs) Handles pd.QueryPageSettings
        e.PageSettings.Landscape = True
    End Sub

    Private Sub pd_BeginPrint(sender As Object, e As PrintEventArgs) Handles pd.BeginPrint
        FntHeader = New Font("MS ゴシック", 20.0!)
        FntYAxis = New Font("MS ゴシック", 10.0!)
        FntXAxis = New Font("MS ゴシック", 8.0!)

        'ページ毎のポイント数 
        XNumPage = (XMax - XMin) \ XInt
        Dim st = 0
        DataGrps = New List(Of Single())
        For Each itm2 In (From itm In Data.Select(Function(d, idx) New With {.data = d, .index = idx})
                          Let Page = itm.index \ XNumPage
                          Group itm.data By Page Into Group
                          Order By Page)
            DataGrps.Add(itm2.Group.ToArray)
        Next
        Pages = DataGrps.Count
        Idx = 0
    End Sub

    Private Sub pd_EndPrint(sender As Object, e As PrintEventArgs) Handles pd.EndPrint
        FntHeader.Dispose()
        FntYAxis.Dispose()
        FntXAxis.Dispose()
    End Sub

    Private Sub pd_PrintPage(sender As Object, e As PrintPageEventArgs) Handles pd.PrintPage
        Dim g = e.Graphics
        DrawHead(g)
        DrawAxis(g)
        DrawPoints(g)

        Idx += 1
        If Idx < Pages Then
            e.HasMorePages = True
        Else
            e.HasMorePages = False
        End If
    End Sub

    Private Sub DrawHead(g As Graphics)
        g.DrawString($"ヘッダ部({Idx + 1}/{Pages})", FntHeader, Brushes.Black, 10, 10)
    End Sub

    Private Sub DrawAxis(g As Graphics)
        g.DrawLine(Pens.Black, XMin, YMin, XMin, YMax)
        g.DrawLine(Pens.Black, XMin, YMax, XMax, YMax)
        For y = YMin2 To YMax2 Step YInt
            g.DrawLine(Pens.Gray, XMin, y, XMax, y)
        Next
    End Sub

    Private Sub DrawPoints(g As Graphics)
        Dim Points = DataGrps(Idx)
        Dim x1 = XMin
        Dim x2 = x1 + XInt
        Dim y1 = 0
        Dim IsFirst = True

        For Each pt In Points
            Dim y2 = YZero - (pt / 5) * YInt
            If IsFirst Then
                IsFirst = False
            Else
                g.DrawString("12/1", FntXAxis, Brushes.Black, x1 + 5, XAxisY)
                g.DrawLine(Pens.Black, x1, y1, x2, y2)
            End If
            x1 = x2
            x2 = x1 + XInt
            y1 = y2
        Next
    End Sub

投稿者 ミニオン  (学生) 投稿日時 2018/12/6 18:48:54
>shuさん

返信が遅れ申し訳ありません。

ご回答頂きありがとうございました。

複数ページの印刷については、ご回答内容で解決しそうですので、
一応解決と致します。
(というのは、ご回答いただいたコードのConst部分の値が、上手く取得できず
その辺りで色々やってるところです。。。)