Click here to Skip to main content
Licence CPOL
First Posted 21 Apr 2004
Views 221,429
Downloads 5,149
Bookmarked 80 times

Dynamic Screen Resolution

By | 22 Jul 2008 | Article
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.

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.

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
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.

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#.

[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.

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.

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)

About the Author

sreejith ss nair

Software Developer (Senior)
Freelance
India India

Member

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.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
QuestionHigh Resolutions Pinmemberahmed.helmy2043:17 18 Dec '11  
QuestionCannot change resolution in Winlogon Screen Pinmembersonali.mendis21:04 8 Sep '11  
QuestionNice its helps me.. PinmemberPritesh Aryan21:01 25 Jul '11  
GeneralMy vote of 5 PinmemberMember 23125030:21 7 Jul '11  
GeneralMy vote of 5 Pinmembertomydragon21:52 5 Oct '10  
GeneralDesktop doesn't follow new orientation on Windows 7 Pinmemberrapik22:24 12 Apr '09  
GeneralDual Monitor Support PinmemberDaniel N21:55 1 Apr '09  
GeneralThanks for this usefull post PinmemberMedoune4:40 9 Mar '09  
GeneralDynamic Screen Resoultion for Windows Mobile Pinmemberjayanice17:51 24 Feb '09  
Question1280x800 ?? Pinmemberronaldo268912:28 20 Nov '08  
Generalconstant size of letters whatever the screen physical size Pinmemberpierre_lannion22:44 14 Sep '08  
AnswerRe: constant size of letters whatever the screen physical size Pinmemberwebatxcent8:18 15 Jan '09  
Generalget available screen resolutions Pinmemberpravin parmar19:32 15 Oct '07  
GeneralRe: get available screen resolutions Pinmembersreejith ss nair0:15 16 Oct '07  
GeneralRe: get available screen resolutions Pinmemberpravin parmar18:37 16 Oct '07  
GeneralRe: get available screen resolutions PinmemberSKRaj789:29 22 Jan '08  
GeneralRe: get available screen resolutions PinmemberSKRaj7810:10 22 Jan '08  
GeneralRe: get available screen resolutions PinmemberSKRaj7810:56 22 Jan '08  
GeneralRe: get available screen resolutions Pinmemberizne16:45 31 Mar '08  
QuestionCDS_TEST is 0x2 and CDS_UPDATEREGISTRY = 0x1??? PinmemberAYR Chen21:08 17 Aug '07  
GeneralError Message Pinmembermegaroo7914:47 26 Jun '07  
GeneralRe: Error Message Pinmembershradds4:29 18 Mar '09  
GeneralRe: Error Message PinmemberEpon19:57 14 Jul '10  
Generalvb.net version Pinmembernandhucbm2:55 5 Jun '07  
Generalplease help me regarding use u,r logic in vb.net Pinmemberram krishna pattnayak21:08 13 Feb '07  
i follow u,r code and do the code in vb.net in a module,but it not work.it show error:-Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
i send my totall code to u:
in a message list u give the sugession for using in vb.net:but when i put all u,r code in a class library then it only take the DEVMOID2 structer only.
please help me:My code is
 
Imports System.Runtime.InteropServices
Imports System.Runtime.InteropServices.MarshalAsAttribute
Imports System.Windows.Forms
Imports DEVMODE1
Module Module1
'Changes resolution on the fly, without rebooting
'Call with:
'Call ChangeRes(800,600)
'or Call ChangeRes(640,480) for example
' if resolution is not possible, a dialog is displayed
Public Declare Function EnumDisplaySettings Lib "user32" Alias "EnumDisplaySettingsA" (ByVal lpszDeviceName As String, ByVal iModeNum As Integer, ByVal lpDevMode As DEVMODE1) As Integer
Public Declare Function ChangeDisplaySettings Lib "user32" Alias "ChangeDisplaySettingsA" (ByVal lpDevMode As DEVMODE1, ByVal dwflags As String) As Integer
 
Const CCDEVICENAME = 32
Const CCFORMNAME = 32
Const DM_PELSWIDTH = &H80000
Const DM_PELSHEIGHT = &H100000
Const ENUM_CURRENT_SETTINGS = -1
Const CDS_UPDATEREGISTRY = 0
 
Const CDS_TEST = 0
Const DISP_CHANGE_SUCCESSFUL = 0
Const DISP_CHANGE_RESTART = 1
Const DISP_CHANGE_FAILED = -1
 
'Private Structure DEVMODE2
' '[MarshalAs](UnmanagedType.ByValTStr,SizeConst=32)] public dmDeviceName as string
' Public dmDeviceName As String '* CCDEVICENAME
' 'Dim dmDeviceName As String '* CCDEVICENAME
' Public dmSpecVersion As Integer
' Public dmDriverVersion As Integer
' Public dmSize As Integer
' Public dmDriverExtra As Integer
 
