2
votes

I am trying to get the top left x,y and bottom right x,y. And calculat the width and height of displays.

My secondary monitor is 1920x1080 as seen in my display settings screenshot:

I am getting the monitor dimensions in two ways. The code below is js-ctypes but I simplified out all the error checking and other ctypes stuff and tried to make it look like c. But this is a winapi issue not ctypes hence I didn't tag the topic with it.

First approach:

cPoint = POINT();
GetCursorPos(&cPoint);


cMon = MonitorFromPoint(cPoint, MONITOR_DEFAULTTONEAREST);


cMonInfo = MONITORINFOEX();
cMonInfo.cbSize = MONITORINFOEX.size;
GetMonitorInfo(cMon, &cMonInfo);

lpszDriver = null;
lpszDevice = cMonInfo.szDevice;

xTopLeft = cMonInfo.rcMonitor.left;
yTopLeft = cMonInfo.rcMonitor.top;
nWidth = cMonInfo.rcMonitor.right - xTopLeft;
nHeight = cMonInfo.rcMonitor.bottom - yTopLeft;

This is giving me a rect of the following:

_RECT(-1920, -1080, -640, -360)

Doing right - left gives 1280 Doing bottom - top gives 720

The dimensions are definitely wrong. It should have been width of 1920 and height of 1080.

I then try the second method:

hdcScreen = CreateDC(lpszDriver, lpszDevice, null, null);
nWidth = GetDeviceCaps(hdcScreen, HORZRES);
nHeight = GetDeviceCaps(hdcScreen, VERTRES);

This gives me the same thing, width of 1280 and height of 720. My mind is boggled! How can I get 1920x1080?

This same method gives me correct dimensions for my primary monitor, so I am very confused.

EDIT

I just now tried a third method, and still same issues:

var jsMonitorEnumProc = function(hMonitor, hdcMonitor, lprcMonitor, dwData) {
    xTopLeft = lprcMonitor.contents.left;
    yTopLeft = lprcMonitor.contents.top;
    nWidth = lprcMonitor.contents.right - xTopLeft;
    nHeight = lprcMonitor.contents.bottom - yTopLeft;

    return true;
}
EnumDisplayMonitors(null, null, jsMonitorEnumProc, 0);

This gives me rects of the following:

_RECT(0, 0, 1280, 1024)
_RECT(-1920, -1080, -640, -360)

The first one is my primary monitor and we see doing bottom - top gives 1280 and right - left gives 1024 which is correct my primary monitor is 1280 x 1024.

But the second monitor again is -360 - -1080 for 720 height and -640 - -1920 for 1280 width. I am using this to take screenshots of all the monitors and second ones is coming out clipped.

1
Is your app DPI aware? If not, Windows can "lie" to you about the monitor dimensions to maintain compatibility with non-DPI apps in high-DPI systems.Remy Lebeau
Thanks @RemyLebeau I never considered that, how would I fix that please? :)Noitidart
You have to make your app DPI aware. Read the documentation: High DPI.Remy Lebeau
Thanks @RemyLebeau I'm reading right now, just a quick check, is this needed for Win8.1+ only?Noitidart
DPI awareness was introduced in Windows Vista, but per-monitor DPI was introduced in Windows 8.1: Writing DPI-Aware Desktop and Win32 ApplicationsRemy Lebeau

1 Answers

0
votes

In my non-dpi aware app 32bit Firefox on Win 8.1 64bit, I was able to get the proper dimensions by using EnumDisplaySettings using the DISPLAY_DEVICE struct of size 220.

js-ctypes:

// start - get all monitor resolutions
var iDevNum = -1;
while (true) {
    iDevNum++;
    var lpDisplayDevice = ostypes.TYPE.DISPLAY_DEVICE();
    lpDisplayDevice.cb = ostypes.TYPE.DISPLAY_DEVICE.size;
    var rez_EnumDisplayDevices = ostypes.API('EnumDisplayDevices')(null, iDevNum, lpDisplayDevice.address(), 0);
    //console.info('rez_EnumDisplayDevices:', rez_EnumDisplayDevices.toString(), uneval(rez_EnumDisplayDevices), cutils.jscGetDeepest(rez_EnumDisplayDevices));

    if (cutils.jscEqual(rez_EnumDisplayDevices, 0)) { // ctypes.winLastError != 0
        // iDevNum is greater than the largest device index.
        break;
    }

    console.info('lpDisplayDevice.DeviceName:', lpDisplayDevice.DeviceName.readString()); // "\\.\DISPLAY1" till "\\.\DISPLAY4"

    if (lpDisplayDevice.StateFlags & ostypes.CONST.DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) {
        console.log('is monitor');

        var dm = ostypes.TYPE.DEVMODE(); // SIZEOF_DEVMODE = 148
        console.info('dm.size:', ostypes.TYPE.DEVMODE.size);
        //dm.dmFields = ostypes.CONST.DM_PELSWIDTH;
        //dm.dmSize = ostypes.TYPE.DEVMODE.size;

        console.log('iDevNum:', iDevNum, lpDisplayDevice.DeviceName.readString());
        var rez_EnumDisplaySettings = ostypes.API('EnumDisplaySettings')(lpDisplayDevice.DeviceName, ostypes.CONST.ENUM_CURRENT_SETTINGS, dm.address());
        //console.info('rez_EnumDisplaySettings:', rez_EnumDisplaySettings.toString(), uneval(rez_EnumDisplaySettings), cutils.jscGetDeepest(rez_EnumDisplaySettings));
        //console.info('dm:', dm.toString());

        collMonInfos.push({
            x: parseInt(cutils.jscGetDeepest(dm.u.dmPosition.x)),
            y: parseInt(cutils.jscGetDeepest(dm.u.dmPosition.y)),
            w: parseInt(cutils.jscGetDeepest(dm.dmPelsWidth)),
            h: parseInt(cutils.jscGetDeepest(dm.dmPelsHeight)),
            screenshot: null, // for winnt, each collMonInfos entry has screenshot data
            otherInfo: {
                nBPP: parseInt(cutils.jscGetDeepest(dm.dmBitsPerPel)),
                lpszDriver: null,
                lpszDevice: lpDisplayDevice.DeviceName
            }
        });
    }
}
// end - get all monitor resolutions