2008年1月25日金曜日

.NET VistaではPageSetupDialogでプリンタ設定ボタンが表示されない

VistaではPageSetUpDialogでプリンタ設定ボタンが表示されません。
■XP PageSetUpDialog


■Vista PageSetUpDialog


■対応策
自作のページ設定画面を作成します。

プロパティボタンクリックで、PageSetUpDialogのプリンタ設定ボタンで開く「プリンタのプロパティ画面」を表示します。


プリンターのプロパティ画面を表示する方法ですが、プリンタを変更するとプリンタドライバに依存するDEVMODE 構造体部分がメモリ確保されていないためエラーになることがあり
Marshal.AllocCoTaskMemを使った方法を使用します。

コードはこちら .NET プリンターのプロパティ画面を表示するには

コード
Imports System.Runtime.InteropServices


 

Public Class frmPrinterSetting


 


 

    Private _printer As System.Drawing.Printing.PrinterSettings


 

#Region "API定義"

    ' API 定義

    Private Declare Auto Function OpenPrinter Lib "winspool.drv" ( _

        <MarshalAs(UnmanagedType.LPTStr)> ByVal pPrinterName As String, _

        ByRef phPrinter As IntPtr, _

        ByVal pDefault As IntPtr) As Int32


 

    Private Declare Auto Function DocumentProperties Lib "winspool.drv" ( _

        ByVal hwnd As IntPtr, _

        ByVal hPrinter As IntPtr, _

        <MarshalAs(UnmanagedType.LPTStr)> ByVal pDeviceName As String, _

        ByVal pDevModeOut As IntPtr, _

        ByVal pDevModeIn As IntPtr, _

        ByVal fMode As IntegerAs Int32


 

    Private Declare Auto Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As IntPtr) As Int32

    Private Declare Auto Function GlobalLock Lib "kernel32" (ByVal hmem As IntPtr) As IntPtr

    Private Declare Auto Function GlobalFree Lib "kernel32" (ByVal hmem As IntPtr) As Int32

    Private Declare Auto Function GlobalUnlock Lib "kernel32" (ByVal hMem As IntPtr) As Int32


 

    Private Const DM_OUT_BUFFER As Short = 2

    Private Const DM_IN_PROMPT As Short = 4

    Private Const DM_IN_BUFFER As Short = 8

