1. Herfried K. Wagner’s VB.Any
  2. .NET
  3. Frequently Asked Questions

Determining a printer’s physical margins

Determining a printer's physical margins
<URL:https://dotnet.currifex.org/dotnet/faqs/getphysicalprintermargins/en/>
----------------------------------------------------------------------------

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.
These methods can be either called by supplying a handle to the device's
context or a 'Graphics' object. The printer may have a margin that is
different from the PrintPreviewDialog's margin.

\\\
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
        Dim g As Graphics = Graphics.FromHdc(hDC)
        Dim m As Margins = GetPhysicalMargins(hDC, g)
        g.Dispose()
        Return m
    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
    Dim g As Graphics = p.CreateMeasurementGraphics()
    MsgBox( _
        PrinterName & ControlChars.NewLine & _
        Device.GetPhysicalMargins(g).ToString() & " [0.01 inch]" _
    )
    g.Dispose() 
Next PrinterName
///