DOBON.NET DOBON.NETプログラミング掲示板過去ログ

印刷速度が違うのはなぜ?

環境/言語:[XPPro/VB.NET2005/.NETFramework2.0]
分類:[.NET]

はじめまして、VB.NET2005 の PrintDocument / PrinterSettings / PageSettings
の処理で分からない所があるので質問させてください。

以下のソースにて、2つのボタンで印刷処理の速度が全く異なります。
「PageSetupDialog未使用」の方が明らかに遅いのです。

100ページ程度印刷するプログラムを作成していたのですが、ページ設定部分を
独自ダイアログに変更したところ何故か印刷に時間がかかるようになってしまい
ました。
原因が分からなかった為、テストプログラムを作成しましたが同様の現象が発生
しております。

何か勘違いをしているのでしょうか?どなたかヒントを頂けないでしょうか?
よろしくお願いします。

Imports System.Drawing.Printing

Public Class Form1

Dim PS As New PageSetupDialog
Dim WithEvents PD As New PrintDocument
Dim PV As New PrintPreviewDialog
Dim pagecount As Integer
Dim WithEvents Button1 As New Button
Dim WithEvents Button2 As New Button

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

PD.PrinterSettings = New PrinterSettings
PD.DefaultPageSettings = New PageSettings

PS.PrinterSettings = PD.PrinterSettings
PS.PageSettings = PD.DefaultPageSettings

If (PS.ShowDialog() <> Windows.Forms.DialogResult.OK) Then Return

PV.Document = PD
PV.ShowDialog()

End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

PD.PrinterSettings = New PrinterSettings
PD.DefaultPageSettings = New PageSettings
PD.DefaultPageSettings.PrinterSettings = New PrinterSettings

PV.Document = PD
PV.ShowDialog()

End Sub

Private Sub PD_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs)
pagecount = 1
End Sub

Private Sub PD_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PD.PrintPage
Using font As New Font("MS ゴシック", 10)
e.Graphics.DrawString("文字列", font, Brushes.Black, 10, 10)
e.Graphics.DrawString("文字列", font, Brushes.Black, 10, 20)
e.Graphics.DrawString("文字列", font, Brushes.Black, 10, 30)
e.Graphics.DrawString("文字列", font, Brushes.Black, 10, 40)
e.Graphics.DrawString("文字列", font, Brushes.Black, 10, 50)
e.Graphics.DrawString("文字列", font, Brushes.Black, 10, 60)
End Using

pagecount += 1

If (pagecount < 500) Then e.HasMorePages = True
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Button1.Text = "PageSetupDialog使用"
Button1.Width = Me.Width
Button2.Text = "PageSetupDialog未使用"
Button2.Width = Me.Width
Button1.Parent = Me
Button2.Parent = Me
Button2.Top = Button1.Height

AddHandler Button1.Click, AddressOf Me.Button1_Click
AddHandler Button2.Click, AddressOf Me.Button2_Click

AddHandler PD.BeginPrint, AddressOf Me.PD_BeginPrint
AddHandler PD.PrintPage, AddressOf Me.PD_PrintPage
End Sub

End Class
この投稿はマルチポストです。

●マルチポストされている場所
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=3556325&SiteID=7

----------
この掲示板ではマルチポストが禁止されています。詳しくは、「書き込みのマナーについて」をお読みください。

●書き込みのマナーについて
http://dobon.net/vb/bbs/index.html
2008/07/04(Fri) 13:51:08 編集(投稿者)

■No22386に返信((報告)さんの記事)
> この投稿はマルチポストです。
>
> ●マルチポストされている場所
> http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=3556325&SiteID=7
>
> ----------
> この掲示板ではマルチポストが禁止されています。詳しくは、「書き込みのマナーについて」をお読みください。
>
> ●書き込みのマナーについて
> http://dobon.net/vb/bbs/index.html

すみません。完全解決後にフィードバックするつもりだったのですが、
それではルール違反になってしまうのですね。
#2週間前なので誰も見ていないだろうという甘い考えがありました。
今後はこのようなことの無い様気をつけます。

リンク先のサイトでは、私的には解決しているので参考にしてください。
#フィードバック可能か確認中です。
解決済み!
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=3573778&SiteID=7&mode=1

上記のサイトで寄せていただいた情報により解決したコードを掲載させていただきます。DEVMODE構造体の入手はついでなので不要です。

Imports System.Drawing.Printing
' ここから不要
Imports System.Runtime.InteropServices
' ここまで不要

