Private Declare PtrSafe Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Private Declare PtrSafe Function GetDeviceCaps Lib "gdi32" (ByVal hdc As LongPtr, ByVal nIndex As Long) As Long
Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hWnd As LongPtr) As LongPtr
Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hWnd As LongPtr, ByVal hdc As LongPtr) As Long
Private Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr
Private Declare PtrSafe Function MonitorFromWindow Lib "user32" (ByVal hWnd As LongPtr, ByVal dwFlags As Long) As LongPtr
Private Declare PtrSafe Function GetMonitorInfo Lib "user32" Alias "GetMonitorInfoA" (ByVal hMonitor As LongPtr, ByRef lpmi As MONITORINFOEX) As Boolean
Private Declare PtrSafe Function CreateDC Lib "gdi32" Alias "CreateDCA" (ByVal lpDriverName As String, ByVal lpDeviceName As String, ByVal lpOutput As String, lpInitData As LongPtr) As LongPtr
Private Declare PtrSafe Function DeleteDC Lib "gdi32" (ByVal hdc As LongPtr) As Long
Private Const SM_CMONITORS As Long = 80
Private Const MONITOR_CCHDEVICENAME As Long = 32
Private Const MONITOR_PRIMARY As Long = 1
Private Const MONITOR_DEFAULTTONULL As Long = 0
Private Const MONITOR_DEFAULTTOPRIMARY As Long = 1
Private Const MONITOR_DEFAULTTONEAREST As Long = 2
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type MONITORINFOEX
cbSize As Long
rcMonitor As RECT
rcWork As RECT
dwFlags As Long
szDevice As String * MONITOR_CCHDEVICENAME
End Type
Private Enum DevCap
HORZSIZE = 4
VERTSIZE = 6
HORZRES = 8
VERTRES = 10
BITSPIXEL = 12
LOGPIXELSX = 88
LOGPIXELSY = 90
COLORRES = 108
VREFRESH = 116
End Enum
Public Function ScreenParameter(Item As String, Optional ActiveWindowID As LongPtr) As Variant
Dim xHSizeSq As Double, xVSizeSq As Double, xPix As Double, xDot As Double
Dim hWnd As LongPtr, hdc As LongPtr, hMonitor As LongPtr
Dim tMonitorInfo As MONITORINFOEX
Dim nMonitors As Integer
Dim vResult As Variant
Dim sItem As String
Application.Volatile
nMonitors = GetSystemMetrics(SM_CMONITORS)
If nMonitors < 2 Then
nMonitors = 1
hWnd = 0
Else
If ActiveWindowID <> 0 Then
hWnd = ActiveWindowID
Else
hWnd = GetActiveWindow()
End If
hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONULL)
If hMonitor = 0 Then
Debug.Print "ActiveWindow does not intersect a monitor"
hWnd = 0
Else
tMonitorInfo.cbSize = Len(tMonitorInfo)
If GetMonitorInfo(hMonitor, tMonitorInfo) = False Then
Debug.Print "GetMonitorInfo failed"
hWnd = 0
Else
hdc = CreateDC(tMonitorInfo.szDevice, 0, 0, 0)
If hdc = 0 Then
Debug.Print "CreateDC failed"
hWnd = 0
End If
End If
End If
End If
If hWnd = 0 Then
If ActiveWindowID <> 0 Then
hdc = GetDC(ActiveWindowID)
Else
hdc = GetDC(hWnd)
End If
tMonitorInfo.dwFlags = MONITOR_PRIMARY
tMonitorInfo.szDevice = "PRIMARY" & vbNullChar
End If
sItem = Trim(LCase(Item))
Select Case sItem
Case "horizontalresolution", "pixelsx"
vResult = GetDeviceCaps(hdc, DevCap.HORZRES)
Case "verticalresolution", "pixelsy"
vResult = GetDeviceCaps(hdc, DevCap.VERTRES)
Case "widthinches", "inchesx"
vResult = GetDeviceCaps(hdc, DevCap.HORZSIZE) / 25.4
Case "heightinches", "inchesy"
vResult = GetDeviceCaps(hdc, DevCap.VERTSIZE) / 25.4
Case "diagonalinches", "inchesdiag"
vResult = Sqr(GetDeviceCaps(hdc, DevCap.HORZSIZE) ^ 2 + GetDeviceCaps(hdc, DevCap.VERTSIZE) ^ 2) / 25.4
Case "pixelsperinchx", "ppix"
vResult = 25.4 * GetDeviceCaps(hdc, DevCap.HORZRES) / GetDeviceCaps(hdc, DevCap.HORZSIZE)
Case "pixelsperinchy", "ppiy"
vResult = 25.4 * GetDeviceCaps(hdc, DevCap.VERTRES) / GetDeviceCaps(hdc, DevCap.VERTSIZE)
Case "pixelsperinch", "ppidiag"
xHSizeSq = GetDeviceCaps(hdc, DevCap.HORZSIZE) ^ 2
xVSizeSq = GetDeviceCaps(hdc, DevCap.VERTSIZE) ^ 2
xPix = GetDeviceCaps(hdc, DevCap.HORZRES) ^ 2 + GetDeviceCaps(hdc, DevCap.VERTRES) ^ 2
vResult = 25.4 * Sqr(xPix / (xHSizeSq + xVSizeSq))
Case "windotsperinchx", "dpix"
vResult = GetDeviceCaps(hdc, DevCap.LOGPIXELSX)
Case "windotsperinchy", "dpiy"
vResult = GetDeviceCaps(hdc, DevCap.LOGPIXELSY)
Case "windotsperinch", "dpiwin"
xHSizeSq = GetDeviceCaps(hdc, DevCap.HORZSIZE) ^ 2
xVSizeSq = GetDeviceCaps(hdc, DevCap.VERTSIZE) ^ 2
xDot = GetDeviceCaps(hdc, DevCap.LOGPIXELSX) ^ 2 * xHSizeSq + GetDeviceCaps(hdc, DevCap.LOGPIXELSY) ^ 2 * xVSizeSq
vResult = Sqr(xDot / (xHSizeSq + xVSizeSq))
Case "adjustmentfactor", "zoomfac"
xHSizeSq = GetDeviceCaps(hdc, DevCap.HORZSIZE) ^ 2
xVSizeSq = GetDeviceCaps(hdc, DevCap.VERTSIZE) ^ 2
xPix = GetDeviceCaps(hdc, DevCap.HORZRES) ^ 2 + GetDeviceCaps(hdc, DevCap.VERTRES) ^ 2
xDot = GetDeviceCaps(hdc, DevCap.LOGPIXELSX) ^ 2 * xHSizeSq + GetDeviceCaps(hdc, DevCap.LOGPIXELSY) ^ 2 * xVSizeSq
vResult = 25.4 * Sqr(xPix / xDot)
Case "isprimary"
vResult = CBool(tMonitorInfo.dwFlags And MONITOR_PRIMARY)
Case "displayname"
vResult = tMonitorInfo.szDevice & vbNullChar
vResult = Left(vResult, (InStr(1, vResult, vbNullChar) - 1))
Case "displayleft"
vResult = tMonitorInfo.rcMonitor.Left
Case "displaytop"
vResult = tMonitorInfo.rcMonitor.Top
Case "update"
vResult = Now
Case "help"
vResult = "HorizontalResolution (pixelsX), VerticalResolution (pixelsY), " _
& "WidthInches (inchesX), HeightInches (inchesY), DiagonalInches (inchesDiag), " _
& "PixelsPerInchX (ppiX), PixelsPerInchY (ppiY), PixelsPerInch (ppiDiag), " _
& "WinDotsPerInchX (dpiX), WinDotsPerInchY (dpiY), WinDotsPerInch (dpiWin), " _
& "AdjustmentFactor (zoomFac), IsPrimary, DisplayName, Update, Help"
Case Else
vResult = CVErr(xlErrValue)
End Select
If hWnd = 0 Then
ReleaseDC hWnd, hdc
Else
DeleteDC hdc
End If
ScreenParameter = vResult
End Function