winapijsctypes

Improper width and height for second monitor from GetMonitorInfo and GetDeviceCaps


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.


Solution

  • 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