#End Region


 

    Public Sub New()

        ' この呼び出しは、Windows フォーム デザイナで必要です。

        InitializeComponent()

        ' InitializeComponent() 呼び出しの後で初期化を追加します。

        Call Initialize()

    End Sub


 

    Private Sub Initialize()

        Me._printer = New System.Drawing.Printing.PrinterSettings

        'プリンターコンボボックスのデータを設定します。

        Me.cboPrinterName.BeginUpdate()

        For Each printerNm As String In Drawing.Printing.PrinterSettings.InstalledPrinters

            Me.cboPrinterName.Items.Add(printerNm)

        Next

        Me.cboPrinterName.EndUpdate()

        Call ToControl()

    End Sub


 

    Private Sub cboPrinterName_SelectedIndexChanged(ByVal sender As System.ObjectByVal e As System.EventArgs) _

    Handles cboPrinterName.SelectedIndexChanged

        Me._printer.PrinterName = Me.cboPrinterName.SelectedItem.ToString

        '用紙サイズコンボボックスのデータを設定します。

        Me.cboPaperSize.BeginUpdate()

        Me.cboPaperSize.DisplayMember = "PaperName"

        For Each paperSize As System.Drawing.Printing.PaperSize In Me._printer.PaperSizes

            Me.cboPaperSize.Items.Add(paperSize)

        Next

        Me.cboPaperSize.EndUpdate()

    End Sub


 

    Private Sub rdoPrintPage_CheckedChanged(ByVal sender As System.ObjectByVal e As System.EventArgs) _

    Handles rdoSomePages.CheckedChanged, rdoAllPages.CheckedChanged

        Dim rdo As RadioButton = CType(sender, RadioButton)

        If Not rdo.Checked Then

            Return

        End If

        If Me.rdoAllPages.Equals(rdo) Then

            Me.txtFromPage.Enabled = False

            Me.txtToPage.Enabled = False

        ElseIf Me.rdoSomePages.Equals(rdo) Then

            Me.txtFromPage.Enabled = True

            Me.txtToPage.Enabled = True

        End If

    End Sub


 

    Private Sub btnSetting_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) _

    Handles btnSetting.Click

        'コントロールの値をPrinterSettingsに設定します。

        Call ToPrinter()


 

        Dim hDevModeIn As IntPtr = Me._printer.GetHdevmode

        Dim hDevModeOut As IntPtr = Me._printer.GetHdevmode


 

        Dim pDevModeIn As IntPtr = GlobalLock(hDevModeIn)

        Dim pDevModeOut As IntPtr = GlobalLock(hDevModeOut)


 

        Dim hPrinter As IntPtr

        OpenPrinter(Me._printer.PrinterName, hPrinter, IntPtr.Zero)

        Dim rc As Integer = DocumentProperties(Me.Handle, hPrinter, Me._printer.PrinterName, pDevModeOut, pDevModeIn, DM_IN_PROMPT Or DM_IN_BUFFER Or DM_OUT_BUFFER)

        If rc = 1 Then

            Me._printer = New System.Drawing.Printing.PrinterSettings

            Me._printer.PrinterName = Me.cboPrinterName.SelectedItem.ToString

            Me._printer.SetHdevmode(pDevModeOut)

            'PrinterSettings値をコントロールに設定します。

            Call ToControl()

        End If


 

        GlobalUnlock(hDevModeIn)

        GlobalUnlock(hDevModeOut)

        GlobalFree(hDevModeIn)

        GlobalFree(hDevModeOut)

        ClosePrinter(hPrinter)

    End Sub


 

    Private Sub btnCancel_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) _

    Handles btnCancel.Click

        Me.Close()

    End Sub


 

    Private Sub btnPrint_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) _

    Handles btnPrint.Click

        '印刷処理

    End Sub


 

    Private Sub ToPrinter()

        If Not Me._printer.PrinterName.Equals(Me.cboPrinterName.SelectedItem.ToString) Then

            Me._printer.PrinterName = cboPrinterName.SelectedItem.ToString

        End If

        Me._printer.DefaultPageSettings.PaperSize = CType(Me.cboPaperSize.SelectedItem, System.Drawing.Printing.PaperSize)

        If Me.rdoAllPages.Checked Then

            Me._printer.PrintRange = Printing.PrintRange.AllPages

        ElseIf Me.rdoSomePages.Checked Then

            Me._printer.PrintRange = Printing.PrintRange.SomePages

            Me._printer.FromPage = CInt(Me.txtFromPage.Text)

            Me._printer.ToPage = CInt(Me.txtToPage.Text)

        End If

        Me._printer.DefaultPageSettings.Landscape = Me.rdoHorizontal.Checked

        Me._printer.Copies = CShort(Me.nudCopies.Value)

    End Sub


 

    Private Sub ToControl()

        Me.cboPrinterName.SelectedItem = Me._printer.PrinterName

        Me.cboPaperSize.Text = Me._printer.DefaultPageSettings.PaperSize.PaperName

        If Me._printer.PrintRange = Printing.PrintRange.AllPages Then

            Me.rdoAllPages.Checked = True

        ElseIf Me._printer.PrintRange = Printing.PrintRange.SomePages Then

            Me.rdoSomePages.Checked = True

            Me.txtFromPage.Text = Me._printer.FromPage.ToString

            Me.txtToPage.Text = Me._printer.ToPage.ToString

        End If

        If Me._printer.DefaultPageSettings.Landscape Then

            Me.rdoHorizontal.Checked = True

        Else

            Me.rdoVertical.Checked = True

        End If

        Me.nudCopies.Value = Me._printer.Copies

    End Sub


 

End Class

0 件のコメント: