5

I have a HTPC (Intel NUC) connected to TV via HDMI. Is it possible to put Windows to sleep when the TV is turned off?

It seems that Windows does have built-in detection for when monitor is turned off; maybe it exposes an API for it? I'm OK with having to code the solution myself.

2
  • 1
    Possibly related to stackoverflow.com/questions/203355/… – Kinnectus May 25 '14 at 20:46
  • You could probably do this by running a script in the background that periodically polls WMI to detect whether a monitor is attached. I have seen something similar done in which an AutoIT script was created to periodically poll WMI for a specific USB device's class ID. If the device's class ID was detected as attached, it launched an executable. – SturdyErde Jun 4 '14 at 19:35
1

I found this forum post, which contains C++ code. I didn't try it yet myself.

You need a compiler to make it work.

#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

//------------------------------------------------------------------------------
0

HDMI has Consumer Electronics Control (CEC). https://en.wikipedia.org/wiki/Consumer_Electronics_Control#CEC Basically the HDMI devices (if they support it) can comunicate w/ one another. For example if u use a remote for HTPC a monitor or tv can be turned off via CEC from HTPC. HTPC- home theatre pc. Google HDMI cec and you might get some ideas.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.