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

投稿で使用できる特殊コードの説明。(別タブで開きます。)
本名は入力しないようにしましょう。
投稿した後で削除するときに使うパスワードです。返答があった後は削除できません。
返答する人が目安にします。相手が小学生か社会人かで返答の仕方も変わります。
最初の投稿が質問の場合、質問者が解決時にチェックしてください。(以降も追加書き込み・返信は可能です。)
※「過去ログ」について書くときはその過去ログのURLも書いてください。

以下の返答は逆順(新しい順)に並んでいます。

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

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

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

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