Windows 7 Multi Monitor Display numbers are unreliable

pjkdeveloper

New Member
In Xp and Vista it was easy to retrieve the display device ID (I.E. \\.\Display1, \\.\Display2, etc). The returned deviced ID's matched the display numbers as depicted on screens with the "identify" button....where a big '1' and '2' would appear on the monitors if clicked.

In Windows 7, this is all broken. Can anyone tell me how to reliably return the display device number (the 1, 2, (or 3 if more than one video card)) that appears on the "Windows 7 Screen Resolution" window?

EnumDisplayDevices, GetMonitorInfo, etc. etc. rarely return display device ID's that actually match the display numbers on the Win 7 Screen Resolution screen.

It seems completely random as to what is returned as \\.\Display1 and \\.\Display2 as well as what numbers win 7 shows on the screen resolution window! Sometimes it'll match up, and MOST times they will NOT match! And worst, it all can change from boot to boot on the same machine!

Someone? HELP!!! I've posted on other forums....I've filed a bug report in microsoft connect (has gone unanswered now for 2 1/2 months)......all to know avail......
 

CommonTater

New Member
Have you tried ...

BOOL EnumDisplayMonitors(
__in HDC hdc,
__in LPCRECT lprcClip,
__in MONITORENUMPROC lpfnEnum,
__in LPARAM dwData
);


It's part of GDI. Should be present Win2000 to current.
 
Last edited:

pjkdeveloper

New Member
Thank you for responding!

I certainly have tried that. It returns the same information as GetMonitorInfo. In both function calls, the device name that is returned rarely correlates with the "display numbers" as seen on the Windows 7 "screen resolution" window. Most times the device names are flipped as to what Windows 7 is calling #1 and #2 ('screen resolution' window), and sometimes it actually does match. There is no consistency, and when using 3 monitors (two video cards), the circus is exacerbated even further.

Since my software displays different things on different screens (user selectable), it is impossible for me to have the user pre-specify what they want on secondary displays....since between reboots, the device names returned by the function calls frequently flip around (as well as the display numbers in Win7 screen resolution) and rarely correspond with the Win7 'screen resolution' window. If \\.\display2 *always* corresponded with what the Win7 'screen resolution' window called #1.....then the problem could be manageable....but sadly that is not the case....and when using two video cards to have two secondary displays....forget it....

Again, THANK YOU for responding
 

CommonTater

New Member
Wow, that sucks.

Is "\\.\display1" always the same screen? If so you probably should treat the results from GetMonitorInfo etc. as handles; like file handles. While we never know the actual handle of a file, we do know that if we open it by name and store the handle in the same variable every time, we can talk to the file. Perhaps this is a route to investigate...

Do you have the Windows 7 SDK? If not you can download it for free. There is a complete chapter in there on working with displays and multiple displays. Apparently it's tied to assigning a "Device Context" to the monitor's name... I didn't read it all but it does sound promissing.

Link Removed due to 404 Error


I've never done this... not sure I want to, now... but others do get it done so, at least, you know you're not looking at an impossiblity.
 

pjkdeveloper

