Thread: Monitor State detection

  1. #1
    Registered User
    Join Date
    Jan 2008
    Posts
    42

    Monitor State detection

    Hi,

    i can turn the Monitor( Display ) off and on programaticly with SendMessage and SC_MONITORPOWER. But in some cases, other applications may prevent that.

    My question is : how can i detect the Monitor state( On/Off-Standby ) ? And Can i detect if the system supports Power-Saving features?



    Thanks in advance.

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> how can i detect the Monitor state
    Code:
    #include <windows.h>
    #include <setupapi.h>
    
    #ifdef _MSC_VER
    #pragma comment(lib, "Setupapi.lib")
    #endif
    
    #include <list>
    #include <vector>
    #include <string>
    using namespace std;
    
    // my StlPort configured w/o iostreams at the moment
    #include <stdio.h> 
    
    //------------------------------------------------------------------------------
    
    struct DevData
    {
        std::wstring Description;  // SPDRP_DEVICEDESC
        CM_POWER_DATA PowerData;   // SPDRP_DEVICE_POWER_DATA
    
        DevData() 
        {
            PowerData.PD_Size = sizeof(PowerData);
        }//constructor
    };//DevData
    
    //------------------------------------------------------------------------------
    
    bool GetDeviceRegString(HDEVINFO infoSet, SP_DEVINFO_DATA *pinfoData, 
                            DWORD prop, wstring &val)
    {
        DWORD req_sz = 0;
        BOOL res = SetupDiGetDeviceRegistryPropertyW(infoSet, pinfoData, prop,
                                                     0, 0, 0, &req_sz);
        if (!res && (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
        {
            if (GetLastError() != ERROR_INVALID_DATA)
            {
                printf("SetupDiGetDeviceRegistryPropertyW() failed, le = &#37;u",
                       GetLastError());
            }//if
    
            return false;
        }//if
    
        vector<wchar_t> vec_buff; // in case we have to go to the heap
        wchar_t auto_buff[512];
    
        DWORD buff_sz;
        wchar_t *buff;
        if (req_sz > sizeof(auto_buff))
        {
            vec_buff.reserve(req_sz/2 + 2);
            buff = &vec_buff[0];
            buff_sz = req_sz;
        }//if
        else
        {
            buff = auto_buff;
            buff_sz = sizeof(auto_buff);
        }//else
    
        res = SetupDiGetDeviceRegistryPropertyW(infoSet, pinfoData, prop,
                                                0, (PBYTE)buff, buff_sz, 0);
        if (!res)
        {
            DWORD le = GetLastError();
            if (le != ERROR_INVALID_DATA)
            {
                printf("SetupDiGetDeviceRegistryPropertyW(%d) "
                       "failed, le = %u",
                       prop, le);
                return false;
            }//if
    
            // return empty string on ERROR_INVALID_DATA
            val.erase(val.begin(), val.end());
            return true;
        }//else
    
        val.assign(buff, req_sz);
        return true;
    }//GetDeviceRegString
    
    //------------------------------------------------------------------------------
    
    template <typename T>
    bool GetDeviceRegData(HDEVINFO infoSet, SP_DEVINFO_DATA *pinfoData, 
                            DWORD prop, T &val)
    {
        SetLastError(0);
        BOOL res = SetupDiGetDeviceRegistryPropertyW(infoSet, pinfoData, prop,
                                                     0, (PBYTE)&val, 
                                                     sizeof(val), 0);
        DWORD le = GetLastError();
        if (!res || (le == ERROR_INVALID_DATA))
        {
            if (le != ERROR_INVALID_DATA)
                printf("GetDeviceRegData() failed, le = %u", le);
            return false;
        }//if
    
        return true;
    }//GetDeviceRegData
    
    //------------------------------------------------------------------------------
    
    void ListDeviceClassData(const GUID *classGuid, std::list<DevData> &devList)
    {
        devList.clear();
    
        const DWORD flags = DIGCF_PRESENT;
        HDEVINFO infoSet = SetupDiGetClassDevsW(classGuid, 0, 0, flags);
        if (infoSet == INVALID_HANDLE_VALUE)
        {
            printf("SetupDiGetClassDevs() failed, le = %u", 
                   GetLastError());
            return;
        }//if
    
        SP_DEVINFO_DATA infoData;
        infoData.cbSize = sizeof(SP_DEVINFO_DATA);
    
        DWORD n;
        for (n = 0; SetupDiEnumDeviceInfo(infoSet, n, &infoData); ++n)
        {
            DevData dd;
            if (GetDeviceRegString(infoSet, &infoData, SPDRP_DEVICEDESC, 
                                   dd.Description) &&
                GetDeviceRegData(infoSet, &infoData, SPDRP_DEVICE_POWER_DATA, 
                                 dd.PowerData))
            {
                devList.push_back(dd);
            }//if
        }//for
    
        if (GetLastError() != ERROR_NO_MORE_ITEMS)
        {
            printf("Last call to SetupDiEnumDeviceInfo(%d) failed, le = %u",
                   n, GetLastError());
        }//if
    
        SetupDiDestroyDeviceInfoList(infoSet);
    }//ListDeviceClassData
    
    //------------------------------------------------------------------------------
    
    void print_monitor_info()
    {
        const GUID MonitorClassGuid =
            {0x4d36e96e, 0xe325, 0x11ce, 
                {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
        
        list<DevData> monitors;
        ListDeviceClassData(&MonitorClassGuid, monitors);
    
        printf("# Monitors = %d\n", monitors.size());
    
        list<DevData>::iterator it = monitors.begin(),
                                it_end = monitors.end();
        for (; it != it_end; ++it)
        {
            const char *off_msg = "";
    
            if (it->PowerData.PD_MostRecentPowerState > PowerDeviceD0)
                off_msg = ", *** Sleeping State ***";
    
            printf("[%ls]\n"
                   "   PowerState = %d%s\n", 
                   it->Description.c_str(),
                   it->PowerData.PD_MostRecentPowerState,
                   off_msg);
        }//for
        
        putchar('\n');
    }//print_monitor_info
    
    //------------------------------------------------------------------------------
    
    int main()
    {
        printf("*** Current Status of Monitor(s) ***\n\n");
        print_monitor_info();
    
        printf("*** Turning OFF Monitor(s) ***\n\n");
        fflush(stdout);
        Sleep(500); // don't use mouse or keyboard
        SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)2);
    
        print_monitor_info();
    
        printf("*** Turning ON Monitor(s) ***\n\n");
        SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)-1);
    
        print_monitor_info();
    
        return 0;
    }//main
    
    //------------------------------------------------------------------------------
    >> Can i detect if the system supports Power-Saving features?
    Like what?

    gg

  3. #3
    Registered User
    Join Date
    Jan 2008
    Posts
    42
    Wow .
    Many thanks Codeplug, i appreciate your answer.

    Quote Originally Posted by Codeplug View Post
    >>>> Can i detect if the system supports Power-Saving features?
    >>Like what?

    gg
    Like:
    • Go to standby
    • Wake-Up from standby
    Last edited by patrick22; 05-22-2008 at 03:55 AM.

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Getting power capabilities:
    Code:
    #include <ntstatus.h>  // for STATUS_SUCCESS
    #define WIN32_NO_STATUS
    #include <windows.h>
    #include <powrprof.h>
    
    #pragma comment(lib, "PowrProf.lib")
    
    typedef DWORD NTSTATUS; // from DDK
    
    #include <iostream> // I have iostreams now :)
    using namespace std;
    
    int main()
    {
        SYSTEM_POWER_CAPABILITIES spc = {0};
        NTSTATUS res = CallNtPowerInformation(SystemPowerCapabilities, 0, 0, 
                                              (PVOID)&spc, sizeof(spc));
        if (res != STATUS_SUCCESS)
        {
            cerr << "CallNtPowerInformation() failed, status = "
                 << res << ", le = " << GetLastError() << endl;
            return 1;
        }//if
    
        cout << "SystemS3 = ";
        if (spc.SystemS3 != FALSE)
            cout << "TRUE" << endl;
        else
            cout << "FALSE" << endl;
    
        return 0;
    }//main
    S-states defined: http://msdn.microsoft.com/en-us/library/ms798270.aspx
    SYSTEM_POWER_CAPABILITIES: http://msdn.microsoft.com/en-us/libr...15(VS.85).aspx

    gg

  5. #5
    Registered User
    Join Date
    Apr 2007
    Posts
    137
    Awful code.
    Use the monitor power state api which has been given many times on Usenet (~10 lines of code)

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> Awful code.
    I'm sorry you don't like it. Just for my own self-improvement, would elaborate a bit more? Does it not work for you? Is it just the choice of API's used?

    >> Use the monitor power state api which has been given many times
    That sounds cool - I'm always willing to learn a new API! Could you post a link or something - you know - something useful?

    gg

  7. #7
    Registered User
    Join Date
    Jan 2008
    Posts
    42
    @Codeplug:

    Your code is working great.
    I have 2 more questions:
    1.Where are the display properties stored in Win9x ? Under WinXp they are stored in :
    Code:
    "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\DISPLAY"
    2.Is it possible to detect the monitor state under Win9x ?
    Thanks in advance.


    @Alex31:
    I do not understand you

    If you know the solution, then post it here and do not send me any Private Messages more saying that i can ask on professional win32 newsgroup:

    You can ask on professional win32 api newsgroup :
    news://194.177.96.26/comp.os.ms-wind...ogrammer.win32
    where it has already been discussed
    Last edited by patrick22; 05-23-2008 at 05:50 AM.

  8. #8
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> 1.Where are the display properties stored in Win9x ?
    Event Win2K isn't supported by MS anymore I don't know, but you could the Win32 API for this, with GetSystemMetrics() etc...

    >> 2.Is it possible to detect the monitor state under Win9x ?
    Wish I could help. A "Win9x not supported" comment in your code solves things nicely though

    >> news: ... /comp.os.ms-windows.programmer.win32
    I use Google as my newsgroup reader. Here's the link for comp.os.ms-windows.programmer.win32.

    So if you search just that group with "Monitor Power", Google returns 18 hits. Sadly, no "monitor power state api" was revealed There was actually only one useful posting out of all those hits:
    Quote Originally Posted by jim clark
    You can get this information using the Setup API - You need to enumerate all
    'monitor' devices and find the power state.
    But why limit your search just to that group:
    - microsoft.public.vb.general.discussion

    I'll go ahead and summarize all the other suggestions in the newsgroups that don't work:

    * "It can't be done"
    You'll find a few "[MSFT]", "[MS]", and "[MSMVP]" people making this claim.

    * "Use SPI_GETLOWPOWERACTIVE and/or SPI_GETPOWEROFFACTIVE"
    Doesn't work, I confirmed.

    * "Use Win32_DesktopMonitor WMI object"
    Doesn't work, I confirmed. I even tried Win32_PnPEntity, no go. (ask if you'd like the code). Also confirmed in the newsgroups.

    * "Use the undocumented NtGetDevicePowerState()"
    May work, don't know. But since the documented GetDevicePowerState() says "This function cannot be used to query the power state of a display device." - the I doubt that it's undocumented (assumed) helper-function would work. Similar conclusion reached in newsgroups.


    >> That sounds cool - I'm always willing to learn a new API! Could you post a link or something
    @Alex31> I was giving you a chance to admit your mistake - in the hopes that you would actually search for a link to post - and discover that no such link, and no such API exists.

    Check your facts before posting, especially in one of my subscribed threads.

    gg

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Collision Detection
    By Grantyt3 in forum C++ Programming
    Replies: 3
    Last Post: 09-30-2005, 03:21 PM
  2. matrixes for collision detection
    By DavidP in forum Game Programming
    Replies: 10
    Last Post: 11-09-2002, 10:31 PM
  3. bounding box collision detection
    By DavidP in forum Game Programming
    Replies: 7
    Last Post: 07-07-2002, 11:43 PM
  4. collision detection
    By DavidP in forum Game Programming
    Replies: 2
    Last Post: 05-11-2002, 01:31 PM
  5. Replies: 4
    Last Post: 05-03-2002, 09:40 PM