Click here to Skip to main content
15,896,111 members
Articles / Programming Languages / C#
Article

Dynamic Screen Resolution

Rate me:
Please Sign up or sign in to vote.
4.45/5 (57 votes)
22 Jul 2008CPOL3 min read 517.6K   17.3K   101   87
Setting the Screen Resolution in C#

Introduction

I had a hard time in setting a dynamic screen resolution when I was doing some thick client application for a test suite. I presume that most of us have had this happen to us, or have faced such times somewhere along our engineering life cycle. Because, as we all know, the resolution of the user screen may not be same as that of the development environment screen.

This article expects to deliver what I found as a solution for the discussed challenge.

The forthcoming part of this literature will communicate about:

  • How to get the end user screen resolution
  • How to change the user screen resolution to product compatible
  • How to safeguard the user screen resolution

How to Get the End User Screen Resolution

Accessing the user screen is being eased by the availing Screen class which is shipped along with the .NET framework. And can access the current user screen resolution through a static Screen.PrimaryScreen property available in the Screen class.

C#
public static Screen PrimaryScreen {get;}

The aforementioned property is read only and returns a Screen type. And the below given logic demonstrates how to make use of the Screen type to access the user screen resolution.

C#
Screen screen = Screen.PrimaryScreen;
int S_width=screen.Bounds.Width;
int S_height=screen.Bounds.Height;

How to Change the User Screen Resolution to Product Compatible

Before heading towards our next goal, let me talk about the unmanaged part of this implementation. Unlike traditional languages, the .NET framework holds a distinct step while leveraging both managed and unmanaged code. Personally, when I wrote this article, I never found any managed code which does this resolution treatment. And this is what made me think to explore some Win32 API’s.

Before continuing, I would request you to have hands on or theoretical knowledge about: COM Interop service, Attribute, DLL import attribute and Platform Invoke.

Since the scope of this article is limited to managed code, I will not be discussing anything about unmanaged code. But, despite that fact, we can use the DllImport attribute to read the definition of unmanaged code to your managed environment. In this case, we will be using the User32.dll API, which facilitates the dynamic resolution and has two functions related to changing the screen resolution.

  • EnumDisplaySettings
  • ChangeDisplaySettings
C#
class User32
{
        [DllImport("user32.dll")]
        public static extern int EnumDisplaySettings (
          string deviceName, int modeNum, ref DEVMODE devMode );         
        [DllImport("user32.dll")]
        public static extern int ChangeDisplaySettings(
              ref DEVMODE devMode, int flags); 
 
        public const int ENUM_CURRENT_SETTINGS = -1;
        public const int CDS_UPDATEREGISTRY = 0x01;
        public const int CDS_TEST = 0x02;
        public const int DISP_CHANGE_SUCCESSFUL = 0;
        public const int DISP_CHANGE_RESTART = 1;
        public const int DISP_CHANGE_FAILED = -1;
}

As we know, the [DllImport("user32.dll")] is an explicit groundwork before injecting an unmanaged implementation in our managed environment.

C#
public static extern int EnumDisplaySettings 
    (string deviceName, int modeNum, ref DEVMODE devMode);

DEVMODE is a structure that is explained in the platform documentation as well as included with Visual Studio .NET. The structure is defined in C#.