' Public dmFields As Long
' Public dmOrientation As Integer
' Public dmPaperSize As Integer
' Public dmPaperLength As Integer
' Public dmPaperWidth As Integer
' Public dmScale As Integer
' Public dmCopies As Integer
' Public dmDefaultSource As Integer
' Public dmPrintQuality As Integer
' Public dmColor As Integer
' Public dmDuplex As Integer
' Public dmYResolution As Integer
' Public dmTTOption As Integer
' Public dmCollate As Integer
 
' '[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
' Public dmFormName As String
' Public dmUnusedPadding As Integer
' Public dmBitsPerPel As Integer
' Public dmPelsWidth As Long
' Public dmPelsHeight As Long
' Public dmDisplayFlags As Long
' Public dmDisplayFrequency As Long
'End Structure
 
Dim DevM As DEVMODE1-this DEVMODE1 is similar to u,r DEVMOID structer i call this from class library
 

Sub ChangeRes(ByVal iWidth As Single, ByVal iHeight As Single)
'Dim a As Integer
DevM.dmSize = Marshal.SizeOf(DevM)
'DevM.dmDeviceName as new string (new char[32]);
'Dim i As Integer
' i = 0
'Do
If (0<>EnumDisplaySettings(0&, ENUM_CURRENT_SETTINGS, DevM)it show the error message) Then
'i = i + 1
'Loop Until (a = False)
 
'Dim b&
DevM.dmFields = DM_PELSWIDTH Or DM_PELSHEIGHT
 
DevM.dmPelsWidth = iWidth
DevM.dmPelsHeight = iHeight
Dim Ret As Integer
Ret = ChangeDisplaySettings(DevM, 0)
If Ret = DISP_CHANGE_FAILED Then
 
MessageBox.Show("Unable to process your request")
MessageBox.Show("Description: Unable To Process Your Request. Sorry For This Inconvenience.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
Else
Ret = ChangeDisplaySettings(DevM, CDS_UPDATEREGISTRY)
 
Select Case Ret
 
Case DISP_CHANGE_SUCCESSFUL
 

 
'successfull change
 
'Case DISP_CHANGE_RESTART
 

MessageBox.Show("Description: You Need To Reboot For The Change To Happen.\n If You Feel Any Problem After Rebooting Your Machine\nThen Try To Change Resolution In Safe Mode.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
'break;
'//windows 9x series you have to restart
 
Case Else
 

MessageBox.Show("Description: Failed To Change The Resolution.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
'break;
'//failed to change
End Select
 

End If
End If
 
End Sub
 
End Module

 
Class LibraeyStructer
 
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
 
public struct DEVMODE1
{
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=32)] public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
 
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
 
public short dmScale;
public short dmCopies;
public short dmDefaultSource;
public short dmPrintQuality;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string dmFormName;
public short dmLogPixels;
public short dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
 
public int dmDisplayFlags;
public int dmDisplayFrequency;
 
public int dmICMMethod;
public int dmICMIntent;
public int dmMediaType;
public int dmDitherType;
public int dmReserved1;
public int dmReserved2;
 
public int dmPanningWidth;
public int dmPanningHeight;
};
 

 
class User_32
{
[DllImport("user32.dll")]
public static extern int EnumDisplaySettings (string deviceName, int modeNum, ref DEVMODE1 devMode );
[DllImport("user32.dll")]
public static extern int ChangeDisplaySettings(ref DEVMODE1 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;
}
 

namespace Resolution
{
class CResolution
{
public CResolution(int a,int b)
{
Screen screen = Screen.PrimaryScreen;


int iWidth =a;
int iHeight =b;

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

dm.dmPelsWidth = iWidth;
dm.dmPelsHeight = iHeight;
 
int iRet = User_32.ChangeDisplaySettings (ref dm, User_32.CDS_TEST);
 
if (iRet == User_32.DISP_CHANGE_FAILED)
{
MessageBox.Show("Unable to process your request");
MessageBox.Show("Description: Unable To Process Your Request. Sorry For This Inconvenience.","Information",MessageBoxButtons.OK,MessageBoxIcon.Information);
}
else
{
iRet = User_32.ChangeDisplaySettings (ref dm, User_32.CDS_UPDATEREGISTRY);
 
switch (iRet)
{
case User_32.DISP_CHANGE_SUCCESSFUL:
{
break;
 
//successfull change
}
case User_32.DISP_CHANGE_RESTART:
{

MessageBox.Show("Description: You Need To Reboot For The Change To Happen.\n If You Feel Any Problem After Rebooting Your Machine\nThen Try To Change Resolution In Safe Mode.","Information",MessageBoxButtons.OK,MessageBoxIcon.Information);
break;
//windows 9x series you have to restart
}
default:
{

MessageBox.Show("Description: Failed To Change The Resolution.","Information",MessageBoxButtons.OK,MessageBoxIcon.Information);
break;
//failed to change
}
}
}

}
}
}
}

 
Ram Krishna Pattnayak
Software Developer(SDS)
Sun-Dew Solutions Pvt.Ltd
www.sundewsolutions.com
kolkata

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

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

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120529.1 | Last Updated 22 Jul 2008
Article Copyright 2004 by sreejith ss nair
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid