Skip to content

Instantly share code, notes, and snippets.

@gsuberland
Created November 25, 2021 04:08
Show Gist options
  • Save gsuberland/81fbec0e0cd1caf0db4a1eb4b6f4407d to your computer and use it in GitHub Desktop.
Save gsuberland/81fbec0e0cd1caf0db4a1eb4b6f4407d to your computer and use it in GitHub Desktop.
Move displays programmatically on Windows in C#
// quick bit of code to move displays to specific locations in C#
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DEVMODE
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public int dmPositionX;
public int dmPositionY;
public int dmDisplayOrientation;
public int dmDisplayFixedOutput;
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;
public static DEVMODE Create()
{
DEVMODE dm = new DEVMODE();
dm.dmDeviceName = new String(new char[32]);
dm.dmFormName = new String(new char[32]);
dm.dmSize = (short)Marshal.SizeOf(dm);
return dm;
}
};
// PInvoke declaration for EnumDisplaySettings Win32 API
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref DEVMODE lpDevMode);
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int ChangeDisplaySettingsEx(string lpszDeviceName, ref DEVMODE lpDevMode, IntPtr hWnd, int dwFlags, IntPtr lParam);
// constants
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;
const int DM_BITSPERPEL = 0x40000;
const int DM_DISPLAYFLAGS = 0x200000;
const int DM_DISPLAYFREQUENCY = 0x400000;
const int DM_PELSHEIGHT = 0x100000;
const int DM_PELSWIDTH = 0x80000;
const int DM_POSITION = 0x20;
void Main()
{
// get existing position info
DEVMODE dm = DEVMODE.Create();
EnumDisplaySettings(@"\\.\DISPLAY5", ENUM_CURRENT_SETTINGS, ref dm);
// change x/y position here
dm.dmPositionX = -1920;
// tell ChangeDisplaySettingsEx to ignore all fields but the position
dm.dmFields = DM_POSITION;
// change the position
ChangeDisplaySettingsEx(@"\\.\DISPLAY5", ref dm, IntPtr.Zero, 0, IntPtr.Zero);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment