Rawns
Rawns

Reputation: 875

Order buttons that represent attached monitors by Windows Display order

I have the below code to draw a button(s) onto a panel for each monitor that is currently connected to the PC.

var padding = 5;
var buttonSize = new Size(95, 75);
for (int i = 0; i < Screen.AllScreens.Length; i++)
{
    var screen = Screen.AllScreens[i];
    Button monitor = new Button
    {
        Name = "Monitor" + screen,
        AutoSize = true,
        Size = buttonSize,
        Location = new Point(12 + i * (buttonSize.Width + padding), 14),
        BackgroundImageLayout = ImageLayout.Stretch,
        BackgroundImage = Properties.Resources.display_enabled,
        TextAlign = ContentAlignment.MiddleCenter,
        Font = new Font("Segoe UI", 10, FontStyle.Bold),
        ForeColor = Color.White,
        BackColor = Color.Transparent,
        Text = screen.Bounds.Width + "x" + screen.Bounds.Height
    };

    monitorPanel.Controls.Add(monitor);
}

For devices with one or more monitors attached, the code works just fine and this is the end result:

enter image description here

However, while it works, I'd like to (if possible) order them as they appear in the Windows display view:

enter image description here

In the first screenshot, they are ordered as 2 | 3 | 1 instead of 3 | 2 | 1.

Is what I'm after possible?

Upvotes: 3

Views: 207

Answers (1)

kiziu
kiziu

Reputation: 1130

Multiple screens in Windows are handled as one, big, "glued" working area. Based on that, order of screens in configuration is according to their position in the new working area. Assuming that all of your screens are in one line, you can just use

screen.Bounds.X

as ordering property. If the screens are layed out in multiple rows, then ordering will also have to consider Y component.

EDIT: You could just use Linq for sorting, specifically OrderBy(). Example usage for case when screens are in one row and collection will be iterated once.

Change

for (int i = 0; i < Screen.AllScreens.Length; i++)
{
   var screen = Screen.AllScreens[i];

to

foreach(var screen in Screen.AllScreens.OrderBy(i => i.Bounds.X))
{

Upvotes: 1

Related Questions