It can often be useful to be able to retrieve or change the screen resolution direct
from your VB application. For example, if you have written a game in VB, you may wish to
set the screen resolution to 600×480. Desktop Publishing software would also benefit from
being able to offer the user a one-click function to change the screen size.
You could even design a dynamic application that resizes all the controls on the form
based on the current screen resolution.
This article will take you through some of the more important display setting functions
that will prove valuable to the Visual Basic programmer.
Normally manipulating and displaying information on the display settings this would be
done with the aid of the Display Properties applet in the control panel, but this article
will teach you how to do the same programmatically using the Windows API.
Click here for a larger image.
The Display Settings Control Panel
For example if you design a program that uses 800 pixels by 600 pixels and the user of
the machine running your application has their screen size set to 640 pixels by 480
pixels, 1024 pixels by 768 pixels or higher then your application may not be displayed
correctly.
If you determine the screen resolution then you can warn the user that their display
settings may effect the functionality of your application. You could, if you the user
wanted, use the method later in this article that will let you dynamically change the
resolution for the user and then on exit of you application set the resolution back to the
previous state.
The API function that returns system metrics, including the screen resolution, is the
GetSystemMetrics API function. It contains only one parameter.
nIndex – This parameter specifies the metric or configuration setting that
you want to retrieve. Although there are over 150 constants that you can use for this
parameter, in this article I will explain how to use just two of them to retrieve the
vertical and horizontal reoulution of the screen. (For a full list of constants, check out
this tip)
Constant | Description |
SM_CXSCREEN | You may have noticed that the constant with CX in it is for the x axis or horizontal axis if you prefer to call it that. The simply returns the width of the screen, which for most users is 800 pixels by 600 pixels. |
SM_CYSCREEN | This is simply the opposite of SM_CXSCREEN, and is the height of the screen or the y-axis of the screen in algebraic form. |
To use this API function simply call it by:
<Variable> = GetSystemMetrics(<Constant>)
The API function will then return the value depending on the constant you have used.
To return the screen resolution you can construct a simple function from the
information above:
Public Function GetScreenResolution() As String GetScreenResolution = GetSystemMetrics(SM_CXSCREEN) & _ " pixels by " & GetSystemMetrics(SM_CYSCREEN) & " pixels" End Function
Now you can change this function to what ever you like. One possible change that you
may make would to be to check that the user has the 800 pixels by 600 pixels screen
resolution set. You could do this by returning true to the function if the user has a 800
pixels by 600 pixels screen resolution and vice versa. Below is an example of this
' Check whether screen resolution is set to 800x600 ' Returns True if the resolution is at 800x600 else ' False is returned Public Function GetScreenResolution() As Boolean Dim lTemp As String ' Temporary string to hold returned screen ' resolution lTemp = GetSystemMetrics(SM_CXSCREEN) & _ "x" & GetSystemMetrics(SM_CYSCREEN) ' Call the API function twice to return ' screen size for each axis as format into ' the temporary string If lTemp = "800x600" Then ' Check whether resolution is set to 800x600 GetScreenResolution = True ' True Else GetScreenResolution = False ' False End If End Function
You should now be able to implement this into your application for your own needs.
The functions here are demonstrated in the GetScreenRes
demo project.
Now that you have know how to retrieve the screen resolution you may want to know how
you can retrieve the number of colours that is available to Windows. The options are: 16
colours, 4 bit; 256 colours,8 bit; 65536 colours, 16 bit; 16.7 million colours, either 24
bit or 32 bit.
GetDeviceCaps
This API function is important in retrieving the number of colours that is available to
windows. It returns the information on a given index. The paramters are:
Hdc – This is the handle of the device context that you find by using
CreateIC.
nIndex – This is the information that you want to retrieve from the display
driver. The constants that are important in this section of the article are
Constant | Description |
BITSPIXEL | This is the number of bits that are available per pixel. This will return 4, 8, 16, 24 or 32. |
PLANES | This returns the number of colour planes |
CreateIC
This API function is used to create a device context, which allows easy access to
device information. This CreateIC API function has these parameters:
LpDriverName – This specifies the name of the driver that you want to
retrieve information on. This is usually ‘Display’ for information on the
display driver.
LpDeviceName – This should be left as null
LpOutput – This should be left as null
LpInitData – This should be left as null
DeleteDC
This simply deletes the device context that was created by using CreateIC. You must do
this for every device context that you create in order to free up Windows resources.
To retrieve the number of colours that are available to Windows we first need to find
out how many planes are available to windows, which will be either 1 or 4. Most machines
will support 1 plane.
This function returns the number of colours and colour depth as a string:
Private Const BITSPIXEL = 12 Private Const PLANES = 14 Private Declare Function CreateIC Lib "gdi32" _ Alias "CreateICA" (ByVal lpDriverName As String, _ ByVal lpDeviceName As Any, ByVal lpOutput As Any, _ ByVal lpInitData As Any) As Long Private Declare Function GetDeviceCaps Lib "gdi32" _ (ByVal hdc As Long, ByVal nIndex As Long) As Long Private Declare Function DeleteDC Lib "gdi32" _ (ByVal hdc As Long) As Long Public Function GetAvailableColours() As String Dim lHdc As Long, lPlanes As Long, lBitsPerPixel As Integer ' Declare variables lHdc = CreateIC("DISPLAY", 0&, 0&, 0&) ' Create the device context for the display If lHdc = 0 Then ' An error has occurred and the function will exit GetAvailableColours = "Error" Exit Function End If lPlanes = GetDeviceCaps(lHdc, PLANES) ' Return info on number of planes lBitsPerPixel = GetDeviceCaps(lHdc, BITSPIXEL) ' Use display device ' context to return info on the ' number of pixels lHdc = DeleteDC(lHdc) ' Delete the device context Select Case lPlanes Case 1 ' 1 plane is available. This ' will be the same for most ' computer systems Select Case lBitsPerPixel ' Select the number of colours available Case 4: GetAvailableColours = _ "4 Bit, 16 Colours" Case 8: GetAvailableColours = _ "8 Bit, 256 Colours" Case 16: GetAvailableColours = _ "16 Bit, 65536 Colours" Case 24: GetAvailableColours = _ "24 Bit True Colour, 16.7 Million Colours" Case 32: GetAvailableColours = _ "32 Bit True Colour, 16.7 Million Colours" End Select Case 4 GetAvailableColours = "16 Bit, 65536 Colours" ' If there are 4 planes then the availible ' colours will be 16-bit Case Else GetAvailableColours = "Undetermined" ' The number of colours could not bee determined End Select End Function
The functions here are demonstrated in
the GetColourDepth demo project.
Now that you can retrieve both the current screen resolutions and number of colours
that are selected in Windows, you will want to know how you can enumerate the resolutions
and colour modes that a machine supports. This can be very useful especially with changing
the screen resolution programmatically, as you must know whether the computer supports it.
EnumDisplaySettings
This API function retrieves information about the display driver’s graphics modes.
There are three parameters:
LpszDeviceName – Leave this as null (0&)
IModeNum = This is the index of the display mode that you want to retrieve
information about, starting with 0. You call this in a sequence, and it will continue
returning modes until 0 is returned by the API function.
PDevMode – This parameter points to a DevMode type structure in which to
retrieve information about the graphics modes that are available.
The following properties of the DevMode structure will be retrieved:
- dmBitsPerPel – This is the
bits per pixel or colour depth that is available in the selected graphics mode - dmPelsWidth – This is the
width of the screen or the x axis. - dmPelsHeight – This is the
height of the screen or the y axis.
Now to create a function to do this.
Private Declare Function EnumDisplaySettings Lib _ "user32" Alias "EnumDisplaySettingsA" _ (ByVal lpszDeviceName As Long, ByVal iModeNum As Long, _ lpDevMode As Any) As Boolean 'Screen Resolution Private Const CCDEVICENAME = 32 Private Const CCFORMNAME = 32 Private Type DEVMODE dmDeviceName As String * CCDEVICENAME dmSpecVersion As Integer dmDriverVersion As Integer dmSize As Integer dmDriverExtra As Integer dmFields As Long dmOrientation As Integer dmPaperSize As Integer dmPaperLength As Integer dmPaperWidth As Integer dmScale As Integer dmCopies As Integer dmDefaultSource As Integer dmPrintQuality As Integer dmColor As Integer dmDuplex As Integer dmYResolution As Integer dmTTOption As Integer dmCollate As Integer dmFormName As String * CCFORMNAME dmUnusedPadding As Integer dmBitsPerPel As Integer dmPelsWidth As Long dmPelsHeight As Long dmDisplayFlags As Long dmDisplayFrequency As Long End Type Public Sub EnumDisplay() Dim lTemp As Long, tDevMode As DEVMODE, lIndex As Long ' Declare variables lIndex = 0 Do lTemp = EnumDisplaySettings(0&, lIndex, tDevMode) ' Call the API function with the current index If lTemp = 0 Then Exit Do ' If the API function returns 0 then no more ' data is availible or an error has occurred. ' As you increase the index on each call ' when there is no more data to enumerate the ' function will return 0 With tDevMode Debug.Print .dmPelsWidth & " pixels by " _ & .dmPelsHeight & " pixels, Color Mode " _ & .dmBitsPerPel & " bit" ' Print the mode information to the debug End With lIndex = lIndex + 1 Loop End Sub
This function will enumerate all the display modes and display them in the debug
window.
The functions here are demonstrated in the EnumDisplayModes
demo project.
First, I must emphasise that some of the constants required to do this are undocumented
in the VB API viewer, but are listed below and in the sample projects.
To change the screen mode, you must enumerate the possible screen modes, as described
earlier, then select the closest match. You then can use the ChangeDisplaySettings API
function to actually change the screen resolution:
ChangeDisplaySettings
This API function changes the display settings on the current machine. There are two
parameters that are passed which are:
lpDevMode – This acts as a pointer to the DevMode structure that contains
information that you want to change. You can set the following parameters of the DevMode
structure that will be changed
Meaning | Description |
dmBitsPerPel | This is the number of colours that you want to use or the bits per pixel as I explained earlier on in this article, which can either be 4, 6, 8, 16, 24 or 32 depending on the modes supported. |
dmPelsWidth | This is the width of the screen in pixels or otherwise known as the x-axis of the screen. |
dmPelsHeight | This is the height of the screen in pixels or otherwise known as the y-axis of the screen. |
This function demonstrates how to change the screen resolution. It enumerates through
the available modes, checking each one. When the correct one is found, it is selected.
Don’t forget to add the earlier declarations to the ones here:
Private Declare Function ChangeDisplaySettings _ Lib "user32" _ Alias "ChangeDisplaySettingsA" (lpDevMode As Any, _ ByVal dwflags As Long) As Long Public Sub ChangeScreenSettings(lWidth As Integer, _ lHeight As Integer, lColors As Integer) Dim tDevMode As DEVMODE, lTemp As Long, lIndex As Long ' Declare variables lIndex = 0 Do lTemp = EnumDisplaySettings(0&, lIndex, tDevMode) ' Call the API function If lTemp = 0 Then Exit Do ' If there is no more data or an error occurs ' then return 0 and exit do lIndex = lIndex + 1 ' Increase the index to be enumerated With tDevMode If .dmPelsWidth = lWidth And .dmPelsHeight = lHeight _ And .dmBitsPerPel = lColors Then lTemp = ChangeDisplaySettings(tDevMode, CDS_UPDATEREGISTRY) Exit Do End If End With Loop ' Set the new data ' Change the display type. This depends on the paramter used ' It can either be: ' 0 - Dynamic change if possible ' CDS_UPDATEREGISTRY - Dynamically change if possible ' and if not possible then update registry for change ' on the next boot-up ' CDS_TEST - Test the new settings Select Case lTemp ' Check for errors Case DISP_CHANGE_SUCCESSFUL MsgBox "The display settings change was successful", _ vbInformation Case DISP_CHANGE_RESTART MsgBox "The computer must be restarted in order for _ the graphics mode to work", vbQuestion Case DISP_CHANGE_FAILED MsgBox "The display driver failed the specified graphics _ mode", vbCritical Case DISP_CHANGE_BADMODE MsgBox "The graphics mode is not supported", vbCritical Case DISP_CHANGE_NOTUPDATED MsgBox "Unable to write settings to the registry", vbCritical ' NB. Windows NT Only Case DISP_CHANGE_BADFLAGS MsgBox "An invalid set of flags was passed in", vbCritical End Select End Sub
The functions here are demonstrated in the ChangeDispMode
demo project.
Whether you are creating a Visual Basic game, DTP program or a drawing application,
harnessing the power of the graphics system is always useful. If you have any
questions about this article, please post a message in our Q
and A forum or drop me an email.