New Member
No, \\.\display1 is NOT always the same screen....sometimes \\.\display1 is the primary and screen #1 in "screen resolution" is #2 (the secondary)....sometimes \\.\display2 is the primary and screen #1 in "screen resolution" is
primary! Sometimes they match (not often though!). Sometimes "screen resolution" reports the primary as #2 and the function calls report the primary as \\.\display1....sometimes the "screen resolution" reports the primary as #1 and the function calls report the primary as #2......its a crapshoot and a hodge-podge.....no consistency....(and again, *SOMETIMES* (not very often) they actually match!)
I've seen this problem reported on other forums with MS people saying something like (paraphrasing) "In windows 7, it was never meant that the display number as seen in "screen resolution" should correspond with the device name that is returned from the various function calls".....which I called them out on as being pure BS since this was NEVER the case in XP and Vista. I responded to those threads with the arguement of "well, if that's the case, then how can I (as an application developer) allow my users to specify what info they want on secondary display #1 (and moreover, secondary display #2 if two video cards). Their response was, "well, they can just drag what windows they want into each display"....to which I responded, "I'm NOT PUTTING UP WINDOWS WITH TITLE BARS....I'M filling the whole screen(s) with data....and thus I cannot guarantee that my users can correlate what screen # they see in "screen resolution" with the screen device names returned by the function calls....let alone store their preferences for future runs since these display numbers change on subsequent reboots!"......of course....that thread went without response. Vista and XP were sufficiently OK at correlating 'screen resolution' display numbers with what was being returned to me in the funtion calls....I.E.....what was labeled as '1' or '2' *AT LEAST* corresponded with the device names that were being returned by my function calls (\\.\display1...\\.\display2....\\.\display3)....this is TOTALLY NOT the case in windows 7!!! Check out this thread that went unanswered by MS people....:
http://social.msdn.microsoft.com/Fo...6f8-c7d2fc1afd39?prof=required&lc=1033&ppud=4
How can I retrieve monitor information?
As you can see.....the MS people never responded to my 'calling them out'
Then, on Microsoft connect, I had this little conversation:
https://connect.microsoft.com/Visua...ws-7-getmonitorinfo-returns-wrong-information
As you can see here, there has *apparantly* been an "internal" bug report created in some mysterious place that I cannot track.........ughhhh.............
I just refuse to accept that something so simple cannot be resolved without writing special code to deal with such a simple concept for "windows 7" only when I just want to support a seemingly simple concept across all three OS's (XP, Vista, Windows 7)....it has been very irritating to me.....I hope you can understand my skeptisism and disbelief that such a simple concept should force me to jump through such tremondous hoops to what clearly seems to me as a (seemingly) fixable bug. I am so irritated in that this is delaying a major project from my releasing it (to the public) for what seems to be something trivial to fix by MS........

THANK YOU FOR CONVERSING WITH ME!!!
 
Last edited:

CommonTater

New Member
I feel your pain, partner... believe me.

I'm currently mid-project (i.e. a year in) on something that would have taken me less than 3 months on XP. Because of system hooks and callbacks I'm working in C (not C++) at the Windows API level. The project involves networking, registry access, temp files and several other things Win7 does for crap. It is beyond frustrating to have to continuously vet everything against the UAC and virtualization rules.

The project itself involves multimedia, which means it's going to have to work on XP and probably even 2000 ... Many audiophile and vidiophile users will still (correctly) favour XP for their HTPC systems. But I also know it will get used on Win7 simply because it's there. So I get to cross check every API call for compatibility with previous versions.

Here's one for you... Winsock2 will not take a Unicode (multi-lingual) machine name... There is a function call for it but it's not fully supported on XP and absent from Win2000 so I'm forced to tell my users that if they have problems with server lookups they're going to have to give their SERVERS an english (preferably numerical) machine name... Think that's a selling point in Arabic or Oriental cultures?

Believe me, I know how frustrating these situations get.

If end users saw some of the frustrations a developer faces with Win7, I'm betting the "gush factor" would evaporate very quickly...
 

tuxy42

New Member
Hi pjkdeveloper,
Have you ever tried to use the new CCD API?

Connecting and Configuring Displays Reference (Windows Driver Kit)

they seem to be more accurate because they are designed for windows Vista/7. I think the old ones are (not officially) depreciated. i think you could obtain good results with combination of these methods :

QueryDisplayConfig & DisplayConfigGetDeviceInfo

I have another issue with old functions, not linked to the display number but with "EnumDisplayDevices" which sometimes doesn't return the good DeviceID (DevicePath) . So it's harder to make link between information returned by EnumDisplaySettings (All modes) and use them with the new method "SetDisplayConfig"

Cheers
Nicolas
 

Coriiander

New Member
Hello,

I understand your problem. Yet there is very simply approach that yields just the solution you need. To be honest I'm somewhat suprised you didn't think of it. Here it comes:

Instead of trying to rely on the device id / names / strings, you could rely on relative screen positions. You can easily get a monitor handle (and thus info about it) using the MonitorFromPoint() function from the native Windows API. Personally I always combine the two methods (GetMonitorInfo() and EnumDisplayDevices()) so I can always rely on correct results.

Here is some short snippets, it does not contain exactly what you need but it might give you a start. Note that header files are not included - those should be pretty self explanatory.

PHP:
//======================================================================================================================
//=== Directives                                                                                                     ===
//======================================================================================================================

#define DNA_PRIMARY_DISPLAYMONITOR (HANDLE)0xbaadf00d

PHP:
//======================================================================================================================
//=== Headers                                                                                                        ===
//======================================================================================================================

#include "DNA/config_platform.h"
#if (DNA_OS != DNA_OS_WINDOWS)
#   error Source file incompatible with target operating system.
#else

