using User32.ChangeDisplaySettings to set resolution fails only on max resolution ('badmode' error)
<p>So what I am trying to do is set a screen resolution on the primary display in C# using ChangeDisplaySettings. I have tested this across multiple windows 7 computers that I own, and the result is always the same: any* valid resolution (those that are listed in the "screen resolution" menu upon right-clicking the desktop) will work just fine, except for the largest resolution that can be selected in that menu, which will cause User32.ChangeDisplaySettings to return -2, which is DISP_CHANGE_BADMODE, meaning that the requested display mode was invalid.</p>

<p>*On some of the computers with larger primary displays, I didn't bother to test every resolution, and just picked some arbitrary smaller ones &amp; the maximum, as there were too many to test on every single one. I feel confident enough in my testing to say that the maximum resolution ALWAYS fails, while smaller resolutions usually/always succeed (I never had any of them fail during my tests anyways).</p>

<p>Documentation on ChangeDisplaySettings: <a href="http://msdn.microsoft.com/en-us/library/dd183411%28VS.85%29.aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/dd183411%28VS.85%29.aspx</a></p>

<p>Documentation on the DEVMODE struct it uses: <a href="http://msdn.microsoft.com/en-us/library/dd183565%28v=vs.85%29.aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/dd183565%28v=vs.85%29.aspx</a></p>

<p>So for an example, lets say I'm running on a 1920x1080 display.</p>

<p>I set my resolution manually (or programmatically) to something else, doesn't matter what it is or how it was changed, and then run the following code:</p>

<pre><code>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 (User32.EnumDisplaySettings(null, User32.ENUM_CURRENT_SETTINGS, ref dm) != 0)
{
     dm.dmPelsWidth = 1920;
     dm.dmPelsHeight = 1080;
     Console.WriteLine("" + User32.ChangeDisplaySettings(ref dm, User32.CDS_UPDATEREGISTRY) + "\n");
}
</code></pre>

<p>*Note that this is not actually the code from the program. I just made this simplified version to cut it down to the bare necessities to illustrate the point.</p>

<p>The program would print out:</p>

<pre><code>-2
</code></pre>

<p>Which, as mentioned previously, is the value of DISP_CHANGE_BADMODE, and the resolution would fail to change.</p>

<p>Now, if I changed the values of 1080 and 1920 to 900 and 1600 respectively, another supported resolution on this monitor, and then set the resolution to something other than 1600x900, and then ran this program, it would in fact change the resolution to 1600x900, and return DISP_CHANGE_SUCCESSFUL.</p>

<p>Note that using other flags, such as CDS_RESET (0x40000000 or 1073741824) in place of CDS_UPDATEREGISTRY also result in the same error.</p>

<p>This is a tutorial I found that helped me get started:</p>

<p>www.codeproject.com/Articles/6810/Dynamic-Screen-Resolution</p>

<p>[I removed the hyperlink because of the apparent spam prevention system. Sort of silly given that the first to were msdn.microsoft links, and this is a codeproject one, but, w/e]</p>

<p>Note that in the comments section, it seems there is someone who used the provided source files directly, and is experiencing a similar problem. To quote them:</p>

<blockquote>
  <p>hello ,
  i'm using Resolution.cs on my c# application
  and it doesn't work with high resolutions like " 1366*768 " &amp; " 1280*720 "
  can any one help ???</p>
</blockquote>

<p>However, despite how commonly ChangeDisplaySettings seems to be recommended by tutorials, I can't find any information on resolving this issue (which could very well be operating system specific, but I currently lack any non-Windows 7 computers to test on, and even if I did, it would not solve the issue that it doesn't work on Windows 7 computers)</p>
