玄関へお回り下さい。
プリンターの印刷余白(印刷開始位置)及び用紙サイズを取得 (3)            (SNo.132)
使用コントロール Form1 Button1  ComboBox1 PrintDocument1
その他条件 WindowsXP(Vista) Visual Basic 2005(VB2008)
WindowsXP(SP2) Visual Basic 2005(E E) Framework 2.0 
★ プリンター個々の印刷開始位置(Left ・Top マージン)を取得の改良版
'-------------- Win32 API 関数の宣言部分 ----------------------
Private Const PHYSICALOFFSETX As Integer = 112      '印刷可能な左方向のマージン
Private Const PHYSICALOFFSETY As Integer = 113      '印刷可能な上方向のマージン
Private Const PHYSICALWIDTH As Integer = 110        '物理的幅(実用紙サイズ)
Private Const PHYSICALHEIGHT As Integer = 111       '物理的高さ

Private Const HORZRES As Integer = 8                '実際のスクリーンの幅(実印刷領域)
Private Const VERTRES As Integer = 10               '実際のスクリーンの高さ
Private Const HORZSIZE As Integer = 4               '実際のスクリーンの幅(実印刷領域)
Private Const VERTSIZE As Integer = 6               '実際のスクリーンの高さ

'ディバイスに関する情報を取得する(908)
<System.Runtime.InteropServices.DllImport("gdi32.dll", _
   CharSet:=Runtime.InteropServices.CharSet.Auto)> _
Private Shared Function GetDeviceCaps( _
   
ByVal Phdc As IntPtr, ByVal cIndex As Int32) As Int32
End Function
'マージンの取得結果の構造体
Private Structure PrintMargin
   
Dim Top As Integer
   
Dim Left As Integer
   
Dim Right As Integer
   
Dim Bottom As Integer
   
Dim PaperWidth As Integer
   
Dim PaperHeight As Integer
End Structure

'-------------- 余白取得の為の自作関数の部分 ----------------------
Private Function GetPrtMargin( _
           
ByVal pe As System.Drawing.Printing.PrintPageEventArgs) As PrintMargin
'プリンター個々の印刷開始位置を取得する関数
   
Dim Widmm, Widpc, Heimm, Heipc, pWid, pHei As Integer, ScaleY, ScaleX As Single
   
Dim m As PrintMargin
   
Dim hdc As IntPtr = pe.Graphics.GetHdc          'プリンターのDCハンドルを取得
   Widmm = GetDeviceCaps(hdc, HORZSIZE)           
'実際の用紙の幅をmm単位で取得
   Widpc = GetDeviceCaps(hdc, HORZRES)             
'実際の用紙の幅をPixel単位で取得
   Heimm = GetDeviceCaps(hdc, VERTSIZE)           
'実際の用紙の高さをmm単位で取得
   Heipc = GetDeviceCaps(hdc, VERTRES)             
'実際の用紙の高さをPixel単位で取得
   ScaleX = Widpc / Widmm                         
'mm当りのピクセル数を取得
   ScaleY = Heipc / Heimm                         
'mm当りのピクセル数を取得
   m.Left = GetDeviceCaps(hdc, PHYSICALOFFSETX)   
'実際に印刷可能なX方向のマージン
   m.Top = GetDeviceCaps(hdc, PHYSICALOFFSETY)     
'実際に印刷可能なY方向のマージン
   m.Left = m.Left / ScaleX                       
'マージンをmm単位に変換
   m.Top = m.Top / ScaleY                         
'マージンをmm単位に変換
   pWid = GetDeviceCaps(hdc, PHYSICALWIDTH)       
'実用紙幅取得(Pixel)
   pHei = GetDeviceCaps(hdc, PHYSICALHEIGHT)       
'実用紙高さ取得(Pixel)
   m.PaperWidth = pWid / ScaleX                   
'実用紙幅(mm に変換)
   m.PaperHeight = pHei / ScaleY                   
'実用紙高さ(mm に変換)
   m.Right = m.PaperWidth - m.Left - Widmm         
'実際に印刷可能な右端のマージン
   m.Bottom = m.PaperHeight - m.Top - Heimm       
'実際に印刷可能な下端のマージン
   pe.Graphics.ReleaseHdc(hdc)                     
'デバイスコンテキストハンドルを解放
   
Return m                                        '戻り値を設定
End Function

'-------------- 上記自作関数の動作確認の部分 ----------------------
Private
 Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As _
        System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
'テスト印刷
   'プリンターのマージン取得へ
   Dim m As PrintMargin = GetPrtMargin(e)

   '---------------------------  以下は参考のため  ------------------------------
   'マージンの取得結果を表示
   MessageBox.Show(PrintDocument1.PrinterSettings.PrinterName & vbCrLf & _
           String.Format("TopMargin= {0}  LeftMargin= {1}  RightMargin= {2}" & _
                "  BottomMargin= {3}  " & "用紙サイズ= {4}×{5}", m.Top, m.Left, _
                   m.Right, m.Bottom, m.PaperWidth, m.PaperHeight))

   '        e.Cancel = True     '印刷をキャンセルする場合

   '-----------------------  印刷して確認する場合  ------------------------------
   Dim g As Graphics = e.Graphics
   'ミリメートルを長さの単位に指定します。
   g.PageUnit = GraphicsUnit.Millimeter
   '左から20mm 上から40mm の位置に印刷します
   g.DrawString("■左から20mm 上から40mm の位置に印刷しました。", _
       New Font("MS Pゴシック", 12), Brushes.Black, 20 - m.Left, 40 - m.Top)
End Sub
Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, _
                ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
'コンボボックスからプリンターを選択
   PrintDocument1.PrinterSettings.PrinterName = ComboBox1.Text
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 Form1_Load(ByVal sender As System.Object, _
                       ByVal e As System.EventArgs) Handles MyBase.Load
'使用するプリンターの一覧を取得し、コンボボックスに表示
   Dim ip As String
   For Each ip In System.Drawing.Printing.PrinterSettings.InstalledPrinters
      ComboBox1.Items.Add(ip)
      If PrintDocument1.PrinterSettings.PrinterName = ip Then
         ComboBox1.Text = ip
      End If
   Next
End Sub

VB2005 (.NET Framework version 2.0) 以降の場合

Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As _
        System.Drawing.Printing.PrintPageEventArgs) 
Handles PrintDocument1.PrintPage
'--------------- HardMarginX は、.NET Framework version 2.0 からの機能です ------------
   'VB2005 以降なら下記の2行で取得できます。
   
Dim lm As Integer = 0.254! * PrintDocument1.DefaultPageSettings.HardMarginX
   
Dim tm As Integer = 0.254! * PrintDocument1.DefaultPageSettings.HardMarginY
   Debug.WriteLine(lm & "   " & tm)
'----------------------------------------------------------------------------------
End Sub
 上記実行結果
    
 
プリンターにより、印刷開始位置が違うので位置を揃える必要があるような場合、あらかじめ開始位置(余白)を取得して、その分を考慮しておくとプリンターによる印刷位置のずれが防止できます。
VB6.0 用に作成していた物を .NET 用に移植したものです。

以前、VB2003 で作成したサンプルを掲載していたのですが、VB2005 がリリースされた事もあってVB2003 で作成したサンプルを見直していた際に削除していたのですが、見直しが一応完了したので、再び掲載する事にしました。


2004/07/10
2006/07/08


VBレスキュー(花ちゃん)
VB.NET2003  VB2005