#include "DNA/Video/CDisplayMonitorManager.h"

#include "DNA/Geometry/Point.h"

#include "DNA/CStringUtils.h"
#include "DNA/Video/CDisplayMonitor.h"

namespace DNA {
namespace Video {

using std::vector;

using DNA::Geometry::Point;
using DNA::Geometry::Rect;

//======================================================================================================================
//=== Global Functions                                                                                               ===
//======================================================================================================================

//-------------------------------------------------------------------------------------------------- MonitorEnumProc ---

BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
    //--------------------------------------------------------------------------------------------------
    // Store enumeration result in the MonitorEnumProcResult vector pointed to by the dwData parameter.
    //--------------------------------------------------------------------------------------------------

    MonitorEnumProcResult result;

    result.Handle        = hMonitor;
    result.DeviceContext = hdcMonitor;
    result.Rect          = *lprcMonitor;

    ((vector<MonitorEnumProcResult>*)dwData)->push_back(result);

    //-----------------------
    // Continue enumerating.
    //-----------------------

    return TRUE;
}

//======================================================================================================================
//=== Static Fields                                                                   CDisplayMonitorManager_Windows ===
//======================================================================================================================

CDisplayMonitorManager_Windows* CDisplayMonitorManager_Windows::_Instance = NULL;

//======================================================================================================================
//=== Construction & Destruction                                                       DisplayMonitorManager_Windows ===
//======================================================================================================================

//-------------------------------------------------------------------------------------------- (Default) Constructor ---

CDisplayMonitorManager_Windows::CDisplayMonitorManager_Windows()
{
    //---------------------------
    // Set the instance pointer.
    //---------------------------

    _Instance = this;

    //---------------------------
    // Set initial field values.
    //---------------------------

    _HasMultiMonitorSupport = FALSE;
    _IsInitialized          = FALSE;
}

//------------------------------------------------------------------------------------------------------- Destructor ---

CDisplayMonitorManager_Windows::~CDisplayMonitorManager_Windows()
{
    //------------------------------------------------------
    // Ensure the display monitor manager is uninitialized.
    //------------------------------------------------------

    if (_IsInitialized)
    {
        Uninitialize();
    }

    //-----------------------------
    // Clear the instance pointer.
    //-----------------------------

    _Instance = NULL;
}

//======================================================================================================================
//=== Methods                                                  DisplayMonitorManager, CDisplayMonitorManager_Windows ===
//======================================================================================================================

//--------------------------------------------------------------------------------------------------- CreateInstance ---

CDisplayMonitorManager_Windows* CDisplayMonitorManager_Windows::CreateInstance()
{
    if (NULL == _Instance)
    {
        new CDisplayMonitorManager_Windows();
    }

    return _Instance;
}

//-------------------------------------------------------------------------------------------------- DestroyInstance ---

void CDisplayMonitorManager_Windows::DestroyInstance()
{
    if (NULL != _Instance)
    {
        delete _Instance;
    }
}

//----------------------------------------------------------------------------------------------- GetMonitorByHandle ---

DisplayMonitor* CDisplayMonitorManager_Windows::GetMonitorByHandle(const void* handle) const 
{
    std::vector<CDisplayMonitor_Windows*>::const_iterator itr_cur = _Monitors.begin();
    std::vector<CDisplayMonitor_Windows*>::const_iterator itr_end = _Monitors.end();
    CDisplayMonitor_Windows* displayMonitor;

    for (itr_cur; itr_cur != itr_end; itr_cur++)
    {
        displayMonitor = *itr_cur;
        
        if (displayMonitor->GetHandle() == handle)
        {
            return displayMonitor;
        }
    }

    return NULL;
}

//------------------------------------------------------------------------------------------------ GetMonitorByIndex ---

DisplayMonitor* CDisplayMonitorManager_Windows::GetMonitorByIndex(const int32 index) const
{
    if ((0 <= index) || ((int32)_Monitors.size() > index))
    {
        return _Monitors[index];
    }

    DNA_THROW(Exception, "Index out of range.", "CDisplayMonitorManager_Windows");
}

//------------------------------------------------------------------------------------------------- GetMonitorByName ---

DisplayMonitor* CDisplayMonitorManager_Windows::GetMonitorByName(const String& name) const
{
    std::vector<CDisplayMonitor_Windows*>::const_iterator itr_cur = _Monitors.begin();
    std::vector<CDisplayMonitor_Windows*>::const_iterator itr_end = _Monitors.end();
    CDisplayMonitor_Windows* displayMonitor;

    for (itr_cur; itr_cur != itr_end; ++itr_cur)
    {
        displayMonitor = *itr_cur;

        if (StringUtils::Equals(name, displayMonitor->GetName(), FALSE))
        {
            return displayMonitor;
        }
    }

    return NULL;
}

//------------------------------------------------------------------------------------------------ GetMonitorByPoint ---

DisplayMonitor* CDisplayMonitorManager_Windows::GetMonitorByPoint(const DNA::Geometry::Point& point) const
{
    if (_HasMultiMonitorSupport)
    {
        HMONITOR hMonitor = MonitorFromPoint(*(POINT*)&point, MONITOR_DEFAULTTONEAREST);
        return GetMonitorByHandle((void*)hMonitor);
    }
    else
    {
        return GetPrimaryMonitor();
    }
}

//------------------------------------------------------------------------------------------------- GetMonitorByRect ---

DisplayMonitor* CDisplayMonitorManager_Windows::GetMonitorByRect(const DNA::Geometry::Rect& rect) const
{
    if (_HasMultiMonitorSupport)
    {
        RECT rc;
        rc.left   = rect.X;
        rc.top    = rect.Y;
        rc.right  = rect.X + rect.Width;
        rc.bottom = rect.Y + rect.Height;

        HMONITOR hMonitor = MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST);
        return GetMonitorByHandle((void*)hMonitor);
    }
    else
    {
        return GetPrimaryMonitor();
    }
}

