Solution: Windows resizes open windows when display turns off

This post has been updated since it was published.

Windows 10 resizes open windows when a monitor connected via DisplayPort is turned off. All of the solutions provided around the internet either never worked, or stopped working for me.

I’ve trawled the internet for reasons and solutions. As far as I can gather the issue stems from the fact that Windows can’t cope with not having a display. The DP port is a special kind of stupid, and coupled with the general stupidity of Windows, it all comes to a head when a monitor connected via DP is turned off.

Windows decides to render to a simulated display, now that there’s no real one to render to. Because reasons. This magical simulated display has the very modern resolution of 640×480. Because more reasons. Guys… C’mon. You have a simulated display, why in the blazing fuck would you not just choose the last resolution the desktop was set to? What does it matter, it’s SIMULATED?! Or better yet, just accept that there’s no display right now and render at the last available resolution to /dev/null? Who cares? Who’s going to be watching it? Why are we even discussing this?

And of course, in their infinite wisdom, the engineers at Microsoft has decided that no window shall be left unreachable. Since the resolution has now changed, they’ve implemented an algorithm to resize everything to fit the virtual display, with the modern resolution, for no apparent reason other than… I don’t know, I honestly don’t. There’s no reason for this crapfest. Great work guys, you’ve simultaneously created a problem, solved it and created a new one.

I might be wrong. This might not be anywhere near how this all works. There might be valid and good reasons for this behavior. But frankly I no longer give a shit how or why it happens. It used to not happen, and now it does. And bucket loads of feedback and bug reports have not moved Microsoft to do anything about their half-assed implementation. I mean, a simple checkbox under the display tab in Settings that goes something like “Save open window dimensions when connection is lost to this device” could fix this once and for all. But no. That would be simple and not user hostile. We can’t have that can we?

Hordes of users have had this issue and smart people all over the ‘net have come up with solutions for this particular problem:

TechNet is it’s normal unhelpful self

Superuser.com has some creative solutions

Reddit is represented here , and here

Tomshardware chimes in

You get the point. Users all over the ‘net are having this issue. Other users step up to try and help out. None of it works for me, but I did learn a thing or two about how monitors work. So there’s that. None of the solutions worked for me. Some of them used to, but not anymore.

There’s even a guy who wrote an application to keep track of all your open windows and listen in on windows events to combat the problem. It’s a nice albeit over engineered solution to the problem. I’ve used his app myself. Unfortunately he abandoned it a couple of years ago. The source is available, but a giant PITA to get up and running and it relies on deprecated frameworks. And honestly it solves the wrong problem, a band aid if you will.

My use case is super simple: I want to be able to turn off my monitor when I leave my PC, and not have to fiddle with resizing windows when i return later.

In an effort to stop obsessing over this issue and getting on with my life, I’ve created a tiny application that solves the problem for me. It leverages the SendMessage API available in Windows since the dawn of time. It basically sends a message to itself instructing the system to put all displays to sleep. The idea came to me via StackOverflow, of course.

The code below if for a C# Console App.


using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace MonitorSleep
{
  class Program
  {
    private static int SC_MONITORPOWER = 0xF170;
    private static uint WM_SYSCOMMAND = 0x0112;

    [DllImport("user32.dll")]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

    static void Main(string[] args)
    {
      IntPtr hWnd = Process.GetCurrentProcess().MainWindowHandle;
      SendMessage(hWnd, WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)2);
    }
  }
}

The documentation for the arguments to SendMessage can be found here. The code should be pretty self-documenting, but I can run you through it if you like. First we find the handle of the currently executing process, which we’ll need for SendMessage. Then we call SendMessage with the handle for our own window, signalling that this is a system command, and the code for the command to control display power states. The 2 at the end signals that we want to turn the display off (which is misleading, it actually puts the display into power saving mode). And that’s it.

I use it like this: put the resulting .exe file somewhere convenient. I have a “Tools” folder on one of my drives for stuff like this. Then pin the application to the taskbar. Whenever I leave my PC, i click the sleepy icon and my monitor goes to sleep. For me, that solves the problem. When the monitor wakes up again, all open windows have the dimensions i left them with and everything is fine.

You can download the .exe, source code, icon file and a short readme here: MonitorSleep, all conveniently rolled up into a ZIP file for you. You’re welcome.

Update: Apparently Nvidia has seen fit to address the issue in one of their newer drivers, at least it seems to be fixed in the 384.94 version. Serves me well for sitting on a post as draft for too long I guess. It remains to be seen whether the issue is actually fixed for everyone though.

 

About Michael Thygesen

Professional software developer, hobbyist web developer, game developer and a lifelong coding enthusiast.
Tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *