The console command SETRES is used to change graphics resolution. However, currently there is no ability to list all the available graphics resolutions on a client's machine.
: there is a simpler alternative now available for later builds of UDK, including 2012-05 onwards, located here
. This tutorial is still a useful template for implementing your own DLLs.
In this tutorial I will walk you through creating a Dynamic Link Library utility in C++, and a class in UnrealScript, that together will build a list of available graphics modes on the client PC – a useful feature for populating your UI options with a choice of screen resolutions.
This is a moderately advanced topic, but you won't need any prior C++ experience. I've purposely kept the code simple and readable, with most of the functionality and flexibility in UnrealScript. The C++ part is mostly copy-paste.
Summary of the steps involved
- Setup a DLL project in Microsfot Visual C++ 2010 Express
- Create and compile a C++ wrapper for the Windows function EnumerateDisplayModes
- Create an UnrealScript class to call the DLL and construct a list of available resolutions
Step 1 The DLL Project
You can use any C++ IDE/compiler, but for this tutorial I'll be using Microsoft Visual C++ 2010 Express.
- Select File -> New -> Project... to open the project template screen
- Select Win32 from the list of options on the left, then Win32 Console Application from the centre
- At the bottom of the template window enter DeviceInfo as the name for the project, and tick Create directory for solution (this is optional, but will keep you in sync with the tutorial)
Click OK and the application wizard will appear
- Click Next > to get to the options page
- For the Application Type choose DLL
- Under Additional Options select Empty Project
Click Finish and a new Solution with the DeviceInfo project will be created for you.
- From the main menu select Project -> Add New Item... to open the item template window. Be sure to choose from the Project menu as there are several 'add' options in the IDE
- Select Code from the options on the left, and C++ File (.cpp) from the centre
- Enter the name DeviceInfo.cpp for the filename
- Click Add to finish
You should now have an empty c++ source file. However, before we begin there is an important setting we must make to the compiler when working with the UDK.
- In the Solution Explorer window right-click on the DeviceInfo project and choose Properties. Note: the project is beneath the Solution in the tree. If the next step doesn't make sense you probably opened the solution properties instead of the project
- In the properties window locate the code generation settings: Configuration Properties -> C/C++ -> Code Generation
- On the right-hand side select the drop-down box next to Struct Member Alignment and choose "4 byte (/Zp4)"
This setting ensures that any struct we define in C++ that's intended to mirror one in UnrealScript will have the same byte padding and layout.
Step 2 C++
Copy and paste the following code into DeviceInfo.cpp
Now from the Build menu choose Build Solution, or press F7. Visual Studio will auto-save the open cpp file and begin compiling. If everything is tickety-boo it should compile successfully, and a debug version of the DLL file will be created in the Debug folder of the DeviceInfo project. If you're using Win7 this will likely be:
/* Include the windows header file, which resolves references to DEVMODE and EnumDisplaySettings */
/* Ensure compatibility between C and C++ code
/* UDK_Resolution, a mirror of our UnrealScript struct Resolution.
Both must have identical structure, and the C++ compiler should be set to pack on 4-byte boundaries (/Zp4)
int PixelWidth, PixelHeight;
A wrapper for the Windows function EnumDisplaySettings.
UDK_Resolution * const udk_r
This is a pointer to the local variable 'r' defined in our UnrealScript function, which allows us to
modify it directly from the DLL. The names do not need to match with UnrealScript, and the prefix
'udk_' is only to help define its role. The pointer is made const to add some safety. Pointers are
powerful and brutal. Learn C/C++ before tinkering with them.
__declspec(dllexport) int DLLEnumDisplaySettings( int modeNum, UDK_Resolution * const udk_r )
dm.dmSize = sizeof(DEVMODE);
/* Each call to EnumDisplaySettings populates 'dm' with the width, height, bit-depth and refresh rate
for the device mode specified by modeNum. However, we're only concerned with resolution so we keep
width and height, and discard the rest.
The NULL value in the first parameter will query the current display adaptor which should be fine
for our purposes.
if ( EnumDisplaySettings(NULL, modeNum, &dm) )
// copy the width and height properties of DEVMODE to UnrealScript's Resolution
udk_r->PixelWidth = dm.dmPelsWidth;
udk_r->PixelHeight = dm.dmPelsHeight;
// EnumDisplaySettings returned false, meaning the specified modeNum does not exist
C:\Users\USERNAME\Documents\Visual Studio 2010\Projects\DeviceInfo\Debug\DeviceInfo.dll
Copy DeviceInfo.dll and paste it into your UDK-version/Binaries/Win32/UserCode directory. On my workstation this is:
DLLs only work with the 32-bit build of UDK. If you are working on a 64-bit platform you may be used to running the 64-bit version. Be sure to compile and run your UDK project against the Win32 binaries.
Step 3 UnrealScript and testing
Create a new class file for your UDK project with the name DeviceInfo.uc. Copy and paste the following code, and save the file.
To use the class you need to instantiate an instance of it and call EnumDeviceModes. Ideally this would be done as part of the initialisation and setup for your game since you only need to call it once if you keep the instance. Alternatively you could implement this into an existing user interface manager class or whatever you prefer.
class DLLDeviceInfo extends Object
/* Resolution, holds the width and height of a display resolution.
var int PixelWidth, PixelHeight;
/* An array of Resolutions, listing all the unique display resolutions found
var array<Resolution> AllResolutions;
/* DLL import declaration, matching the call signature of the function defined in our DLL
dllimport final function int DLLEnumDisplaySettings( int modeNum, out Resolution r );
/* EnumDeviceModes, builds a list of graphics resolutions supported by the hardware.
Each call to DLLEnumDisplaySettings may return a new resolution, or a duplicate resolution with
different bit-depth and refresh rate. For SETRES and our UI options we only require a list of the
unique resolutions, so we'll filter out all the duplicates.
local Resolution r;
local int modeNum;
local int key;
local array<int> keys;
`log("Enumerating device modes...");
// Start with mode 0
modeNum = 0;
// Query device mode 0, 1, 2, ... etc. DLLEnumDisplaySettings returns 0 when all modes have been reported
while( DLLEnumDisplaySettings(modeNum, r) != 0 )
// combine width and height into a single integer 'key'
key = r.PixelWidth << 16 | r.PixelHeight;
/* This simple trick filters out duplicate resolutions by creating a unique key for each combination of
width and height. If our key list doesn't yet contain an entry for this combo then we have a new
resolution to add to our list of AllResolutions.
Reduces hundreds of reported modes down to a handful of useable options. Which is nice.
// Already added this combination of width and height?
if ( keys.Find(key) == INDEX_NONE )
// Add the new resolution
// Add the key
// next device mode
// Report some useful info...
`log(AllResolutions.Length @ "available resolutions from" @ modeNum @ "device modes");
`log("The following resolutions are supported:");
`log(" " $ r.PixelWidth @ "x" @ r.PixelHeight);
For testing we'll add it to the InitGame event in GameInfo.
Now compile and run your UDK project.
var DLLDeviceInfo DeviceInfo;
event InitGame( string options, out string errorMessage )
DeviceInfo = new class'DLLDeviceInfo';
The results will show up in the console and logfile. This example is from my workstation running an Nvidia GTX560Ti:
[0002.60] ScriptLog: Enumerating device modes...
[0002.62] ScriptLog: 16 available resolutions from 225 device modes.
[0002.62] ScriptLog: The following resolutions are supported:
[0002.62] ScriptLog: 640 x 480
[0002.62] ScriptLog: 720 x 480
[0002.62] ScriptLog: 720 x 576
[0002.62] ScriptLog: 800 x 600
[0002.62] ScriptLog: 1024 x 768
[0002.62] ScriptLog: 1152 x 864
[0002.62] ScriptLog: 1280 x 720
[0002.62] ScriptLog: 1280 x 768
[0002.62] ScriptLog: 1280 x 800
[0002.62] ScriptLog: 1280 x 960
[0002.62] ScriptLog: 1280 x 1024
[0002.62] ScriptLog: 1360 x 768
[0002.62] ScriptLog: 1366 x 768
[0002.62] ScriptLog: 1600 x 900
[0002.62] ScriptLog: 1600 x 1024
[0002.62] ScriptLog: 1680 x 1050
You can replace the debug version of the DLL with a release version at some point. Simply select Release from the solution configurations toolbar and rebuild. You'll find it in the release directory.
Further reading and reference