//----------------------------------------------------------------------------------------------- GetMonitorByWindow ---

DisplayMonitor* CDisplayMonitorManager_Windows::GetMonitorByWindow(const void* windowHandle) const
{
    if (_HasMultiMonitorSupport)
    {
        HMONITOR hMonitor = MonitorFromWindow((HWND)windowHandle, MONITOR_DEFAULTTONEAREST);
        return GetMonitorByHandle((void*)hMonitor);
    }
    else
    {
        return GetPrimaryMonitor();
    }
}

//-------------------------------------------------------------------------------------------------- GetMonitorCount ---

int32 CDisplayMonitorManager_Windows::GetMonitorCount() const
{
    return (int32)_Monitors.size();
}

//------------------------------------------------------------------------------------------------------ GetInstance ---

DisplayMonitorManager* DisplayMonitorManager::GetInstance()
{
    return (DisplayMonitorManager*)CDisplayMonitorManager_Windows::_Instance;
}

//------------------------------------------------------------------------------------------- HasMultiMonitorSupport ---

bool CDisplayMonitorManager_Windows::HasMultiMonitorSupport() const
{
    return _HasMultiMonitorSupport;
}

//------------------------------------------------------------------------------------------------ GetPrimaryMonitor ---

DisplayMonitor* CDisplayMonitorManager_Windows::GetPrimaryMonitor() const
{
    std::vector<CDisplayMonitor_Windows*>::const_iterator itr_cur = _Monitors.begin();
    std::vector<CDisplayMonitor_Windows*>::const_iterator itr_end = _Monitors.end();
    
    CDisplayMonitor_Windows* displayMonitor;

    for (itr_cur; itr_cur != itr_end; ++itr_cur)
    {
        displayMonitor = *itr_cur;
        
        if (displayMonitor->IsPrimary())
        {
            return displayMonitor;
        }
    }

    return NULL;
}

//------------------------------------------------------------------------------------------------------- Initialize ---

