Retrieving Display Settings

When I used to develop Excel mini-applications for use by others in my department, I often needed to know the user’s display settings at runtime so that I could adjust my UI accordingly. I learned to do that the hard way, when users started complaining about my dialogs being too big for their screens or too small for them to work with.

The GetDeviceCaps API function can supply all kinds of metrics about any output device, although I’ve only used it for display settings. The functions I use are provided below:

Option Explicit

Declare Function GetDeviceCaps Lib “Gdi32” _
 (ByVal hdc As Long, ByVal nIndex As Long) As Long
Declare Function GetDC Lib “User32” _
 (ByVal hWnd As Long) As Long
Declare Function ReleaseDC Lib “User32” _
 (ByVal hWnd As Long, ByVal hdc As Long) As Long
 
Function HRes() As Integer
    ‘Returns the horizontal resolution in pixels
   Dim lDC As Long
    lDC = GetDC(0)
    HRes = GetDeviceCaps(lDC, 8)
    ReleaseDC 0, lDC
End Function

Function VRes() As Integer
    ‘Returns the vertical resolution in pixels
   Dim lDC As Long
    lDC = GetDC(0)
    VRes = GetDeviceCaps(lDC, 10)
    ReleaseDC 0, lDC
End Function

Function ColorDepth() As Integer
    ‘Returns the color depth in bits per pixel
   Dim lDC As Long
    lDC = GetDC(0)
    ColorDepth = GetDeviceCaps(lDC, 12) _
     * GetDeviceCaps(lDC, 14)
    ReleaseDC 0, lDC
End Function

Function Colors() As Single
    ‘Returns the number of available colors
   Dim lDC As Long
    lDC = GetDC(0)
    Colors = 2 ^ (GetDeviceCaps(lDC, 12) _
     * GetDeviceCaps(lDC, 14))
    ReleaseDC 0, lDC
End Function

Function VRefresh() As Integer
    ‘Returns the vertical refresh rate in Hz
   Dim lDC As Long
    lDC = GetDC(0)
    VRefresh = GetDeviceCaps(lDC, 116)
    ReleaseDC 0, lDC
End Function

The basic approach is to get the handle of the Device Context (in this case the screen) using GetDC(0), and then passing the handle to the GetDeviceCaps function with the appropriate parameter to retrieve the desired metric. There seem to be differing opinions on whether or not ReleaseDC is needed in this case, but I’ve included it for neatness (and because Bob Phillips insists that it’s necessary).

Of course, all of these functions can be wrapped up in a single sub, but I prefer to use functions so that I can use their return values directly in other procedures.

Since I hadn’t used these functions in a few years, I had to update the return type for the Colors function from a Long to a Single, since many displays now support 32 bits per pixel, or 4.3 billion colors. The old 24-bit standard was a paltry 16.7 million colors.

Needless to say, nothing in these functions is original material. It’s pretty basic API stuff, hopefully useful to users who may be thinking about getting their feet wet with APIs.

Is this number prime?

In one of my (many) previous lives, I wanted to be a mathematician.

Even after I realized that being a mathematician would preclude a lifestyle that I wanted to become accustomed to, I still retained an active interest in mathematics. One of the areas that I found fascinating involved prime numbers.

I’ve seen many UDFs in the newsgroups, mostly provided by Excel MVPs, to determine if a number is prime. However, the following is the shortest UDF that I’ve been able to come up with:

Function IsPrime(Num As Single) As Boolean
    Dim i As Long
    If Num < 2 Or (Num <> 2 And Num Mod 2 = 0) _
     Or Num <> Int(Num) Then Exit Function
    For i = 3 To Sqr(Num) Step 2
        If Num Mod i = 0 Then Exit Function
    Next
    IsPrime = True
End Function

The reason for declaring the input number Num as a Single is that if it’s declared as an Integer or a Long, an input value of, say, 3.2 will be coerced to 3 and be evaluated as a prime number. Clearly, this is not the desired result. There is probably a better way of handling this, but I can’t figure it out.

I’d be interested in some comments as to whether this code can be shortened or made more elegant.