官方api
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumdisplaymonitors
https ://blog.youkuaiyun.com/zgl7903/article/details/80925285
https://learn.microsoft.com/zh-cn/windows-hardware/drivers/display/hardware-flip-queue
https://learn.microsoft.com/zh-cn/windows-hardware/test/wpt/
#include <filesystem>
#include <mutex>
#include <sstream>
#include "device_master_interface.h"
#include "dof_data_type.h"
#include "sensor_raw_types.h"
#include "tracker3dof_api.h"
#include <windows.h>
#include <powrprof.h>
#include <lowlevelmonitorconfigurationapi.h>
#include <physicalmonitorenumerationapi.h>
#include <iostream>
#include <vector>
#include <atlstr.h>
#include <string>
#pragma comment(lib, "Dxva2.lib")
#pragma comment(lib, "User32.lib")
// 定义必要的常量
#ifndef CDS_OFF
#define CDS_OFF 0x00000040
#endif
class MonitorPowerMonitor {
public:
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
if (msg == WM_POWERBROADCAST) {
switch (wParam) {
case PBT_APMPOWERSTATUSCHANGE: {
int a;
std::cout << "aaa" << std::endl;
break;
}
case PBT_APMRESUMEAUTOMATIC: {
int a;
std::cout << "bbbb" << std::endl;
break;
}
default:
break;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
public:
void StartMonitoring() {
// 创建隐藏窗口用于接收消息
WNDCLASS wc = {};
wc.lpfnWndProc = WndProc;
wc.hInstance = GetModuleHandle(nullptr);
wc.lpszClassName = "MonitorPowerMonitor";
RegisterClass(&wc);
HWND hwnd = CreateWindow(wc.lpszClassName, "", 0, 0, 0, 0, 0, nullptr, nullptr, wc.hInstance, nullptr);
std::cout << "StartMonitoring " << std::endl;
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
static void ControlMonitor(int command) {
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, command);
}
};
void GetScreenInfo(HDC hdc) {
//HDC hdc = GetDC(NULL); // 获取屏幕的DC
int width = GetDeviceCaps(hdc, HORZRES); // 获取水平分辨率
int height = GetDeviceCaps(hdc, VERTRES); // 获取垂直分辨率
int colorDepth = GetDeviceCaps(hdc, BITSPIXEL); // 获取颜色深度(位数)
//ReleaseDC(NULL, hdc); // 释放DC
std::cout << "Width: " << width << std::endl;
std::cout << "Height: " << height << std::endl;
std::cout << "Color Depth: " << colorDepth << std::endl;
DISPLAY_DEVICE lpDisplayDevice;
ZeroMemory(&lpDisplayDevice, sizeof(DISPLAY_DEVICE));
lpDisplayDevice.cb = sizeof(DISPLAY_DEVICE);
//lpDisplayDevice.StateFlags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP;
DWORD iDevNum = 0;
TCHAR adapterDevice[32];
for (iDevNum = 0; EnumDisplayDevices(NULL, iDevNum, &lpDisplayDevice, 0); iDevNum++)
{
std::cout << "--------iDevNum-------" << iDevNum << std::endl;
//mylog << "cb\t:" << lpDisplayDevice.cb << endl;
//mylog << "DeviceID\t:" << lpDisplayDevice.DeviceID << endl; //not used
//mylog << "DeviceKey\t:" << lpDisplayDevice.DeviceKey << endl; //reserved
std::cout << "DeviceName\t:" << (lpDisplayDevice.DeviceName) << std::endl;
std::cout << "DeviceString\t:" << (lpDisplayDevice.DeviceString) << std::endl;
std::cout << "StateFlags\t:" << int(lpDisplayDevice.StateFlags) << std::endl;
if ((DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE) == lpDisplayDevice.StateFlags)
{
std::cout << "DISPLAY_DEVICE_ATTACHED_TO_DESKTOP & DISPLAY_DEVICE_PRIMARY_DEVICE" << std::endl;
}
if (DISPLAY_DEVICE_PRIMARY_DEVICE == lpDisplayDevice.StateFlags)
{
std::cout << "DISPLAY_DEVICE_PRIMARY_DEVICE" << std::endl;
}
if (DISPLAY_DEVICE_ATTACHED_TO_DESKTOP == lpDisplayDevice.StateFlags)
{
std::cout << "DISPLAY_DEVICE_ATTACHED_TO_DESKTOP" << std::endl;
}
/* Get monitor name via adaptername; please refer to: https://msdn.microsoft.com/en-us/library/dd162609(v=vs.85).aspx */
memcpy(adapterDevice, lpDisplayDevice.DeviceName, sizeof(lpDisplayDevice.DeviceName));
ZeroMemory(&lpDisplayDevice, sizeof(DISPLAY_DEVICE));
lpDisplayDevice.cb = sizeof(DISPLAY_DEVICE);
EnumDisplayDevices(adapterDevice, 0, &lpDisplayDevice, 0);
std::cout << "monitor name \t:" << (lpDisplayDevice.DeviceName) << std::endl;
std::cout << "monitor type\t:" << (lpDisplayDevice.DeviceString) << std::endl;
//clear DISPLAY_DEVICE and goto the next loop
ZeroMemory(&lpDisplayDevice, sizeof(DISPLAY_DEVICE));
lpDisplayDevice.cb = sizeof(DISPLAY_DEVICE);
}
//DEVMODE dm;
//ZeroMemory(&dm, sizeof(DEVMODE));
//dm.dmSize = sizeof(DEVMODE);
//for (int i = 0; EnumDisplaySettings(NULL, i, &dm); i++) {
// printf("%d: %dx%d @ %dbpp @ %dHz\n",
// i, dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency);
//}
}
class CMultiMonitorEnumerator
{
public:
int m_iMontorNumber;
typedef struct _tagVMonitorInfo_t
{
HMONITOR hMonitor; //显示器句柄
TCHAR szDevice[32]; //显示器名
RECT rcVirtual; //虚拟显示屏坐标
RECT rcMonitor; //物理显示坐标
RECT rcWork; //工作显示坐标
BOOL bPrimary; //主显示器?
_tagVMonitorInfo_t()
{
memset(this, 0, sizeof(*this));
}
}VMONITORINFO, * LPVMONITORINFO;
//显示器信息列表
VMONITORINFO m_MonitorInfoExArray[64];
protected:
//枚举显示器回调函数
static BOOL CALLBACK MonitorEnumProc(
HMONITOR hMonitor, // handle to display monitor
HDC hdcMonitor, // handle to monitor-appropriate device context
LPRECT lprcMonitor, // pointer to monitor intersection rectangle
LPARAM dwData // data passed from EnumDisplayMonitors
)
{
CMultiMonitorEnumerator* pThis = (CMultiMonitorEnumerator*)dwData;
GetScreenInfo(hdcMonitor);
//The rectangle coordinates are virtual-screen coordinates
if (lprcMonitor)
{
printf("MonitorEnumProc 1:%p (l=%d t=%d r=%d b=%d)(w=%d h=%d)\n",
hMonitor, lprcMonitor->left, lprcMonitor->top, lprcMonitor->right, lprcMonitor->bottom,
lprcMonitor->right - lprcMonitor->left, lprcMonitor->bottom - lprcMonitor->top);
}
//GetMonitorInfo 获取显示器信息
MONITORINFOEX infoEx;
memset(&infoEx, 0, sizeof(infoEx));
infoEx.cbSize = sizeof(infoEx);
if (GetMonitorInfo(hMonitor, &infoEx))
{
printf(("MonitorEnumProc 2:%p [%s] %s rcMonitor(l=%d t=%d r=%d b=%d)(w=%d h=%d) rcWork(l=%d t=%d r=%d b=%d)(w=%d h=%d)\n"),
hMonitor,
infoEx.szDevice,
infoEx.dwFlags == MONITORINFOF_PRIMARY ? ("Primary") : ("Slave"),
infoEx.rcMonitor.left, infoEx.rcMonitor.top, infoEx.rcMonitor.right, infoEx.rcMonitor.bottom,
infoEx.rcMonitor.right - infoEx.rcMonitor.left, infoEx.rcMonitor.bottom - infoEx.rcMonitor.top,
infoEx.rcWork.left, infoEx.rcWork.top, infoEx.rcWork.right, infoEx.rcWork.bottom,
infoEx.rcWork.right - infoEx.rcWork.left, infoEx.rcWork.bottom - infoEx.rcWork.top);
}
//保存显示器信息
if (pThis->m_iMontorNumber < _countof(pThis->m_MonitorInfoExArray) - 1)
{
VMONITORINFO* pInfo = &pThis->m_MonitorInfoExArray[pThis->m_iMontorNumber];
pInfo->hMonitor = hMonitor;
if (lprcMonitor)
{
pInfo->rcVirtual = *lprcMonitor;
}
pInfo->rcMonitor = infoEx.rcMonitor;
pInfo->rcWork = infoEx.rcWork;
pInfo->bPrimary = infoEx.dwFlags == MONITORINFOF_PRIMARY;
strcpy(pInfo->szDevice, infoEx.szDevice);
pThis->m_iMontorNumber++;
return TRUE; //continue the enumeration
}
return FALSE; //stop the enumeration
}
public:
CMultiMonitorEnumerator()
{
m_iMontorNumber = 0;
EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)this);
}
};
class DisplayPowerMonitor {
private:
HPOWERNOTIFY hPowerNotify;
HWND hWnd;
public:
DisplayPowerMonitor(HWND window) : hWnd(window), hPowerNotify(nullptr) {}
bool StartMonitoring() {
// Register for console display state notifications
hPowerNotify = RegisterPowerSettingNotification(
hWnd,
&GUID_CONSOLE_DISPLAY_STATE,
DEVICE_NOTIFY_WINDOW_HANDLE
);
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (hPowerNotify != nullptr);
}
void StopMonitoring() {
if (hPowerNotify) {
UnregisterPowerSettingNotification(hPowerNotify);
hPowerNotify = nullptr;
}
}
static std::string GetDisplayStateString(DWORD state) {
switch (state) {
case 0: return "Display Off";
case 1: return "Display On";
case 2: return "Display Dimmed";
default: return "Unknown State";
}
}
static LRESULT HandlePowerBroadcast(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (uMsg == WM_POWERBROADCAST && wParam == PBT_POWERSETTINGCHANGE) {
auto* setting = reinterpret_cast<POWERBROADCAST_SETTING*>(lParam);
if (IsEqualGUID(setting->PowerSetting, GUID_CONSOLE_DISPLAY_STATE)) {
DWORD displayState = *reinterpret_cast<DWORD*>(&setting->Data);
std::string stateStr = GetDisplayStateString(displayState);
std::cout << "Display state changed: " << stateStr << std::endl;
// Perform actions based on display state
switch (displayState) {
case 0: // Display Off
OnDisplayOff();
break;
case 1: // Display On
OnDisplayOn();
break;
case 2: // Display Dimmed
OnDisplayDimmed();
break;
}
}
}
PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = ("Hello,");
switch (uMsg)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
TextOut(hdc,
5, 5,
greeting, strlen(greeting));
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
private:
static void OnDisplayOff() {
std::cout << "Performing cleanup for display off..." << std::endl;
// Pause rendering, stop videos, etc.
}
static void OnDisplayOn() {
std::cout << "Resuming operations for display on..." << std::endl;
// Resume rendering, restart videos, etc.
}
static void OnDisplayDimmed() {
std::cout << "Display dimmed - reducing activity..." << std::endl;
// Reduce CPU/GPU usage
}
};
std::string toUtf8(wchar_t* buffer)
{
CW2A utf8(buffer, CP_UTF8);
const char* data = utf8.m_psz;
return std::string{ data };
}
class MultiMonitorController {
private:
struct PhysicalMonitor {
HANDLE hPhysicalMonitor;
DWORD index;
wchar_t description[128];
};
std::vector<PhysicalMonitor> physicalMonitors;
public:
bool Initialize() {
// 获取显示器数量
DWORD monitorCount;
HMONITOR hMonitor = NULL;
HDC hdc = GetDC(NULL);
monitorCount = GetSystemMetrics(SM_CMONITORS);
ReleaseDC(NULL, hdc);
// 枚举物理显示器
for (DWORD i = 0; i < monitorCount; i++) {
DISPLAY_DEVICE displayDevice = { 0 };
displayDevice.cb = sizeof(DISPLAY_DEVICE);
if (EnumDisplayDevices(NULL, i, &displayDevice, 0)) {
if (displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE) {
// 获取物理显示器句柄
HMONITOR hMonitor = MonitorFromPoint(POINT{ 0,0 }, MONITOR_DEFAULTTOPRIMARY);
if (hMonitor) {
DWORD physicalCount;
LPPHYSICAL_MONITOR physicalMonitors = NULL;
if (GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, &physicalCount)) {
physicalMonitors = new PHYSICAL_MONITOR[physicalCount];
if (GetPhysicalMonitorsFromHMONITOR(hMonitor, physicalCount, physicalMonitors)) {
for (DWORD j = 0; j < physicalCount; j++) {
PhysicalMonitor pm;
pm.hPhysicalMonitor = physicalMonitors[j].hPhysicalMonitor;
wprintf(L"ssssssssssssssssssssss i=%ul j=%ul == description%ls\n", i, j, toUtf8(pm.description));
pm.index = i;
wcscpy_s(pm.description, physicalMonitors[j].szPhysicalMonitorDescription);
this->physicalMonitors.push_back(pm);
}
}
delete[] physicalMonitors;
}
}
}
}
}
return !physicalMonitors.empty();
}
// 关闭指定显示器
bool TurnOffMonitor(int monitorIndex) {
for (const auto& monitor : physicalMonitors) {
if (monitor.index == monitorIndex) {
printf("TurnOffMonitorTurnOffMonitorTurnOffMonitorTurnOffMonitor index=%ul\n", monitor.index);
// 使用DDC/CI命令关闭显示器
return SetVCPFeature(monitor.hPhysicalMonitor, 0xD6, 0x04) == TRUE;
}
}
return false;
}
// 开启指定显示器
bool TurnOnMonitor(int monitorIndex) {
for (const auto& monitor : physicalMonitors) {
if (monitor.index == monitorIndex) {
// 使用DDC/CI命令开启显示器
return SetVCPFeature(monitor.hPhysicalMonitor, 0xD6, 0x01) == TRUE;
}
}
return false;
}
// 设置显示器电源状态 (0x01=开, 0x04=关, 0x05=待机)
bool SetMonitorPowerState(int monitorIndex, BYTE powerState) {
for (const auto& monitor : physicalMonitors) {
if (monitor.index == monitorIndex) {
printf("SetMonitorPowerStateSetMonitorPowerStateSetMonitorPowerState index=%ul\n", monitor.index);
return SetVCPFeature(monitor.hPhysicalMonitor, 0xD6, powerState) == TRUE;
}
}
return false;
}
~MultiMonitorController() {
// 清理资源
for (const auto& monitor : physicalMonitors) {
DestroyPhysicalMonitor(monitor.hPhysicalMonitor);
}
}
};
class ServicePowerMonitor {
private:
HPOWERNOTIFY hPowerNotify;
HANDLE hService;
public:
ServicePowerMonitor() : hService(GetCurrentProcess()), hPowerNotify(nullptr) {}
bool StartServiceMonitoring() {
hPowerNotify = RegisterPowerSettingNotification(
hService,
&GUID_CONSOLE_DISPLAY_STATE,
DEVICE_NOTIFY_SERVICE_HANDLE
);
if (!hPowerNotify) {
std::cerr << "Failed to register power notification: " << GetLastError() << std::endl;
return false;
}
std::cout << "Service registered for display power notifications" << std::endl;
return true;
}
void StopMonitoring() {
if (hPowerNotify) {
UnregisterPowerSettingNotification(hPowerNotify);
hPowerNotify = nullptr;
}
}
void HandleServiceControl(DWORD dwControl) {
if (dwControl == SERVICE_CONTROL_POWEREVENT) {
// Handle power events in service context
std::cout << "Power event received by service" << std::endl;
}
}
};
// 简化版本的多显示器控制器
class SimpleMultiMonitorController {
private:
struct MonitorInfo {
int index;
std::string name;
std::string description;
bool isPrimary;
};
std::vector<MonitorInfo> monitors;
public:
bool Initialize() {
monitors.clear();
DISPLAY_DEVICE displayDevice;
displayDevice.cb = sizeof(DISPLAY_DEVICE);
for (DWORD i = 0; EnumDisplayDevices(NULL, i, &displayDevice, 0); i++) {
if (displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) {
MonitorInfo info;
info.index = i;
info.name = displayDevice.DeviceName;
info.description = displayDevice.DeviceString;
info.isPrimary = (displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) != 0;
monitors.push_back(info);
}
}
return !monitors.empty();
}
// 方法1:使用显示设置API关闭指定显示器(推荐)
bool TurnOffMonitor(int monitorIndex) {
DISPLAY_DEVICE displayDevice;
displayDevice.cb = sizeof(DISPLAY_DEVICE);
for (DWORD i = 0; EnumDisplayDevices(NULL, i, &displayDevice, 0); i++) {
if (i == monitorIndex && (displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) {
DEVMODE devMode = { 0 };
devMode.dmSize = sizeof(DEVMODE);
devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
devMode.dmPelsWidth = 0;
devMode.dmPelsHeight = 0;
printf("TurnOffMonitor TurnOffMonitor 88888888888888888888 monitorIndex=%d displayDevice.DeviceName=%s\n",
monitorIndex, displayDevice.DeviceName);
// 禁用显示器
LONG result = ChangeDisplaySettingsEx(displayDevice.DeviceName,
&devMode,
NULL,
CDS_UPDATEREGISTRY | CDS_NORESET | CDS_OFF,
NULL);
if (result == DISP_CHANGE_SUCCESSFUL) {
// 应用更改
result = ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
return result == DISP_CHANGE_SUCCESSFUL;
}
}
}
return false;
}
// 方法2:使用简单的显示器禁用/启用
bool DisableMonitor(int monitorIndex) {
DISPLAY_DEVICE displayDevice;
displayDevice.cb = sizeof(DISPLAY_DEVICE);
for (DWORD i = 0; EnumDisplayDevices(NULL, i, &displayDevice, 0); i++) {
if (i == monitorIndex) {
DEVMODE devMode = { 0 };
devMode.dmSize = sizeof(DEVMODE);
printf("DisableMonitorDisableMonitorDisableMonitorDisableMonitor monitorIndex=%d displayDevice.DeviceName=%s\n",
monitorIndex, displayDevice.DeviceName);
// 设置为禁用状态
return ChangeDisplaySettingsEx(displayDevice.DeviceName,
NULL, NULL,
CDS_UPDATEREGISTRY | CDS_NORESET | CDS_OFF,
NULL) == DISP_CHANGE_SUCCESSFUL;
}
}
return false;
}
bool EnableMonitor(int monitorIndex) {
DISPLAY_DEVICE displayDevice;
displayDevice.cb = sizeof(DISPLAY_DEVICE);
for (DWORD i = 0; EnumDisplayDevices(NULL, i, &displayDevice, 0); i++) {
if (i == monitorIndex) {
// 恢复到默认设置
return ChangeDisplaySettingsEx(displayDevice.DeviceName,
NULL, NULL, 0, NULL) == DISP_CHANGE_SUCCESSFUL;
}
}
return false;
}
// 方法3:使用电源管理API(如果支持)
bool SetMonitorPowerState(int monitorIndex, bool turnOn) {
// 发送电源管理消息
if (turnOn) {
// 开启屏幕
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)-1);
}
else {
// 关闭屏幕(需要先激活屏幕)
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)2);
}
return true;
}
std::vector<MonitorInfo> GetMonitorList() const {
return monitors;
}
void PrintMonitorInfo() {
std::cout << "检测到的显示器:" << std::endl;
for (const auto& monitor : monitors) {
std::cout << "显示器 " << monitor.index << ": "
<< monitor.description
<< (monitor.isPrimary ? " (主显示器)" : "")
<< std::endl;
}
}
};
// 替代方案:使用更简单的API
class SimpleScreenController {
public:
// 关闭所有屏幕(最简单的方法)
static void TurnOffAllScreens() {
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)2);
}
// 开启所有屏幕
static void TurnOnAllScreens() {
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)-1);
}
// 防止屏幕关闭
static void PreventScreenOff() {
SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_CONTINUOUS);
}
// 允许屏幕关闭
static void AllowScreenOff() {
SetThreadExecutionState(ES_CONTINUOUS);
}
};
CMultiMonitorEnumerator mMultDisplayEnum;
HDC hdc = GetDC(NULL); // 获取屏幕的DC
GetScreenInfo(hdc);
ReleaseDC(NULL, hdc); // 释放DC
//MonitorPowerMonitor monitor;
//monitor.StartMonitoring();
WNDCLASS wc = {};
//wc.lpfnWndProc = MonitorPowerMonitor::WndProc;
wc.lpfnWndProc = DisplayPowerMonitor::HandlePowerBroadcast;
wc.hInstance = GetModuleHandle(nullptr);
wc.lpszClassName = "MonitorPowerMonitor";
RegisterClass(&wc);
HWND hwnd = CreateWindow(wc.lpszClassName, "3dof", 0, 0, 0, 800, 600, nullptr, nullptr, wc.hInstance, nullptr);
//ShowWindow(hwnd, SW_SHOW);
//MoveWindow(hwnd, 2880, 0, 800, 600, false);
std::this_thread::sleep_for(std::chrono::seconds(1));
MultiMonitorController mc;
mc.Initialize();
//mc.TurnOffMonitor(1);
//mc.SetMonitorPowerState(0, 4);
SimpleMultiMonitorController controller;
controller.Initialize();
//controller.TurnOffMonitor(0);
controller.DisableMonitor(0);
#include <filesystem>
#include <mutex>
#include <sstream>
#include "device_master_interface.h"
#include "dof_data_type.h"
#include "sensor_raw_types.h"
#include "tracker3dof_api.h"
#include <windows.h>
#include <powrprof.h>
#include <lowlevelmonitorconfigurationapi.h>
#include <physicalmonitorenumerationapi.h>
#include <iostream>
#include <vector>
#include <atlstr.h>
#include <string>
#pragma comment(lib, "Dxva2.lib")
#pragma comment(lib, "User32.lib")
// 定义必要的常量
#ifndef CDS_OFF
#define CDS_OFF 0x00000040
#endif
class MonitorPowerMonitor {
public:
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
if (msg == WM_POWERBROADCAST) {
switch (wParam) {
case PBT_APMPOWERSTATUSCHANGE: {
int a;
std::cout << "aaa" << std::endl;
break;
}
case PBT_APMRESUMEAUTOMATIC: {
int a;
std::cout << "bbbb" << std::endl;
break;
}
default:
break;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
public:
void StartMonitoring() {
// 创建隐藏窗口用于接收消息
WNDCLASS wc = {};
wc.lpfnWndProc = WndProc;
wc.hInstance = GetModuleHandle(nullptr);
wc.lpszClassName = "MonitorPowerMonitor";
RegisterClass(&wc);
HWND hwnd = CreateWindow(wc.lpszClassName, "", 0, 0, 0, 0, 0, nullptr, nullptr, wc.hInstance, nullptr);
std::cout << "StartMonitoring " << std::endl;
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
static void ControlMonitor(int command) {
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, command);
}
};
void GetScreenInfo(HDC hdc) {
//HDC hdc = GetDC(NULL); // 获取屏幕的DC
int width = GetDeviceCaps(hdc, HORZRES); // 获取水平分辨率
int height = GetDeviceCaps(hdc, VERTRES); // 获取垂直分辨率
int colorDepth = GetDeviceCaps(hdc, BITSPIXEL); // 获取颜色深度(位数)
//ReleaseDC(NULL, hdc); // 释放DC
std::cout << "Width: " << width << std::endl;
std::cout << "Height: " << height << std::endl;
std::cout << "Color Depth: " << colorDepth << std::endl;
DISPLAY_DEVICE lpDisplayDevice;
ZeroMemory(&lpDisplayDevice, sizeof(DISPLAY_DEVICE));
lpDisplayDevice.cb = sizeof(DISPLAY_DEVICE);
//lpDisplayDevice.StateFlags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP;
DWORD iDevNum = 0;
TCHAR adapterDevice[32];
for (iDevNum = 0; EnumDisplayDevices(NULL, iDevNum, &lpDisplayDevice, 0); iDevNum++)
{
std::cout << "--------iDevNum-------" << iDevNum << std::endl;
//mylog << "cb\t:" << lpDisplayDevice.cb << endl;
//mylog << "DeviceID\t:" << lpDisplayDevice.DeviceID << endl; //not used
//mylog << "DeviceKey\t:" << lpDisplayDevice.DeviceKey << endl; //reserved
std::cout << "DeviceName\t:" << (lpDisplayDevice.DeviceName) << std::endl;
std::cout << "DeviceString\t:" << (lpDisplayDevice.DeviceString) << std::endl;
std::cout << "StateFlags\t:" << int(lpDisplayDevice.StateFlags) << std::endl;
if ((DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE) == lpDisplayDevice.StateFlags)
{
std::cout << "DISPLAY_DEVICE_ATTACHED_TO_DESKTOP & DISPLAY_DEVICE_PRIMARY_DEVICE" << std::endl;
}
if (DISPLAY_DEVICE_PRIMARY_DEVICE == lpDisplayDevice.StateFlags)
{
std::cout << "DISPLAY_DEVICE_PRIMARY_DEVICE" << std::endl;
}
if (DISPLAY_DEVICE_ATTACHED_TO_DESKTOP == lpDisplayDevice.StateFlags)
{
std::cout << "DISPLAY_DEVICE_ATTACHED_TO_DESKTOP" << std::endl;
}
/* Get monitor name via adaptername; please refer to: https://msdn.microsoft.com/en-us/library/dd162609(v=vs.85).aspx */
memcpy(adapterDevice, lpDisplayDevice.DeviceName, sizeof(lpDisplayDevice.DeviceName));
ZeroMemory(&lpDisplayDevice, sizeof(DISPLAY_DEVICE));
lpDisplayDevice.cb = sizeof(DISPLAY_DEVICE);
EnumDisplayDevices(adapterDevice, 0, &lpDisplayDevice, 0);
std::cout << "monitor name \t:" << (lpDisplayDevice.DeviceName) << std::endl;
std::cout << "monitor type\t:" << (lpDisplayDevice.DeviceString) << std::endl;
//clear DISPLAY_DEVICE and goto the next loop
ZeroMemory(&lpDisplayDevice, sizeof(DISPLAY_DEVICE));
lpDisplayDevice.cb = sizeof(DISPLAY_DEVICE);
}
//DEVMODE dm;
//ZeroMemory(&dm, sizeof(DEVMODE));
//dm.dmSize = sizeof(DEVMODE);
//for (int i = 0; EnumDisplaySettings(NULL, i, &dm); i++) {
// printf("%d: %dx%d @ %dbpp @ %dHz\n",
// i, dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency);
//}
}
class CMultiMonitorEnumerator
{
public:
int m_iMontorNumber;
typedef struct _tagVMonitorInfo_t
{
HMONITOR hMonitor; //显示器句柄
TCHAR szDevice[32]; //显示器名
RECT rcVirtual; //虚拟显示屏坐标
RECT rcMonitor; //物理显示坐标
RECT rcWork; //工作显示坐标
BOOL bPrimary; //主显示器?
_tagVMonitorInfo_t()
{
memset(this, 0, sizeof(*this));
}
}VMONITORINFO, * LPVMONITORINFO;
//显示器信息列表
VMONITORINFO m_MonitorInfoExArray[64];
protected:
//枚举显示器回调函数
static BOOL CALLBACK MonitorEnumProc(
HMONITOR hMonitor, // handle to display monitor
HDC hdcMonitor, // handle to monitor-appropriate device context
LPRECT lprcMonitor, // pointer to monitor intersection rectangle
LPARAM dwData // data passed from EnumDisplayMonitors
)
{
CMultiMonitorEnumerator* pThis = (CMultiMonitorEnumerator*)dwData;
GetScreenInfo(hdcMonitor);
//The rectangle coordinates are virtual-screen coordinates
if (lprcMonitor)
{
printf("MonitorEnumProc 1:%p (l=%d t=%d r=%d b=%d)(w=%d h=%d)\n",
hMonitor, lprcMonitor->left, lprcMonitor->top, lprcMonitor->right, lprcMonitor->bottom,
lprcMonitor->right - lprcMonitor->left, lprcMonitor->bottom - lprcMonitor->top);
}
//GetMonitorInfo 获取显示器信息
MONITORINFOEX infoEx;
memset(&infoEx, 0, sizeof(infoEx));
infoEx.cbSize = sizeof(infoEx);
if (GetMonitorInfo(hMonitor, &infoEx))
{
printf(("MonitorEnumProc 2:%p [%s] %s rcMonitor(l=%d t=%d r=%d b=%d)(w=%d h=%d) rcWork(l=%d t=%d r=%d b=%d)(w=%d h=%d)\n"),
hMonitor,
infoEx.szDevice,
infoEx.dwFlags == MONITORINFOF_PRIMARY ? ("Primary") : ("Slave"),
infoEx.rcMonitor.left, infoEx.rcMonitor.top, infoEx.rcMonitor.right, infoEx.rcMonitor.bottom,
infoEx.rcMonitor.right - infoEx.rcMonitor.left, infoEx.rcMonitor.bottom - infoEx.rcMonitor.top,
infoEx.rcWork.left, infoEx.rcWork.top, infoEx.rcWork.right, infoEx.rcWork.bottom,
infoEx.rcWork.right - infoEx.rcWork.left, infoEx.rcWork.bottom - infoEx.rcWork.top);
}
//保存显示器信息
if (pThis->m_iMontorNumber < _countof(pThis->m_MonitorInfoExArray) - 1)
{
VMONITORINFO* pInfo = &pThis->m_MonitorInfoExArray[pThis->m_iMontorNumber];
pInfo->hMonitor = hMonitor;
if (lprcMonitor)
{
pInfo->rcVirtual = *lprcMonitor;
}
pInfo->rcMonitor = infoEx.rcMonitor;
pInfo->rcWork = infoEx.rcWork;
pInfo->bPrimary = infoEx.dwFlags == MONITORINFOF_PRIMARY;
strcpy(pInfo->szDevice, infoEx.szDevice);
pThis->m_iMontorNumber++;
return TRUE; //continue the enumeration
}
return FALSE; //stop the enumeration
}
public:
CMultiMonitorEnumerator()
{
m_iMontorNumber = 0;
EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)this);
}
};
class DisplayPowerMonitor {
private:
HPOWERNOTIFY hPowerNotify;
HWND hWnd;
public:
DisplayPowerMonitor(HWND window) : hWnd(window), hPowerNotify(nullptr) {}
bool StartMonitoring() {
// Register for console display state notifications
hPowerNotify = RegisterPowerSettingNotification(
hWnd,
&GUID_CONSOLE_DISPLAY_STATE,
DEVICE_NOTIFY_WINDOW_HANDLE
);
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (hPowerNotify != nullptr);
}
void StopMonitoring() {
if (hPowerNotify) {
UnregisterPowerSettingNotification(hPowerNotify);
hPowerNotify = nullptr;
}
}
static std::string GetDisplayStateString(DWORD state) {
switch (state) {
case 0: return "Display Off";
case 1: return "Display On";
case 2: return "Display Dimmed";
default: return "Unknown State";
}
}
static LRESULT HandlePowerBroadcast(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (uMsg == WM_POWERBROADCAST && wParam == PBT_POWERSETTINGCHANGE) {
auto* setting = reinterpret_cast<POWERBROADCAST_SETTING*>(lParam);
if (IsEqualGUID(setting->PowerSetting, GUID_CONSOLE_DISPLAY_STATE)) {
DWORD displayState = *reinterpret_cast<DWORD*>(&setting->Data);
std::string stateStr = GetDisplayStateString(displayState);
std::cout << "Display state changed: " << stateStr << std::endl;
// Perform actions based on display state
switch (displayState) {
case 0: // Display Off
OnDisplayOff();
break;
case 1: // Display On
OnDisplayOn();
break;
case 2: // Display Dimmed
OnDisplayDimmed();
break;
}
}
}
PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = ("Hello,");
switch (uMsg)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
TextOut(hdc,
5, 5,
greeting, strlen(greeting));
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
private:
static void OnDisplayOff() {
std::cout << "Performing cleanup for display off..." << std::endl;
// Pause rendering, stop videos, etc.
}
static void OnDisplayOn() {
std::cout << "Resuming operations for display on..." << std::endl;
// Resume rendering, restart videos, etc.
}
static void OnDisplayDimmed() {
std::cout << "Display dimmed - reducing activity..." << std::endl;
// Reduce CPU/GPU usage
}
};
std::string toUtf8(wchar_t* buffer)
{
CW2A utf8(buffer, CP_UTF8);
const char* data = utf8.m_psz;
return std::string{ data };
}
class MultiMonitorController {
private:
struct PhysicalMonitor {
HANDLE hPhysicalMonitor;
DWORD index;
wchar_t description[128];
};
std::vector<PhysicalMonitor> physicalMonitors;
public:
bool Initialize() {
// 获取显示器数量
DWORD monitorCount;
HMONITOR hMonitor = NULL;
HDC hdc = GetDC(NULL);
monitorCount = GetSystemMetrics(SM_CMONITORS);
ReleaseDC(NULL, hdc);
// 枚举物理显示器
for (DWORD i = 0; i < monitorCount; i++) {
DISPLAY_DEVICE displayDevice = { 0 };
displayDevice.cb = sizeof(DISPLAY_DEVICE);
if (EnumDisplayDevices(NULL, i, &displayDevice, 0)) {
if (displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE) {
// 获取物理显示器句柄
HMONITOR hMonitor = MonitorFromPoint(POINT{ 0,0 }, MONITOR_DEFAULTTOPRIMARY);
if (hMonitor) {
DWORD physicalCount;
LPPHYSICAL_MONITOR physicalMonitors = NULL;
if (GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, &physicalCount)) {
physicalMonitors = new PHYSICAL_MONITOR[physicalCount];
if (GetPhysicalMonitorsFromHMONITOR(hMonitor, physicalCount, physicalMonitors)) {
for (DWORD j = 0; j < physicalCount; j++) {
PhysicalMonitor pm;
pm.hPhysicalMonitor = physicalMonitors[j].hPhysicalMonitor;
wprintf(L"ssssssssssssssssssssss i=%ul j=%ul == description%ls\n", i, j, toUtf8(pm.description));
pm.index = i;
wcscpy_s(pm.description, physicalMonitors[j].szPhysicalMonitorDescription);
this->physicalMonitors.push_back(pm);
}
}
delete[] physicalMonitors;
}
}
}
}
}
return !physicalMonitors.empty();
}
// 关闭指定显示器
bool TurnOffMonitor(int monitorIndex) {
for (const auto& monitor : physicalMonitors) {
if (monitor.index == monitorIndex) {
printf("TurnOffMonitorTurnOffMonitorTurnOffMonitorTurnOffMonitor index=%ul\n", monitor.index);
// 使用DDC/CI命令关闭显示器
return SetVCPFeature(monitor.hPhysicalMonitor, 0xD6, 0x04) == TRUE;
}
}
return false;
}
// 开启指定显示器
bool TurnOnMonitor(int monitorIndex) {
for (const auto& monitor : physicalMonitors) {
if (monitor.index == monitorIndex) {
// 使用DDC/CI命令开启显示器
return SetVCPFeature(monitor.hPhysicalMonitor, 0xD6, 0x01) == TRUE;
}
}
return false;
}
// 设置显示器电源状态 (0x01=开, 0x04=关, 0x05=待机)
bool SetMonitorPowerState(int monitorIndex, BYTE powerState) {
for (const auto& monitor : physicalMonitors) {
if (monitor.index == monitorIndex) {
printf("SetMonitorPowerStateSetMonitorPowerStateSetMonitorPowerState index=%ul\n", monitor.index);
return SetVCPFeature(monitor.hPhysicalMonitor, 0xD6, powerState) == TRUE;
}
}
return false;
}
~MultiMonitorController() {
// 清理资源
for (const auto& monitor : physicalMonitors) {
DestroyPhysicalMonitor(monitor.hPhysicalMonitor);
}
}
};
class ServicePowerMonitor {
private:
HPOWERNOTIFY hPowerNotify;
HANDLE hService;
public:
ServicePowerMonitor() : hService(GetCurrentProcess()), hPowerNotify(nullptr) {}
bool StartServiceMonitoring() {
hPowerNotify = RegisterPowerSettingNotification(
hService,
&GUID_CONSOLE_DISPLAY_STATE,
DEVICE_NOTIFY_SERVICE_HANDLE
);
if (!hPowerNotify) {
std::cerr << "Failed to register power notification: " << GetLastError() << std::endl;
return false;
}
std::cout << "Service registered for display power notifications" << std::endl;
return true;
}
void StopMonitoring() {
if (hPowerNotify) {
UnregisterPowerSettingNotification(hPowerNotify);
hPowerNotify = nullptr;
}
}
void HandleServiceControl(DWORD dwControl) {
if (dwControl == SERVICE_CONTROL_POWEREVENT) {
// Handle power events in service context
std::cout << "Power event received by service" << std::endl;
}
}
};
// 简化版本的多显示器控制器
class SimpleMultiMonitorController {
private:
struct MonitorInfo {
int index;
std::string name;
std::string description;
bool isPrimary;
};
std::vector<MonitorInfo> monitors;
public:
bool Initialize() {
monitors.clear();
DISPLAY_DEVICE displayDevice;
displayDevice.cb = sizeof(DISPLAY_DEVICE);
for (DWORD i = 0; EnumDisplayDevices(NULL, i, &displayDevice, 0); i++) {
if (displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) {
MonitorInfo info;
info.index = i;
info.name = displayDevice.DeviceName;
info.description = displayDevice.DeviceString;
info.isPrimary = (displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) != 0;
monitors.push_back(info);
}
}
return !monitors.empty();
}
// 方法1:使用显示设置API关闭指定显示器(推荐)
bool TurnOffMonitor(int monitorIndex) {
DISPLAY_DEVICE displayDevice;
displayDevice.cb = sizeof(DISPLAY_DEVICE);
for (DWORD i = 0; EnumDisplayDevices(NULL, i, &displayDevice, 0); i++) {
if (i == monitorIndex && (displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) {
DEVMODE devMode = { 0 };
devMode.dmSize = sizeof(DEVMODE);
devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
devMode.dmPelsWidth = 0;
devMode.dmPelsHeight = 0;
printf("TurnOffMonitor TurnOffMonitor 88888888888888888888 monitorIndex=%d displayDevice.DeviceName=%s\n",
monitorIndex, displayDevice.DeviceName);
// 禁用显示器
LONG result = ChangeDisplaySettingsEx(displayDevice.DeviceName,
&devMode,
NULL,
CDS_UPDATEREGISTRY | CDS_NORESET | CDS_OFF,
NULL);
if (result == DISP_CHANGE_SUCCESSFUL) {
// 应用更改
result = ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
return result == DISP_CHANGE_SUCCESSFUL;
}
}
}
return false;
}
// 方法2:使用简单的显示器禁用/启用
bool DisableMonitor(int monitorIndex) {
DISPLAY_DEVICE displayDevice;
displayDevice.cb = sizeof(DISPLAY_DEVICE);
for (DWORD i = 0; EnumDisplayDevices(NULL, i, &displayDevice, 0); i++) {
if (i == monitorIndex) {
DEVMODE devMode = { 0 };
devMode.dmSize = sizeof(DEVMODE);
printf("DisableMonitorDisableMonitorDisableMonitorDisableMonitor monitorIndex=%d displayDevice.DeviceName=%s\n",
monitorIndex, displayDevice.DeviceName);
// 设置为禁用状态
return ChangeDisplaySettingsEx(displayDevice.DeviceName,
NULL, NULL,
CDS_UPDATEREGISTRY | CDS_NORESET | CDS_OFF,
NULL) == DISP_CHANGE_SUCCESSFUL;
}
}
return false;
}
bool EnableMonitor(int monitorIndex) {
DISPLAY_DEVICE displayDevice;
displayDevice.cb = sizeof(DISPLAY_DEVICE);
for (DWORD i = 0; EnumDisplayDevices(NULL, i, &displayDevice, 0); i++) {
if (i == monitorIndex) {
// 恢复到默认设置
return ChangeDisplaySettingsEx(displayDevice.DeviceName,
NULL, NULL, 0, NULL) == DISP_CHANGE_SUCCESSFUL;
}
}
return false;
}
// 方法3:使用电源管理API(如果支持)
bool SetMonitorPowerState(int monitorIndex, bool turnOn) {
// 发送电源管理消息
if (turnOn) {
// 开启屏幕
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)-1);
}
else {
// 关闭屏幕(需要先激活屏幕)
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)2);
}
return true;
}
std::vector<MonitorInfo> GetMonitorList() const {
return monitors;
}
void PrintMonitorInfo() {
std::cout << "检测到的显示器:" << std::endl;
for (const auto& monitor : monitors) {
std::cout << "显示器 " << monitor.index << ": "
<< monitor.description
<< (monitor.isPrimary ? " (主显示器)" : "")
<< std::endl;
}
}
};
// 替代方案:使用更简单的API
class SimpleScreenController {
public:
// 关闭所有屏幕(最简单的方法)
static void TurnOffAllScreens() {
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)2);
}
// 开启所有屏幕
static void TurnOnAllScreens() {
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)-1);
}
// 防止屏幕关闭
static void PreventScreenOff() {
SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_CONTINUOUS);
}
// 允许屏幕关闭
static void AllowScreenOff() {
SetThreadExecutionState(ES_CONTINUOUS);
}
};
CMultiMonitorEnumerator mMultDisplayEnum;
HDC hdc = GetDC(NULL); // 获取屏幕的DC
GetScreenInfo(hdc);
ReleaseDC(NULL, hdc); // 释放DC
//MonitorPowerMonitor monitor;
//monitor.StartMonitoring();
WNDCLASS wc = {};
//wc.lpfnWndProc = MonitorPowerMonitor::WndProc;
wc.lpfnWndProc = DisplayPowerMonitor::HandlePowerBroadcast;
wc.hInstance = GetModuleHandle(nullptr);
wc.lpszClassName = "MonitorPowerMonitor";
RegisterClass(&wc);
HWND hwnd = CreateWindow(wc.lpszClassName, "3dof", 0, 0, 0, 800, 600, nullptr, nullptr, wc.hInstance, nullptr);
//ShowWindow(hwnd, SW_SHOW);
//MoveWindow(hwnd, 2880, 0, 800, 600, false);
std::this_thread::sleep_for(std::chrono::seconds(1));
MultiMonitorController mc;
mc.Initialize();
//mc.TurnOffMonitor(1);
//mc.SetMonitorPowerState(0, 4);
SimpleMultiMonitorController controller;
controller.Initialize();
//controller.TurnOffMonitor(0);
controller.DisableMonitor(0);
Windows显示器控制与电源管理

被折叠的 条评论
为什么被折叠?



