Windows 7 Multi Monitor Display numbers are unreliable

Discussion in 'Programming and Scripting' started by pjkdeveloper, Jun 6, 2010.

  1. pjkdeveloper

    pjkdeveloper New Member

    Joined:
    Jun 6, 2010
    Messages:
    6
    Likes Received:
    0
    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......
     
  2. CommonTater

    CommonTater New Member

    Joined:
    Jul 21, 2010
    Messages:
    868
    Likes Received:
    36
    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.
     
    #2 CommonTater, Aug 5, 2010
    Last edited: Aug 5, 2010
  3. pjkdeveloper

    pjkdeveloper New Member

    Joined:
    Jun 6, 2010
    Messages:
    6
    Likes Received:
    0
    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
     
  4. CommonTater

    CommonTater New Member

    Joined:
    Jul 21, 2010
    Messages:
    868
    Likes Received:
    36
    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.

    Download details: Microsoft Windows 7 SDK


    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.
     
  5. pjkdeveloper

    pjkdeveloper New Member

    Joined:
    Jun 6, 2010
    Messages:
    6
    Likes Received:
    0
    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/Forums/en/windowsgeneraldevelopmentissues/thread/668e3cf9-4e00-4b40-a6f8-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/VisualStudio/feedback/details/545217/windows-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!!!
     
    #5 pjkdeveloper, Aug 6, 2010
    Last edited: Aug 6, 2010
  6. CommonTater

    CommonTater New Member

    Joined:
    Jul 21, 2010
    Messages:
    868
    Likes Received:
    36
    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...
     
  7. tuxy42

    tuxy42 New Member

    Joined:
    Aug 17, 2010
    Messages:
    2
    Likes Received:
    0
    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
     
  8. Coriiander

    Coriiander New Member

    Joined:
    Oct 3, 2010
    Messages:
    2
    Likes Received:
    0
    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 hMonitorHDC hdcMonitorLPRECT lprcMonitorLPARAM 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_WindowsCDisplayMonitorManager_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_WindowsCDisplayMonitorManager_Windows::CreateInstance()
    {
        if (
    NULL == _Instance)
        {
            new 
    CDisplayMonitorManager_Windows();
        }

        return 
    _Instance;
    }

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

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

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

    DisplayMonitorCDisplayMonitorManager_Windows::GetMonitorByHandle(const voidhandle) const 
    {
        
    std::vector<CDisplayMonitor_Windows*>::const_iterator itr_cur _Monitors.begin();
        
    std::vector<CDisplayMonitor_Windows*>::const_iterator itr_end _Monitors.end();
        
    CDisplayMonitor_WindowsdisplayMonitor;

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

        return 
    NULL;
    }

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

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

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

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

    DisplayMonitorCDisplayMonitorManager_Windows::GetMonitorByName(const Stringname) const
    {
        
    std::vector<CDisplayMonitor_Windows*>::const_iterator itr_cur _Monitors.begin();
        
    std::vector<CDisplayMonitor_Windows*>::const_iterator itr_end _Monitors.end();
        
    CDisplayMonitor_WindowsdisplayMonitor;

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

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

        return 
    NULL;
    }

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

    DisplayMonitorCDisplayMonitorManager_Windows::GetMonitorByPoint(const DNA::Geometry::Pointpoint) const
    {
        if (
    _HasMultiMonitorSupport)
        {
            
    HMONITOR hMonitor MonitorFromPoint(*(POINT*)&pointMONITOR_DEFAULTTONEAREST);
            return 
    GetMonitorByHandle((void*)hMonitor);
        }
        else
        {
            return 
    GetPrimaryMonitor();
        }
    }

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

    DisplayMonitorCDisplayMonitorManager_Windows::GetMonitorByRect(const DNA::Geometry::Rectrect) const
    {
        if (
    _HasMultiMonitorSupport)
        {
            
    RECT rc;
            
    rc.left   rect.X;
            
    rc.top    rect.Y;
            
    rc.right  rect.rect.Width;
            
    rc.bottom rect.rect.Height;

            
    HMONITOR hMonitor MonitorFromRect(&rcMONITOR_DEFAULTTONEAREST);
            return 
    GetMonitorByHandle((void*)hMonitor);
        }
        else
        {
            return 
    GetPrimaryMonitor();
        }
    }

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

    DisplayMonitorCDisplayMonitorManager_Windows::GetMonitorByWindow(const voidwindowHandle) const
    {
        if (
    _HasMultiMonitorSupport)
        {
            
    HMONITOR hMonitor MonitorFromWindow((HWND)windowHandleMONITOR_DEFAULTTONEAREST);
            return 
    GetMonitorByHandle((void*)hMonitor);
        }
        else
        {
            return 
    GetPrimaryMonitor();
        }
    }

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

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

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

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

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

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

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

    DisplayMonitorCDisplayMonitorManager_Windows::GetPrimaryMonitor() const
    {
        
    std::vector<CDisplayMonitor_Windows*>::const_iterator itr_cur _Monitors.begin();
        
    std::vector<CDisplayMonitor_Windows*>::const_iterator itr_end _Monitors.end();
        
        
    CDisplayMonitor_WindowsdisplayMonitor;

        for (
    itr_curitr_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 = (!= 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<MonitorEnumProcResultresults;

            if (!
    EnumDisplayMonitors(hdcNULLMonitorEnumProc, (LPARAM)&results))
            {
                
    ReleaseDC(NULLhdc);
                
    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 (results.size())
            {
                
    vector<MonitorEnumProcResult>::const_iterator itr_cur results.begin();
                
    vector<MonitorEnumProcResult>::const_iterator itr_end results.end();
                const 
    MonitorEnumProcResultresult;
                
    CDisplayMonitor_WindowsdisplayMonitor;

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

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

            
    ReleaseDC(NULLhdc);
        }

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

        
    if (== _Monitors.size())
        {
            try
            {
                
    CDisplayMonitor_WindowsdisplayMonitor = new CDisplayMonitor_Windows(DNA_PRIMARY_DISPLAYMONITORNULL);
                
    _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_WindowsdisplayMonitor;

        for (
    itr_curitr_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 handleHDC 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_GETWORKAREA0, &rect0))
            {
                
    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(deviceContextBITSPIXEL) * 
                            
    GetDeviceCaps(deviceContextPLANES);
        }

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

            
    _BitsPerPixel GetDeviceCaps(deviceContextTempBITSPIXEL) * 
                            
    GetDeviceCaps(deviceContextTempPLANES);

            
    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(Rectbounds) const
    {
        
    bounds->Set(_Bounds);
    }

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

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

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

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

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

    void CDisplayMonitor_Windows::GetWorkingArea(RectworkingArea) 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_DEVICEadapters;
        
    int32 adapterCount 0;
        
    DWORD devNum 0;
        
    DISPLAY_DEVICE displayDevice;

        while (
    TRUE)
        {
            
    displayDevice.cb sizeof(DISPLAY_DEVICE);
            
            if (
    == EnumDisplayDevices(NULLdevNum++, &displayDeviceDISPLAY_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 0iAdapter adapterCount; ++iAdapter)
        {
            
    devNum 0;

            while (
    TRUE)
            {
                
    displayDevice.cb sizeof(DISPLAY_DEVICE);
                
                if (
    == EnumDisplayDevices(adapters[iAdapter].DeviceNamedevNum++, &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 0iAdapter adapterCount; ++iAdapter)
        {
            
    devNum 0;

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

                if (
    == EnumDisplaySettingsEx(adapters[iAdapter].DeviceNamedevNum++, &devMode0))
                {
                    break;
                }

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

        
    //---------------------------------------
        // Not intended for public domain >>>>>>
        //---------------------------------------
    Good luck on your project,

    /|\ Coriiander /|\
     
    #8 Coriiander, Oct 3, 2010
    Last edited: Oct 3, 2010

Share This Page

Loading...