C#
[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE 
{
        [MarshalAs(UnmanagedType.ByValTStr,SizeConst=32)] 
          public string dmDeviceName;
        public short  dmSpecVersion;
        public short  dmDriverVersion;
        ... 
}

You can have a look at the source code attached and apply this logic to any event that you want.

Be aware that, the types have the right size and that fixed length strings are appropriately defined. In this case WORD maps to short, DWORD to int and short stays as short.

C#
DEVMODE dm = new DEVMODE();
dm.dmDeviceName = new String (new char[32]);
dm.dmFormName = new String (new char[32]);
dm.dmSize = (short)Marshal.SizeOf (dm); 
 
if (0 != User32.EnumDisplaySettings (null, 
       User32.ENUM_CURRENT_SETTINGS, ref dm))
{

At this point the DEVMODE structure will be decorated with the default settings and can modify it at any instance.

C#
dm.dmPelsWidth = iWidth;
dm.dmPelsHeight = iHeight; 
 
int iRet = User32.ChangeDisplaySettings (
  ref dm, User32.CDS_UPDATEREGISTRY);

The enclosed code block does this a little differently to deal with various error conditions. I would encourage you to look at the full source file and see what it does. That's all there is to it.

How to Safeguard the User Screen Resolution

Finally, before we continue, it’s our responsibly to safeguard a user's default screen resolution. In order to do that, you might have to use some static members or classes to hold the user screen resolution and retain it back when you complete the execution.

See the downloads at the top of this article for the source code.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Freelance
India India
He is a certified professional in both MCPD and MCTS. He is a mathematics graduate with masters in computer science.He was born and bred in India and happen to spend some time in Europe.

Comments and Discussions

 
GeneralRe: get available screen resolutions Pin
IgorAfonin25-Jul-12 4:22
IgorAfonin25-Jul-12 4:22 
GeneralRe: get available screen resolutions Pin
izne31-Mar-08 16:45
izne31-Mar-08 16:45 
QuestionCDS_TEST is 0x2 and CDS_UPDATEREGISTRY = 0x1??? Pin
Doug.Chen17-Aug-07 21:08
Doug.Chen17-Aug-07 21:08 
GeneralError Message Pin
megaroo7926-Jun-07 14:47
megaroo7926-Jun-07 14:47 
GeneralRe: Error Message Pin
shradds18-Mar-09 4:29
shradds18-Mar-09 4:29 
GeneralRe: Error Message Pin
Epon14-Jul-10 19:57
Epon14-Jul-10 19:57 
GeneralRe: Error Message Pin
Member 1010100917-Aug-13 21:45
Member 1010100917-Aug-13 21:45 
Generalvb.net version Pin
nandhucbm5-Jun-07 2:55
nandhucbm5-Jun-07 2:55 
'Class file:

Imports System.Runtime.InteropServices

Namespace Win32Functions

' Encapsulate the magic numbers for the return value in an enumeration
Public Enum ReturnCodes As Integer
DISP_CHANGE_SUCCESSFUL = 0
DISP_CHANGE_BADDUALVIEW = -6
DISP_CHANGE_BADFLAGS = -4
DISP_CHANGE_BADMODE = -2
DISP_CHANGE_BADPARAM = -5
DISP_CHANGE_FAILED = -1
DISP_CHANGE_NOTUPDATED = -3
DISP_CHANGE_RESTART = 1
End Enum

<structlayout(layoutkind.sequential, charset:="CharSet.Ansi)"> _
Public Structure DevMode
' The MarshallAs attribute is covered in the Background section of the article
<marshalas(unmanagedtype.byvaltstr, sizeconst:="32)"> _
Public dmDeviceName As String

Public dmSpecVersion As Short
Public dmDriverVersion As Short
Public dmSize As Short
Public dmDriverExtra As Short
Public dmFields As Integer
Public dmPositionX As Integer
Public dmPositionY As Integer
Public dmDisplayOrientation As Integer
Public dmDisplayFixedOutput As Integer
Public dmColor As Short
Public dmDuplex As Short
Public dmYResolution As Short
Public dmTTOption As Short
Public dmCollate As Short

<marshalas(unmanagedtype.byvaltstr, sizeconst:="32)"> _
Public dmFormName As String

Public dmLogPixels As Short
Public dmBitsPerPel As Short
Public dmPelsWidth As Integer
Public dmPelsHeight As Integer
Public dmDisplayFlags As Integer
Public dmDisplayFrequency As Integer
Public dmICMMethod As Integer
Public dmICMIntent As Integer
Public dmMediaType As Integer
Public dmDitherType As Integer
Public dmReserved1 As Integer
Public dmReserved2 As Integer
Public dmPanningWidth As Integer
Public dmPanningHeight As Integer
End Structure

<structlayout(layoutkind.sequential, charset:="CharSet.Ansi)"> _
Public Structure DisplayDevice
Public cb As Integer
' The MarshallAs attribute is covered in the Background section of the article
<marshalas(unmanagedtype.byvaltstr, sizeconst:="32)"> _
Public DeviceName As String
<marshalas(unmanagedtype.byvaltstr, sizeconst:="128)"> _
Public DeviceString As String
Public StateFlag As Integer
<marshalas(unmanagedtype.byvaltstr, sizeconst:="128)"> _
Public DeviceID As String
<marshalas(unmanagedtype.byvaltstr, sizeconst:="128)"> _
Public DeviceKey As String
End Structure

Public Class DisplayMonitor

Public Sub GetDisplayDevices(ByRef DisplayDev As DisplayDevice, ByVal DeviceName As String)
Dim initDisp As DisplayDevice = Me.DispDev
Dim counter As Integer = 0
Dim returnValue As Integer = 1

DisplayDev = Me.DispDev
' A return value of zero indicates that no more settings are available
While returnValue <> 0
returnValue = NativeMethods.EnumDisplayDevices(Nothing, counter, initDisp, 0)
If initDisp.DeviceName = DeviceName Then
DisplayDev = initDisp
Exit Sub
End If

counter = counter + 1
End While
End Sub

Public Sub GetDisplaySetting(ByRef Devmode As DevMode, ByVal NameDevice As String)
NativeMethods.EnumDisplaySettings(NameDevice, NativeMethods.ENUM_CURRENT_SETTINGS, Devmode)
End Sub

Public Sub DisplayChange(ByVal devmode As DevMode, ByVal NameDevice As String)
Dim errorMessage As String = ""
Dim iRet As ReturnCodes = NativeMethods.ChangeDisplaySettingsEx(NameDevice, devmode, Nothing, 1, Nothing)

If iRet <> ReturnCodes.DISP_CHANGE_SUCCESSFUL Then
MessageBox.Show("Error : " + iRet.ToString)
End If
End Sub

' Return a properly configured DEVMODE
Public ReadOnly Property DevMode() As DevMode
Get
Dim m_devmode As DevMode = New DevMode
m_devmode.dmDeviceName = New String(New Char, 32)
m_devmode.dmFormName = New String(New Char, 32)
m_devmode.dmSize = CType(Marshal.SizeOf(m_devmode), Short)
Return m_devmode
End Get
End Property

' Return a properly configured DisplayDevice
Public ReadOnly Property DispDev() As DisplayDevice
Get
Dim m_DisplayDevice As DisplayDevice = New DisplayDevice
m_DisplayDevice.cb = CType(Marshal.SizeOf(m_DisplayDevice), Integer)
m_DisplayDevice.DeviceName = New String(New Char, 32)
m_DisplayDevice.DeviceString = New String(New Char, 128)
m_DisplayDevice.DeviceID = New String(New Char, 128)
m_DisplayDevice.DeviceKey = New String(New Char, 128)
Return m_DisplayDevice
End Get
End Property

End Class

Public Class NativeMethods

<dllimport("user32.dll", charset:="CharSet.Ansi)"> _
Public Shared Function EnumDisplaySettings(ByVal lpszDeviceName As String, ByVal iModeNum As Integer, ByRef lpDevMode As DevMode) As Integer
End Function

<dllimport("user32.dll", charset:="CharSet.Ansi)"> _
Public Shared Function ChangeDisplaySettingsEx(ByVal lpszDeviceName As String, ByRef lpDevMode As DevMode, ByVal hdl As IntPtr, ByVal dwFlags As Integer, ByRef lParam As Long) As ReturnCodes
End Function

<dllimport("user32.dll", charset:="CharSet.Ansi)"> _
Public Shared Function EnumDisplayDevices(ByVal lpDevice As String, ByVal iModeNum As Integer, ByRef lpDisplayDevice As DisplayDevice, ByVal dwFlag As Integer) As Integer
End Function

Public Const ENUM_CURRENT_SETTINGS As Integer = -1

End Class

End Namespace
===================================== End Class ==============================

'Call

' In form

===================================== Form ===================================
'Procedure
Public Sub ChangeResolution(ByVal Width As Integer, ByVal Height As Integer)
Dim DispMonitor As New Win32Functions.DisplayMonitor
Dim DevModes As New Win32Functions.DevMode
Dim DispDev As New Win32Functions.DisplayDevice

DispMonitor.GetDisplayDevices(DispDev, "\\.\DISPLAY1")

If DispDev.StateFlag <> 1 Then
DispMonitor.GetDisplaySetting(DevModes, DispDev.DeviceName)

DevModes.dmPelsWidth = Width
DevModes.dmPelsHeight = Height
DispMonitor.DisplayChange(DevModes, DispDev.DeviceName)
End If
End Sub


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
ChangeResolution(800, 600)
End Sub

code from

http://www.sql.ru/forum/actualthread.aspx?tid=407345[^]

Nanda kumar | eMantras | Programmer
Generalplease help me regarding use u,r logic in vb.net Pin
ram krishna pattnayak13-Feb-07 21:08
ram krishna pattnayak13-Feb-07 21:08 
GeneralRe: please help me regarding use u,r logic in vb.net Pin
sreejith ss nair11-Mar-07 23:13
sreejith ss nair11-Mar-07 23:13 
GeneralUseful tip PinPopular
Vyacheslav Trubarov13-Jan-07 11:25
Vyacheslav Trubarov13-Jan-07 11:25 
GeneralRe: Useful tip Pin
SKRaj7822-Jan-08 9:19
SKRaj7822-Jan-08 9:19 
Generalhiii sreejith Pin
kannan m24-Jul-06 3:52
kannan m24-Jul-06 3:52 
GeneralRe: hiii sreejith Pin
sreejith ss nair7-Aug-06 4:41
sreejith ss nair7-Aug-06 4:41 
AnswerRe: hiii sreejith Pin
John Storer II14-Nov-06 2:21
John Storer II14-Nov-06 2:21 
GeneralThanks a BUNCH :-) Pin
KJAM200513-Jul-06 0:14
KJAM200513-Jul-06 0:14 
GeneralRe: Thanks a BUNCH :-) Pin
sreejith ss nair7-Aug-06 4:42
sreejith ss nair7-Aug-06 4:42 
GeneralNew and GRAND problem - Disorder Desktop-Icons Pin
sevenverse6-Jun-06 0:05
sevenverse6-Jun-06 0:05 
GeneralRe: New and GRAND problem - Disorder Desktop-Icons Pin
sreejith ss nair7-Aug-06 4:43
sreejith ss nair7-Aug-06 4:43 
Questionproblem - Disorder Desktop-Icons Pin
xDarkmanx4-Mar-08 11:56
xDarkmanx4-Mar-08 11:56 
GeneralGood Idea for small games BUT HOW DOW I GET THE SUPPORTED RESOLUTION Pin
sevenverse5-Jun-06 23:35
sevenverse5-Jun-06 23:35 
GeneralRe: Good Idea for small games BUT HOW DOW I GET THE SUPPORTED RESOLUTION Pin
sreejith ss nair7-Aug-06 4:47
sreejith ss nair7-Aug-06 4:47 
GeneralGreat Idea, wrong suggestion Pin
El Gato10-May-06 8:36
El Gato10-May-06 8:36 
GeneralRe: Great Idea, wrong suggestion Pin
sreejith ss nair7-Aug-06 4:45
sreejith ss nair7-Aug-06 4:45 
QuestionRe: Great Idea, wrong suggestion Pin
sreejith ss nair11-Mar-07 23:22
sreejith ss nair11-Mar-07 23:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.