Click here to Skip to main content
12,759,971 members (32,198 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as


10 bookmarked
Posted 6 Apr 2011

How to create a display switcher for Windows XP

, 6 Apr 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
This article shows how to use native APIs in C# to switch between multiple displays.


Windows 7 comes with a built-in display switcher for multiple displays which can be activated using the (Windows + P) shortcut key. This article shows how to implement a similar utility to switch between multiple displays in older Operating Systems such as Windows XP and below.


I had to frequently switch between multiple displays when I using Windows XP. Every time I wanted to switch display, I had to go to Display Properties and fiddle with the UI to extend/shift the display to the second display. I found this to be extremely annoying and decided to do it the API way. So I wrote a program to switch displays with two clicks. You can use the source code to create your own utility.

Using the code

This code is written in C# using the Win32 Managed API. I have divided the article into two easy parts:

  • Part 1: The native structures and function declarations needed for the program to work.
  • Part 2: How to use the APIs to switch the display.

Part 1

These variables hold the device information for the active and the inactive displays. The enumeration is required to tell the API to get display-device information from the Registry.

//Member variables
DEVMODE ddActive = new DEVMODE();
DEVMODE ddInactive = new DEVMODE();
string szActiveDeviceName = string.Empty;
string szInactiveDeviceName = string.Empty;
const int ENUM_REGISTRY_SETTINGS = -2;        

Next are the DllImports and these are the stars of our show. EnumDisplayDevices gets all the devices connected to your system. EnumDisplaySettings gets the detailed information of the selected device obtained from EnumDisplayDevices. This information can then be used to pass to ChangeDisplaySettingsEx to manipulate the display devices.

static extern bool EnumDisplayDevices(string lpDevice, 
       uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags);

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

static extern DISP_CHANGE ChangeDisplaySettingsEx(string lpszDeviceName, 
       ref DEVMODE lpDevMode, IntPtr hwnd, uint dwflags, IntPtr lParam);

The last part of declarations are the enums which are used by the API and we need to construct them for the APIs to work properly.

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
public struct DEVMODE
    public const int CCHDEVICENAME = 32;
    public const int CCHFORMNAME = 32;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
    public string dmDeviceName;
    public Int16 dmSpecVersion;
    public Int16 dmDriverVersion;
    public Int16 dmSize;
    public Int16 dmDriverExtra;
    public DM dmFields;
    Int16 dmOrientation;
    Int16 dmPaperSize;
    Int16 dmPaperLength;
    Int16 dmPaperWidth;
    Int16 dmScale;
    Int16 dmCopies;
    Int16 dmDefaultSource;
    Int16 dmPrintQuality;

    public POINTL dmPosition;
    public Int32 dmDisplayOrientation;
    public Int32 dmDisplayFixedOutput;

    public short dmColor;
    public short dmDuplex;
    public short dmYResolution;
    public short dmTTOption;
    public short dmCollate;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
    public string dmFormName;
    public Int16 dmLogPixels;
    public Int32 dmBitsPerPel;
    public Int32 dmPelsWidth;
    public Int32 dmPelsHeight;
    public Int32 dmDisplayFlags;
    public Int32 dmNup;
    public Int32 dmDisplayFrequency;


[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DISPLAY_DEVICE
    public int cb;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public string DeviceName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string DeviceString;
    public DisplayDeviceStateFlags StateFlags;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string DeviceID;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string DeviceKey;

public enum DisplayDeviceStateFlags : int
    AttachedToDesktop = 0x1,
    MultiDriver = 0x2,
    PrimaryDevice = 0x4,
    MirroringDriver = 0x8,
    VGACompatible = 0x16,
    Removable = 0x20,
    ModesPruned = 0x8000000,
    Remote = 0x4000000,
    Disconnect = 0x2000000

public enum DM : int
    Orientation = 0x1,
    PaperSize = 0x2,
    PaperLength = 0x4,
    PaperWidth = 0x8,
    Scale = 0x10,
    Position = 0x20,
    NUP = 0x40,
    DisplayOrientation = 0x80,
    Copies = 0x100,
    DefaultSource = 0x200,
    PrintQuality = 0x400,
    Color = 0x800,
    Duplex = 0x1000,
    YResolution = 0x2000,
    TTOption = 0x4000,
    Collate = 0x8000,
    FormName = 0x10000,
    LogPixels = 0x20000,
    BitsPerPixel = 0x40000,
    PelsWidth = 0x80000,
    PelsHeight = 0x100000,
    DisplayFlags = 0x200000,
    DisplayFrequency = 0x400000,
    ICMMethod = 0x800000,
    ICMIntent = 0x1000000,
    MediaType = 0x2000000,
    DitherType = 0x4000000,
    PanningWidth = 0x8000000,
    PanningHeight = 0x10000000,
    DisplayFixedOutput = 0x20000000

enum DISP_CHANGE : int
    Successful = 0,
    Restart = 1,
    Failed = -1,
    BadMode = -2,
    NotUpdated = -3,
    BadFlags = -4,
    BadParam = -5,
    BadDualView = -1

public struct POINTL
    public long x;
    public long y;

enum CDSFlags
    CDS_RESET = 0x40000000,
    CDS_UPDATEREGISTRY = 0x00000001,
    CDS_SET_PRIMARY = 0x00000010

Part 2: Time for some action

In my example, I am going to show you a function to toggle between your multiple displays. First, get the device information using this function. This will set the Active and the Inactive device information for your code to use.

  • Active device information:
    • ddActive
    • szActiveDeviceName
  • Inactive device information:
    • ddInactive
    • szInactiveDeviceName
public void GetDisplayInfo()
    ddActive.dmSize = (short)Marshal.SizeOf(ddActive);
    ddInactive.dmSize = (short)Marshal.SizeOf(ddInactive);
    uint iDeviceCntr = 0;
    dd.cb = Marshal.SizeOf(dd);
    while(EnumDisplayDevices(null,iDeviceCntr, ref dd,0))
        DEVMODE dMode = new DEVMODE();
        dMode.dmSize = (short)Marshal.SizeOf(dMode);
        if (EnumDisplaySettings(dd.DeviceName, ENUM_REGISTRY_SETTINGS, ref dMode))
            if (dMode.dmPelsHeight > 0 && dMode.dmPelsWidth > 0)
                if ((dd.StateFlags & DisplayDeviceStateFlags.PrimaryDevice) == 
                    ddActive = dMode;
                    szActiveDeviceName =  dd.DeviceName;
                    ddInactive = dMode;
                    szInactiveDeviceName =  dd.DeviceName;

The next function resets your display to set the primary display device as active and disable the second one. This uses the ChangeDisplaySettingsEx API.

private void ChangeToSingleDisplay()
    ddInactive.dmPosition.x = 0;
    ddInactive.dmPosition.y = 0;
    ddInactive.dmPelsHeight = 0;
    ddInactive.dmPelsWidth = 0;
    ddInactive.dmFields = DM.PelsHeight | DM.PelsWidth | DM.Position;

    ChangeDisplaySettingsEx(szInactiveDeviceName, ref ddInactive, 
      IntPtr.Zero, (int)(CDSFlags.CDS_RESET | CDSFlags.CDS_UPDATEREGISTRY), IntPtr.Zero);

Next, we will get the get the refreshed display information and try to toggle the displays (making active device inactive, and vice versa).

ddInactive.dmPosition.x = 0;
ddInactive.dmPosition.y = 0;
ddInactive.dmFields = DM.Position;
if (DISP_CHANGE.Successful == ChangeDisplaySettingsEx(szInactiveDeviceName, 
    ref ddInactive, IntPtr.Zero, 
     CDSFlags.CDS_SET_PRIMARY), IntPtr.Zero))
    ddActive.dmPosition.x = 0;
    ddActive.dmPosition.y = 0;
    ddActive.dmPelsHeight = 0;
    ddActive.dmPelsWidth = 0;
    ddActive.dmFields = DM.PelsHeight | DM.PelsWidth | DM.Position;

    ChangeDisplaySettingsEx(szActiveDeviceName, ref ddActive, 
      IntPtr.Zero, (int)(CDSFlags.CDS_RESET | 
      CDSFlags.CDS_UPDATEREGISTRY), IntPtr.Zero);

That's all.


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


About the Author

Software Developer (Senior)
United States United States
No Biography provided

You may also be interested in...


Comments and Discussions

QuestionWin7 Windows-P Duplicate/Extend mode in code? Pin
k9mab8-Apr-11 17:17
memberk9mab8-Apr-11 17:17 
AnswerRe: Win7 Windows-P Duplicate/Extend mode in code? Pin
Nikhil Mujumdar10-Apr-11 18:47
memberNikhil Mujumdar10-Apr-11 18:47 
GeneralRe: Win7 Windows-P Duplicate/Extend mode in code? Pin
hxhgxytiger28-May-11 5:19
memberhxhgxytiger28-May-11 5:19 

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.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170217.1 | Last Updated 6 Apr 2011
Article Copyright 2011 by nikhilogic
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid