Determining Windows resolution at runtime
23yrold3yrold

I've been trying to figure out a way to run a program so it displays on a second monitor. Works fine, by making that window a popup with the dimensions of the second monitor, an x coordinate equal to the first monitor's horizontal resolution, and a y coordinate of 0. Problem being these values need to be hardcoded and if some dingus changes the monitor's resolution, things mess up.

Making notes in readme's that the resolution must be such and such is fine, but I'm trying to make these programs idiot-proof, plus I don't like making multiple builds with different hard-coded variables. Anyone know of some sort of Win32 method for getting the monitor resolutions dynamically at runtime so I can always position the window at the desktop's right edge, and at the second monitor's resolution?

I may have asked this before, but it bothers me that I can't find a way to do it. :P Be real nice if the program was all automated and stuff ...

Jakub Wasilewski

You can call EnumDisplayDevices repeatedly (with a device of NULL) to get to your monitors. This will yield a number of DISPLAY_DEVICE structs, you'll have to check which of them correspond to monitors.

Then, you can EnumDisplaySettings with the DISPLAY_DEVICE.DeviceName and iModeNum=ENUM_CURRENT_SETTINGS to get actual information about the current resolution.

This is based on a rusty and incomplete knowledge of WinAPI, but with MSDN you might be able to make something out of it ;).

23yrold3yrold

You're more or less mentioning the structures and stuff that cropped up the last time I looked into this, but I was unable to translate it into actual code ...

Jakub Wasilewski

Let's see:

1#include <windows.h>
2#include <iostream>
3 
4using namespace std;
5 
6int main()
7{
8 DISPLAY_DEVICE adapter;
9 adapter.cb = sizeof(DISPLAY_DEVICE);
10
11 int i = 0;
12
13 while (EnumDisplayDevices(NULL, i++, &adapter, 0))
14 {
15 DEVMODE mode;
16 mode.dmSize = sizeof(DEVMODE);
17 mode.dmDriverExtra = 0;
18
19 cout << "Adapter " << i << ": " << adapter.DeviceName << endl;
20 if (EnumDisplaySettings(adapter.DeviceName, ENUM_CURRENT_SETTINGS, &mode))
21 cout << "\tresolution: " << mode.dmPelsWidth << "x" << mode.dmPelsHeight << endl;
22 else
23 cout << "Unable to get settings for device." << endl;
24 }
25
26 return 0;
27}

On my system, it shows this:

Adapter 1: \\.\DISPLAY1
        resolution: 1280x960
Adapter 2: \\.\DISPLAYV1
Unable to get settings for device.
Adapter 3: \\.\DISPLAYV2
Unable to get settings for device.

I think that on a multi-monitor system there will be at least two DISPLAYs. I'm not sure what those V1 and V2 are, but I think it's safe to ignore any adapters for which you are not able to retrieve settings.

EDIT: By the way, what is it for?

23yrold3yrold

Well, I run it and it detects my main resolution easily enough, so I'll call it win. I can't get my Windows settings to accept a secondary; keeps seeming to disable it, so I can't test here if it works for getting that second resolution. This is still a small victory though, so I assume the code works as intended and I grant you cookies. Now to look it over and see how it works. ;D

And it's for the kids I teach at church. We're kinda media driven and my supervisor is always asking me to write a program for this and that. It needs to go to the second monitor on the computer to display up front for the kids, and I've torn out a fair share of hair getting it working in a satisfactory manner. Think I may finally have it.

MiquelFire

Note, the second monitor may have it's right edge at 0, so it's left side is some negative value (depends on it's horizontal resolution).

Jakub Wasilewski

Well, this is a little late, but here is a simpler and better solution, using the proper function:

1#include <windows.h>
2#include <iostream>
3 
4using namespace std;
5 
6BOOL callback(HMONITOR hMonitor, HDC hdc, LPRECT rect, LPARAM data)
7{
8 static int no = 1;
9
10 cout << "Monitor " << no << ":\n";
11 cout << "\tTop-left corner at: " << rect->left << "," << rect->top << "\n";
12 cout << "\tResolution: " << (rect->right - rect->left) << "x" << (rect->bottom - rect->top) << "\n\n";
13
14 no++;
15 
16 return true;
17}
18 
19int main()
20{
21 EnumDisplayMonitors(NULL, NULL, (MONITORENUMPROC)callback, 0);
22}

I knew it was EnumDisplaySomethings, I just picked the wrong one the first time around ;). This way you get both coordinates for the monitor, so you always know where exactly to display the window. The callback is called repeatedly as long as there are monitors left, and as long as you return true from it.

Perhaps someone from the forums with multiple monitors at hand could test it?

Matthew Leverton
Quote:

Monitor 1:
Top-left corner at: 0,0
Resolution: 1280x1024

Monitor 2:
Top-left corner at: 1280,256
Resolution: 1024x768

Monitor 3:
Top-left corner at: -1280,0
Resolution: 1280x1024

Works for me.

MiquelFire
Quote:

Monitor 1:
Top-left corner at: 0,0
Resolution: 1280x1024

Monitor 2:
Top-left corner at: -1280,0
Resolution: 1280x1024

Works here as well.

BAF
Quote:

Monitor 1:
Top-left corner at: 0,0
Resolution: 1680x1050

Works fine for one monitor.

23yrold3yrold

Sounds awesome. I'll put it to good use; thanks again.

Thread #591426. Printed from Allegro.cc