I currently fiddle with both SetDisplayConfig()
and ChangeDisplaySettingsEx()
as well and found that this seems to work with my setup. SDC_TOPOLOGY_INTERNAL
and SDC_TOPOLOGY_EXTERNAL
refer to whatever Windows decides your primary (screen) and secondary (projector) monitor is, similar to the monitor selection when your press Win+P. It's the other way around for me, so you'd have to check whats the correct one in your configuration is. Then you can simply call InternalDisplay()
or ExternalDisplay()
to activate the one and automatically deactivate the other. I added the clone and extend settings for the sake of completeness.
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern long SetDisplayConfig(uint numPathArrayElements,
IntPtr pathArray, uint numModeArrayElements, IntPtr modeArray, uint flags);
UInt32 SDC_TOPOLOGY_INTERNAL = 0x00000001;
UInt32 SDC_TOPOLOGY_CLONE = 0x00000002;
UInt32 SDC_TOPOLOGY_EXTEND = 0x00000004;
UInt32 SDC_TOPOLOGY_EXTERNAL = 0x00000008;
UInt32 SDC_APPLY = 0x00000080;
public void CloneDisplays() {
SetDisplayConfig(0, IntPtr.Zero, 0, IntPtr.Zero, (SDC_APPLY | SDC_TOPOLOGY_CLONE));
}
public void ExtendDisplays() {
SetDisplayConfig(0, IntPtr.Zero, 0, IntPtr.Zero, (SDC_APPLY | SDC_TOPOLOGY_EXTEND));
}
public void ExternalDisplay() {
SetDisplayConfig(0, IntPtr.Zero, 0, IntPtr.Zero, (SDC_APPLY | SDC_TOPOLOGY_EXTERNAL));
}
public void InternalDisplay() {
SetDisplayConfig(0, IntPtr.Zero, 0, IntPtr.Zero, (SDC_APPLY | SDC_TOPOLOGY_INTERNAL));
}