You normally don’t have to pay special attention to multi-monitor setups when programming Windows desktop applications. There are only a few areas where multi-monitor setups differ from a single monitor machine. However, since many developers still use only one monitor, they often make assumptions that are not valid when more than one monitor is used.
I will highlight two problem areas where many programs, including popular ones, make these wrong assumptions and therefore contain bugs on multi-monitor machines. In fact, we have been affected by one of these problems ourselves. A customer reported that the SmartInspect Console isn’t restored correctly when it’s closed on a non-primary monitor in maximized state. We tested it, could reproduce the annoyance and wondered why we never noticed it before, especially since we use two monitors, too. We found out that we didn’t test this case because our primary test systems are VMware machines which unfortunately cannot emulate more than one monitor. After we fixed the problem, we quickly added new test cases to our test plan to avoid such problems in the future.
Problem Numero One
Most Windows programs try to save the last position of the main window when a program is closed. When the program is started again, it is expected that the application restores the last known position on the screen. Most programs do this correctly – even on multi-monitor machines. However, there is one special case, when a program is closed maximized, where many programs fail (including the SmartInspect Console).
Most programs actually do not save the window position and size when a program is closed maximized. They only remember the fact that the program has been closed maximized and try to restore this state on program startup. So, why do they do this? This is often done because when a program is maximized, the current position of the window is the top left corner of the screen (usually at X=0, Y=0) and the size of the window is the entire desktop.
When a program tries to save these values, restores them on program startup and then maximizes the main window, the following can happen: If the user wants to switch the window from maximized to normal state, the window will keep the same size, because the restored position of the window is at X=0, Y=0 and the size is the size of the entire desktop. To workaround this problem, many applications simply do not store the size and position of a window when the application is closed maximized. This is normally acceptable, but on a multi-monitor setup, this can lead to some annoying bugs.
The bug demonstrated with Mozilla Firefox
To demonstrate this bug, I use the popular Firefox browser. After I discovered this problem in SmartInspect, I tried if other applications have the same behavior and Firefox seems to have exactly the same bug. To reproduce the problem, you will need two monitors:
- Position the Firefox window in normal mode (not maximized) in the middle of the first screen and then close it.
- Now start Firefox again and it should be restored at the exact same position as it was when you closed it.
- Now move Firefox to your second monitor, maximize it and close it again.
- When you now start Firefox, it is restored in maximized state, but on the wrong monitor.
This is the exact same problem I just described. Because Firefox only saves the maximized state but not the actual position of the main window, it cannot restore the window on the correct monitor. In fact, it will just use the same position for normal mode that was used when you closed it in step 1. It is easy to confirm this theory:
- Position the Firefox main window on your second monitor (normal mode) and close it.
- Start it again, maximize the main window and close it again.
- When you start Firefox now, it should be restored in maximized state on the correct monitor.
This works because Firefox saved the position of the window in the first and the maximized state in the second step. When started again, it first restored the position of the window and then maximized it so it ended up on the correct screen.
How can this confusing and annoying problem be fixed? Fortunately, it can be fixed quite easily. Remember why the position and size of the main window is normally not saved when an application is closed in maximized state? The problem was that the position and size of the window represent the entire desktop. But Windows has a nice API function called GetWindowPlacement which returns a structure that contains not only the current window state, but also contains the position and size of the window when it’s not maximized.
So the solution to the previous problem is to just call this API function, retrieve the normal size and position of the window and save it, regardless of the state of the window. This will make sure that the position is always restored on the correct screen even in maximized mode.
Where Is My Window?
The second wrong assumption and problem is with the window position itself. Normally you don’t have negative window positions on a single monitor machine (although this is not always true, we can ignore the special cases where it does happen). If we take a two monitor setup and the primary monitor is on the right, windows on the secondary screen (on the left) will have negative values for Left (or X, whatever you want to call it). The window positions are always calculated relative to the primary monitor (the one normally displaying the Windows taskbar). This results in having negative position values when a window moves to the left or top of the main screen.
So, when a programmer expects the window positions to be always positive, they cannot be restored correctly on a non-primary monitor. Another strange effect can happen when an unsigned integer is used to store the positions: As the numbers get gigantic when a negative number is stored in an unsigned integer, a window could be restored 2.000.000 million pixels on the right of the screen, so it looks like the window of the just started application is hidden (it is still visible in the taskbar). To avoid all these confusing problems, make sure that you never assume that window positions are always >= 0.
As the described problems are quite annoying for owners of multiple monitor systems, make sure you keep these problems in mind when designing your next Windows desktop application. By the way, testing the correct behavior of your application on such systems could be the perfect argument for your manager to get you a good graphic card and a second screen (next to other good arguments)! If you have any questions or comments about this article, just drop me a mail at [email protected].