When developing Windows software that is to be distributed to a wide variety of personal computers, it's often useful to have some kind of routine that will allow us to get not only the current display settings but to get and set all possible device modes of the display device.
In this article we'll see how to actually use Windows API function EnumDisplaySettings to get a list of valid mode settings, and the ChangeDisplaySettings function to change the display setting.
Retrieve Possible Display ModesYou can obtain information for all of the display device's graphics modes by making a series of calls to EnumDisplaySettings function. EnumDisplaySettings finds the number of possible modes by enumerating them until the function result is no longer True.
This function requires a TDevMode type variable in which to place the settings. The TDevMode type has a number of variables that refer to display devices (among others). These include the display device resolution in pixels (dmPelsWidth, dmPelsHeight), the color depth (in bits per pixel) supported at the resolution (dmBitsPerPel), refresh rate (dmDisplayFrequency) and others.
procedure TForm1.FormCreate(Sender: TObject) ; var cnt : Integer; DevMode : TDevMode; begin cnt := 0; while EnumDisplaySettings(nil,cnt,DevMode) do begin with Devmode do ListBox1.Items.Add(Format('%dx%d %d Colors', [dmPelsWidth,dmPelsHeight,Int64(1) shl dmBitsperPel])) ; Inc(cnt) ; end; end;
Set Screen Resolution and ColorsOnce we have all the possible display modes, setting the desired-appropriate display mode is very simple. The ChangeDisplaySettings function is then used to change the current display mode and update the Windows Registry as necessary.
The ChangeDisplaySettings function returns a long integer value. This value can be compared to a list of constants to determine whether the function was successful or not.
procedure TForm1.Button1Click(Sender: TObject) ; var DevMode : TDeviceMode; liRetValue : Longint; begin if EnumDisplaySettings (nil, Listbox1.ItemIndex, Devmode) then liRetValue := ChangeDisplaySettings(DevMode, CDS_UPDATEREGISTRY) ; SendMessage(HWND_BROADCAST, WM_DISPLAYCHANGE, SPI_SETNONCLIENTMETRICS,0) ; end;
- It is not recommended that we set the display modes individually, rather than choosing from the Enumerated list. This will prevent us from bringing a blank screen in front of the user. For example: setting the dmBitsPerPel variable to a color depth unsupported by the resolution could blank the screen.
- Many drivers (especially older ones) will not perform the change without rebooting the computer, even though they are capable of doing so.
- SendMessage is used to inform all windows that the screen resolution was changed.
Detecting Changes in DisplayTo detect changes in the display, we'll create a message handler to trap the WM_DISPLAYCHANGE message. If your application makes use of graphics, you may want to restart the application, as there may be many changes to the system that may be difficult to overcome as the screen resolution, color depth and default fonts may change.
type TForm1 = class(TForm) ListBox1: TListBox; ... private procedure WMDisplayChange(var Message:TMessage) ; message WM_DISPLAYCHANGE; ... procedure TForm1.WMDisplayChange(var Message: TMessage) ; begin ShowMessage('Changes in display detected!') ; inherited; end;