void CDisplayMonitorManager_Windows::Initialize()
{
    //---------------------------------------
    // Nothing to do if already initialized.
    //---------------------------------------

    if (_IsInitialized)
    {
        return;
    }

    //------------------------------------------------------
    // Detect whether we have multi-monitor support or not.
    //------------------------------------------------------

    _HasMultiMonitorSupport = (0 != GetSystemMetrics(SM_CMONITORS));

    //-----------------------------------------------------------------------------------------------------------------
    // Get available display monitors. If we have multi-monitor support then we need to enumerate the display monitors
    // that intersect the device context of the entire screen and add them all to our display monitor collection. If 
    // we have no multi-monitor support, or if enumeration didn't return anything, we just add the primary monitor.
    //-----------------------------------------------------------------------------------------------------------------

    if (_HasMultiMonitorSupport)
    {
        //--------------------------------------
        // Get device context for entire sceen.
        //--------------------------------------

        HDC hdc = GetDC(NULL);

        if (NULL == hdc)
        {
            Uninitialize();
            DNA_THROW(Exception, "Could not get device context of entire screen.", "CDisplayMonitorManager_Windows");
        }

        //------------------------------------------------------------------------------------
        // Enumerate display monitors that intersect the device context of the entire screen.
        //------------------------------------------------------------------------------------

        vector<MonitorEnumProcResult> results;

        if (!EnumDisplayMonitors(hdc, NULL, MonitorEnumProc, (LPARAM)&results))
        {
            ReleaseDC(NULL, hdc);
            Uninitialize();
            DNA_THROW(Exception, "Could not enumerate the display monitors.", "CDisplayMonitorManager_Windows");
        }

        //----------------------------------------------------------------------------------------------
        // Create and store a CDisplayMonitor_Windows object for each enumerated display monitor. If no 
        // display monitors were enumerated then we just create and store the primary display monitor.
        //----------------------------------------------------------------------------------------------

        if (0 < results.size())
        {
            vector<MonitorEnumProcResult>::const_iterator itr_cur = results.begin();
            vector<MonitorEnumProcResult>::const_iterator itr_end = results.end();
            const MonitorEnumProcResult* result;
            CDisplayMonitor_Windows* displayMonitor;

            try
            {
                for (itr_cur; itr_cur != itr_end; ++itr_cur)
                {
                    result = &(*itr_cur);
                    displayMonitor = new CDisplayMonitor_Windows(result->Handle, result->DeviceContext);
                    _Monitors.push_back(displayMonitor);
                }
            }
            catch (const Exception&)
            {
                ReleaseDC(NULL, hdc);
                Uninitialize();
                throw;
            }
        }

        //----------------------------------------------
        // Release device context of the entire screen.
        //----------------------------------------------

        ReleaseDC(NULL, hdc);
    }

    //---------------------------------------------------------------------------------------------------------------
    // We have no multi-monitor support or the enumeration didn't return anything. Just add primary display monitor.
    //---------------------------------------------------------------------------------------------------------------

    if (0 == _Monitors.size())
    {
        try
        {
            CDisplayMonitor_Windows* displayMonitor = new CDisplayMonitor_Windows(DNA_PRIMARY_DISPLAYMONITOR, NULL);
            _Monitors.push_back(displayMonitor);
        }
        catch (const Exception&)
        {
            Uninitialize();
            throw;
        }
    }    

    //-------------------------------------------------
    // The display monitor manager is now initialized.
    //-------------------------------------------------

    _IsInitialized = TRUE;
}

//---------------------------------------------------------------------------------------------------- IsInitialized ---

bool CDisplayMonitorManager_Windows::IsInitialized() const
{
    return _IsInitialized;
}

//----------------------------------------------------------------------------------------------------- Uninitialize ---

void CDisplayMonitorManager_Windows::Uninitialize()
{
    //---------------------------------------------------------------------------------------------------------------
    // Destroy all display monitor objects. Luckily we're talking about C++ objects and not the physical devices ;).
    // BOOM BOOM! "We cannot be held responsible for any damage caused to your system."
    //---------------------------------------------------------------------------------------------------------------

    std::vector<CDisplayMonitor_Windows*>::const_iterator itr_cur = _Monitors.begin();
    std::vector<CDisplayMonitor_Windows*>::const_iterator itr_end = _Monitors.end();
    CDisplayMonitor_Windows* displayMonitor;

    for (itr_cur; itr_cur != itr_end; ++itr_cur)
    {
        displayMonitor = *itr_cur;
        
        if (NULL != displayMonitor)
        {
            delete displayMonitor;
        }
    }    

    //------------------
    // Clear the lists.
    //------------------

    _Monitors.clear();

    //---------------
    // Reset fields.
    //---------------

    _HasMultiMonitorSupport = FALSE;

    //---------------------------------------------------
    // The display monitor manager is now uninitialized.
    //---------------------------------------------------

    _IsInitialized = FALSE;
}

} // namespace Video
} // namespace DNA

#endif // (DNA_OS == DNA_OS_WINDOWS)

PHP:
//======================================================================================================================
//=== Headers                                                                                                        ===
//======================================================================================================================

