Working with Dual Monitors in .Net
Prologue
It's been a while since I posted becuase until recently I haven't had the opportunity to do much coding lately. All the website updates I was working on got suspended and then outsourced so I haven't been doing much coding, mostly other projects. Recently though, I had reason to do some work with creating a web service and some other interesting things that I may do some articles on. One of those is today's article.
We recently purchased access to an XML data feed that gives us live data that we'd like to redisplay in a number of ways and a number of locations here. So I was tasked with the coding. I'll probably talk more about our re-purposing of the feed later in a subsequent article, but today I want to talk about something different, supporting dual monitors. The data we retrieve from the feed, we will be displaying in a number of locations. This is done quite often with a dual monitor computer. One display shows at the computer, and the other at a remote monitor, usually a flat panel TV.
Problem
Our problem, we found was that the application I wrote to display the information would maximize to the primary monitor, usually we want it to be displayed on the secondary monitor instead (the flat panel TV). Our challenge in this excercise is to get the application to run maximized on the secondary monitor. Additionally, not all locations that the application will be used at should necessarily go directly to the secondary monitor, so we want to let the user who launches the application select which monitor to display on.
Solution
Ok, let's begin by creating an application that exhibits the old, undesirable primary monitor oonly behavior first and then begin modifying the application to do what we need it to do. We don't need much for an application, so it'll be pretty simple. Begin by creating a new application. Modify the form so it maximizes by default, by changing the WindowState property of the form to Maximized. Also, we wanted to NOT have any window controls showing so also set the FormBorderStyle property to none. One last thing, we want to add one line of code to the form's click event handler as follows:
Application.Exit()
This will allow us to exit the program, otherwise since we don't have a title bar at the top, it would be rather difficult. Run the application and your form should fill the primary monitor. But how do we get it to go to the secondary monitor? We can't drag it there (no title bar remember?), moving the .exe file to the second monitor doesn't help either. We'll have to do it through code. So, add to your form a button and a checkbox, name the button btnDoIt, and the checkbox chkSecondMonitor. Change the checkbox's visible property to false. Now we're ready to start adding some code to move to the 2nd monitor. I found a post on Microsoft forums that walked me through some of the code to do what we want, you can read their information here.
First we want to make the checkbox show only if there are dual monitors. If not, then we don't want to show it. So we'll add some code to detect if there are multiple monitors. Let's create a new function that returns if there are dual monitors as follows:
Public Function DualMonitors() As Boolean
Dim myScreens() As Screen = Screen.AllScreens
If myScreens.Length > 1 Then Return True Else Return False
End Function
Basically, this retrieves an array of all the screens (monitors) available, checks if the array has more than one element (or more than one screen) and returns true if there are multiple. Now we need to add some code to the form_load event to make visible the checkbox if there are dual monitors. Add the following to form_load:
chkSecondMonitor.Visible = DualMonitors()
Now if you run your application, you'll see that our checkbox will display depending on availability of a 2nd monitor. However, we still need to make the form move when the button is clicked (if the checkbox is checked). To our btnDoIt_clicked event, add the following:
If chkSecondMonitor.Checked = True Then
Dim theScreen As Screen = Screen.AllScreens(1)
Me.Location = theScreen.Bounds.Location
End If
Basically, we're retrieving the specifics of the second screen (element 1 in the AllScreens array) and using its location to set our form's location. This in effect should move our form to the starting point of the 2nd monitor, the upper-left location will become our form's upper-left location.
Run your application, check the checkbox, click the button and see what happens. That's right, big fat nothing. Why? You can't move a form that is maximized. We need to either launch the application NOT maximized, or restore (un-maximize) the form, move it and then re-maximize it. So we'll modify our code to restore, move and maximize. Add the following BEFORE the Me.Location = line in our btnDoIt_Clicked event handler:
Me.WindowState = FormWindowState.Normal
and add it's corresponding maximize call after the Me.Location line:
Me.WindowState = FormWindowState.Maximized
Now run your application and observe it functioning. Check the box, click the button, the form restores, moves and the maximizes. Just as it should.
Epilogue
Realistically speaking, moving the application to the second monitor is very easy. There are other things that we could do using the screen object that we haven't touched on (centering the form on the second monitor etc). A point of distinction that may help if you want to do further development, the Bounds encompasss the entire screen (including the task bar), if you want working area (not including the task bar) you'll need to get the WorkingArea property instead of Bounds property.