我有一台通过 HDMI 连接到电视的 HTPC(英特尔 NUC)。电视关闭时可以让 Windows 进入睡眠状态吗?
看来 Windows 确实内置了显示器关闭时的检测功能;也许它为此公开了一个 API?我愿意自己编写解决方案。
答案1
我发现此论坛帖子,其中包含 C++ 代码。我自己还没有尝试过。
您需要一个编译器才能使其工作。
#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 = %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
//------------------------------------------------------------------------------
答案2
HDMI 具有消费电子控制 (CEC)。https://en.wikipedia.org/wiki/Consumer_Electronics_Control#CEC基本上,HDMI 设备(如果它们支持)可以相互通信。例如,如果您使用 HTPC 遥控器,则可以通过 HTPC 的 CEC 关闭显示器或电视。HTPC- 家庭影院电脑。谷歌搜索 HDMI cec,您可能会得到一些想法。