Public Class Form1

    ' ここから不要
    <DllImport("kernel32.dll")> Private Shared Function GlobalLock(ByVal hMem As IntPtr) As IntPtr
    End Function

    <DllImport("kernel32.dll")> Private Shared Function GlobalUnlock(ByVal hMem As IntPtr) As IntPtr
    End Function
    ' ここまで不要

    <DllImport("kernel32.dll")> Private Shared Function GlobalFree(ByVal hMem As IntPtr) As IntPtr
    End Function

    ' ここから不要
    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
    Public Structure DEVMODE
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=32)> _
        Public dmDeviceName As String
        Public dmSpecVersion As Short
        Public dmDriverVersion As Short
        Public dmSize As Short
        Public dmDriverExtra As Short
        Public dmFields As Integer
        Public dmOrientation As Short
        Public dmPaperSize As Short
        Public dmPaperLength As Short
        Public dmPaperWidth As Short
        Public dmScale As Short
        Public dmCopies As Short
        Public dmDefaultSource As Short
        Public dmPrintQuality As Short
        Public dmColor As Short
        Public dmDuplex As Short
        Public dmYResolution As Short
        Public dmTTOption As Short
        Public dmCollate As Short
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=32)> _
        Public dmFormName As String
        Public dmLogPixels As Short
        Public dmBitsPerPel As Short
        Public dmPelsWidth As Integer
        Public dmPelsHeight As Integer
        Public dmDisplayFlags As Integer
        Public dmDisplayFrequency As Integer
        Public dmICMMethod As Integer
        Public dmICMIntent As Integer
        Public dmMediaType As Integer
        Public dmDitherType As Integer
        Public dmReserved1 As Integer
        Public dmReserved2 As Integer
        Public dmPanningWidth As Integer
        Public dmPanningHeight As Integer
    End Structure
    ' ここまで不要

    Dim PS As New PageSetupDialog
    Dim WithEvents PD As New PrintDocument
    Dim PV As New PrintPreviewDialog
    Dim pagecount As Integer
    Dim WithEvents Button1 As New Button
    Dim WithEvents Button2 As New Button

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

        PD.PrinterSettings = New PrinterSettings
        PD.DefaultPageSettings = New PageSettings

        PS.PrinterSettings = PD.PrinterSettings
        PS.PageSettings = PD.DefaultPageSettings

        If (PS.ShowDialog() <> Windows.Forms.DialogResult.OK) Then Return

        PV.Document = PD
        PV.ShowDialog()

    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

        PD.PrinterSettings = New PrinterSettings
        PD.DefaultPageSettings = New PageSettings
        PD.DefaultPageSettings.PrinterSettings = New PrinterSettings

        Dim hDevMode As IntPtr = IntPtr.Zero
        Dim hDevNames As IntPtr = IntPtr.Zero
        Dim hPtrDevMode As IntPtr = IntPtr.Zero

        Try
            hDevMode = PD.PrinterSettings.GetHdevmode()
            hDevNames = PD.PrinterSettings.GetHdevnames()

            ' ここから不要
            ' DEVMODE 構造体の入手
            hPtrDevMode = GlobalLock(hDevMode)
            Dim dModDefPgStngs_Hdevmode As DEVMODE = CType(Marshal.PtrToStructure(hPtrDevMode, GetType(DEVMODE)), DEVMODE)
            Marshal.StructureToPtr(dModDefPgStngs_Hdevmode, hPtrDevMode, True)  ' 構造体からポインタにコピー

            GlobalUnlock(hDevMode)
            ' ここまで不要

            PD.DefaultPageSettings.SetHdevmode(hDevMode)
            PD.DefaultPageSettings.PrinterSettings.SetHdevnames(hDevNames)
            PD.PrinterSettings.SetHdevmode(hDevMode)
            PD.PrinterSettings.SetHdevnames(hDevNames)

        Finally
            '(GlobalFree の戻り値チェックは省略)
            If (hDevMode <> IntPtr.Zero) Then GlobalFree(hDevMode)
            If (hDevNames <> IntPtr.Zero) Then GlobalFree(hDevNames)
        End Try

        PV.Document = PD

        PV.ShowDialog()

    End Sub

    Private Sub PD_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs)
        pagecount = 1
    End Sub

    Private Sub PD_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PD.PrintPage
        Using font As New Font("MS ゴシック", 10)
            e.Graphics.DrawString("文字列", font, Brushes.Black, 10, 10)
            e.Graphics.DrawString("文字列", font, Brushes.Black, 10, 20)
            e.Graphics.DrawString("文字列", font, Brushes.Black, 10, 30)
            e.Graphics.DrawString("文字列", font, Brushes.Black, 10, 40)
            e.Graphics.DrawString("文字列", font, Brushes.Black, 10, 50)
            e.Graphics.DrawString("文字列", font, Brushes.Black, 10, 60)
        End Using

        pagecount += 1

        If (pagecount < 500) Then e.HasMorePages = True
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Button1.Text = "PageSetupDialog使用"
        Button1.Width = Me.Width
        Button2.Text = "PageSetupDialog未使用"
        Button2.Width = Me.Width
        Button1.Parent = Me
        Button2.Parent = Me
        Button2.Top = Button1.Height

        AddHandler Button1.Click, AddressOf Me.Button1_Click
        AddHandler Button2.Click, AddressOf Me.Button2_Click

        AddHandler PD.BeginPrint, AddressOf Me.PD_BeginPrint
        AddHandler PD.PrintPage, AddressOf Me.PD_PrintPage
    End Sub

End Class
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板