Determining a Printer’s Physical Margins
The .NET Framework does not provide a managed way to access a printer’s (device’s) physical margins. The Device
class’ methods GetPhysicalMargins
can be used to determine a printer’s physical margins. The printer may have a margin that is different from the PrintPreviewDialog’s margin. The methods below methods can be either called by supplying a handle to the device’s context or a Graphics
object:
Imports System.Drawing.Printing
''' <summary>
''' Provides information about a device.
''' </summary>
Public Class Device
Private Declare Function GetDeviceCaps Lib "gdi32.dll" ( _
ByVal hdc As IntPtr, _
ByVal nIndex As Int32 _
) As Int32
Private Const PHYSICALOFFSETX As Int32 = 112 ' In device units.
Private Const PHYSICALOFFSETY As Int32 = 113 ' In device units.
Private Const HORZRES As Int32 = 8 ' In pixels/dots.
Private Const VERTRES As Int32 = 10 ' In pixels/dots.
''' <summary>
''' Gets a device's physical margins.
''' </summary>
''' <param name="Graphics">The device's <c>Graphics</c> object.</param>
''' <returns>
''' The device's physical margins in 0.001 inch units.
''' </returns>
Public Shared Function GetPhysicalMargins( _
ByVal Graphics As Graphics _
) As Margins
Dim hDC As IntPtr = Graphics.GetHdc()
Dim m As Margins = GetPhysicalMargins(hDC, Graphics)
Graphics.ReleaseHdc(hDC)
Return m
End Function
''' <summary>
''' Gets a device's physical margins.
''' </summary>
''' <param name="hDC">Handle to the device context.</param>
''' <returns>
''' The device's physical margins in 0.001 inch units.
''' </returns>
Public Shared Function GetPhysicalMargins( _
ByVal hDC As IntPtr _
) As Margins
Using g As Graphics = Graphics.FromHdc(hDC)
Return GetPhysicalMargins(hDC, g)
End Using
End Function
''' <summary>
''' Gets a device's physical margins.
''' </summary>
''' <param name="hDC">Handle to the device context.</param>
''' <param name="Graphics">The device's <c>Graphics</c> object.</param>
''' <returns>
''' The device's physical margins in 0.001 inch units.
''' </returns>
Private Shared Function GetPhysicalMargins( _
ByVal hDC As IntPtr, _
ByVal Graphics As Graphics _
) As Margins
Dim m As New Margins()
Dim ox As Int32 = GetDeviceCaps(hDC, PHYSICALOFFSETX)
Dim oy As Int32 = GetDeviceCaps(hDC, PHYSICALOFFSETY)
With m
.Left = CInt(ox * 100 / Graphics.DpiX)
.Top = CInt(oy * 100 / Graphics.DpiY)
.Right = _
CInt( _
(ox + GetDeviceCaps(hDC, HORZRES)) * 100 / _
Graphics.DpiX _
)
.Bottom = _
CInt( _
(oy + GetDeviceCaps(hDC, VERTRES)) * 100 / _
Graphics.DpiY _
)
End With
Return m
End Function
End Class
Usage:
Dim p As New PrinterSettings()
For Each PrinterName As String In PrinterSettings.InstalledPrinters
p.PrinterName = PrinterName
Using g As Graphics = p.CreateMeasurementGraphics()
MsgBox( _
PrinterName & ControlChars.NewLine & _
Device.GetPhysicalMargins(g).ToString() & " [0.01 inch]" _
)
End Using
Next PrinterName