#include "DNA/config_platform.h"
#if (DNA_OS != DNA_OS_WINDOWS)
#   error Source file incompatible with target operating system.
#else

#include "DNA/Video/CDisplayMonitor.h"

#include "DNA/Video/CDisplayMonitorManager.h"

namespace DNA {
namespace Video {

using DNA::Geometry::Rect;

//======================================================================================================================
//=== Construction & Destruction                                                             CDisplayMonitor_Windows ===
//======================================================================================================================

//------------------------------------------------------------------------------------------------------ Constructor ---

CDisplayMonitor_Windows::CDisplayMonitor_Windows(HANDLE handle, HDC deviceContext)
    : _Handle(handle)
{
    //---------------
    // Store handle.
    //---------------

    _Handle = handle;

    //--------------------------
    // Get monitor information.
    //--------------------------

    if ((!CDisplayMonitorManager_Windows::GetInstance()->HasMultiMonitorSupport()) || 
        (DNA_PRIMARY_DISPLAYMONITOR == handle))
    {
        _Name       = "DISPLAY";
        _IsPrimary  = TRUE;

        _Bounds.X      = 0;
        _Bounds.Y      = 0;
        _Bounds.Width  = GetSystemMetrics(SM_CXSCREEN);
        _Bounds.Height = GetSystemMetrics(SM_CYSCREEN); 
        
        RECT rect;
        if (!SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0))
        {
            DNA_THROW(Exception, "Could not retrieve size of working area for the primary display monitor.", 
                "CDisplayMonitor_Windows");
        }
        
        _WorkingArea.X      = rect.left;
        _WorkingArea.Y      = rect.top;
        _WorkingArea.Width  = rect.right  - rect.left;
        _WorkingArea.Height = rect.bottom - rect.top;
    }
    else
    {
        MONITORINFOEX info;
        info.cbSize = sizeof(MONITORINFOEX);
        
        if (!GetMonitorInfo((HMONITOR)_Handle, &info))
        {
            DNA_THROW(Exception, "Could not retrieve display monitor information.", "CDisplayMonitor_Windows");
        }

        _Name               = info.szDevice;
        _IsPrimary          = (MONITORINFOF_PRIMARY == (MONITORINFOF_PRIMARY & info.dwFlags));

        _Bounds.X           = info.rcMonitor.left;
        _Bounds.Y           = info.rcMonitor.top;
        _Bounds.Width       = info.rcMonitor.right  - _Bounds.X;
        _Bounds.Height      = info.rcMonitor.bottom - _Bounds.Y;
        
        _WorkingArea.X      = info.rcWork.left;
        _WorkingArea.Y      = info.rcWork.top;
        _WorkingArea.Width  = info.rcWork.right  - _WorkingArea.X;
        _WorkingArea.Height = info.rcWork.bottom - _WorkingArea.Y;
    }

    //---------------------------------------------------------------------------------------------------------------
    // Get bits per pixel. Number of adjacent color bits for each pixel, multiplied by number of color planes.
    // We need a valid device context to determine this. If none was provided then we create and delete a temporary.
    //---------------------------------------------------------------------------------------------------------------

    _BitsPerPixel = 0;

    if (NULL != deviceContext)
    {
        _BitsPerPixel = GetDeviceCaps(deviceContext, BITSPIXEL) * 
                        GetDeviceCaps(deviceContext, PLANES);
    }

    if (0 == _BitsPerPixel)
    {
        HDC deviceContextTemp = CreateDC(_Name.c_str(), NULL, NULL, NULL);

        _BitsPerPixel = GetDeviceCaps(deviceContextTemp, BITSPIXEL) * 
                        GetDeviceCaps(deviceContextTemp, PLANES);

        DeleteDC(deviceContextTemp);
    }
}

//------------------------------------------------------------------------------------------------------- Destructor ---

CDisplayMonitor_Windows::~CDisplayMonitor_Windows()
{
}

//======================================================================================================================
//=== Methods                                                                                CDisplayMonitor_Windows ===
//======================================================================================================================

//-------------------------------------------------------------------------------------------------- GetBitsPerPixel ---

int32 CDisplayMonitor_Windows::GetBitsPerPixel() const
{
    return _BitsPerPixel;
}

//---------------------------------------------------------------------------------------------------- GetBounds (1) ---

Rect CDisplayMonitor_Windows::GetBounds() const
{
    return _Bounds;
}

//---------------------------------------------------------------------------------------------------- GetBounds (2) ---

void CDisplayMonitor_Windows::GetBounds(Rect* bounds) const
{
    bounds->Set(_Bounds);
}

//-------------------------------------------------------------------------------------------------------- GetHandle ---

void* CDisplayMonitor_Windows::GetHandle() const
{
    return (void*)_Handle;
}

//----------------------------------------------------------------------------------------------- GetWorkingArea (1) ---

Rect CDisplayMonitor_Windows::GetWorkingArea() const
{
    return _WorkingArea;
}

//----------------------------------------------------------------------------------------------- GetWorkingArea (2) ---

void CDisplayMonitor_Windows::GetWorkingArea(Rect* workingArea) const
{
    workingArea->Set(_WorkingArea);
}

//---------------------------------------------------------------------------------------------------------- GetName ---

String CDisplayMonitor_Windows::GetName() const
{
    return _Name;
}

//-------------------------------------------------------------------------------------------------------- IsPrimary ---

bool CDisplayMonitor_Windows::IsPrimary() const
{
    return _IsPrimary;
}

} // namespace Video
} // namespace DNA

#endif // (DNA_OS == DNA_OS_WINDOWS)

PHP:
    //---------------------------------------
    // <<<<<< Not intended for public domain
    //---------------------------------------

    //---------------------------------------------------------------------------------------------------------------
    // Enumerate display adapters that are attached to the desktop. We are not interested in mirroring drivers which
    // are typically used for remoting or other purposes. Netmeeting uses it for example.
    //---------------------------------------------------------------------------------------------------------------

    vector<DISPLAY_DEVICE> adapters;
    int32 adapterCount = 0;
    DWORD devNum = 0;
    DISPLAY_DEVICE displayDevice;

    while (TRUE)
    {
        displayDevice.cb = sizeof(DISPLAY_DEVICE);
        
        if (0 == EnumDisplayDevices(NULL, devNum++, &displayDevice, DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
        {
            break;
        }

        if (DISPLAY_DEVICE_MIRRORING_DRIVER == (DISPLAY_DEVICE_MIRRORING_DRIVER & displayDevice.StateFlags))
        {
            continue;
        }

        adapters.push_back(displayDevice);
        ++adapterCount;
    }

    //--------------------------------------------------------------
    // Enumerate display monitors attached to the display adapters.
    //--------------------------------------------------------------

    int32 monitorCount = 0;
    vector<vector<DISPLAY_DEVICE>> monitors(adapterCount);
    
    for (int32 iAdapter = 0; iAdapter < adapterCount; ++iAdapter)
    {
        devNum = 0;

        while (TRUE)
        {
            displayDevice.cb = sizeof(DISPLAY_DEVICE);
            
            if (0 == EnumDisplayDevices(adapters[iAdapter].DeviceName, devNum++, &displayDevice, 
                DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
            {
                break;
            }

            if ((DISPLAY_DEVICE_MIRRORING_DRIVER    == (DISPLAY_DEVICE_MIRRORING_DRIVER & displayDevice.StateFlags)) ||
                (DISPLAY_DEVICE_ATTACHED_TO_DESKTOP != (DISPLAY_DEVICE_ATTACHED_TO_DESKTOP & displayDevice.StateFlags)))
            {
                continue;
            }

            monitors[iAdapter].push_back(displayDevice);
            ++monitorCount;
        }
    }

    //---------------------------------------------------------------------------------------------------------
    // Enumerate display modes for the display adapters. Note that we are only interested in the display modes 
    // that are indeed compatible with the monitor capabilities.
    //---------------------------------------------------------------------------------------------------------

    DEVMODE devMode;
    int32 modeCount = 0;
    vector<vector<DEVMODE>> modes(adapterCount);

    for (int32 iAdapter = 0; iAdapter < adapterCount; ++iAdapter)
    {
        devNum = 0;

        while (TRUE)
        {
            devMode.dmSize = sizeof(DEVMODE);
            devMode.dmDriverExtra = 0;

            if (0 == EnumDisplaySettingsEx(adapters[iAdapter].DeviceName, devNum++, &devMode, 0))
            {
                break;
            }

            modes[iAdapter].push_back(devMode);
            ++modeCount;
        }
    }

    //---------------------------------------
    // Not intended for public domain >>>>>>
    //---------------------------------------

Good luck on your project,

/|\ Coriiander /|\
 
Last edited:
Top