因复现问题,需要通过程序可以自动在两个分辨率之间循环调整系统分辨率,于是有了下面代码
代码在win11、win10上均测试可以正常运行。如果遇到问题欢迎留言交流。
#include <windows.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <string>
#include <vector>
#include <atomic>
// 分辨率结构体
struct Resolution {
int width;
int height;
int refreshRate;
};
// 用于控制循环的原子变量
std::atomic<bool> g_running(true);
// 控制台处理函数
BOOL WINAPI ConsoleHandler(DWORD ctrlType) {
if (ctrlType == CTRL_C_EVENT) {
g_running = false;
return TRUE;
}
return FALSE;
}
// 获取当前系统分辨率
Resolution GetCurrentResolution() {
DEVMODE dm = { 0 };
dm.dmSize = sizeof(DEVMODE);
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
Resolution res;
res.width = dm.dmPelsWidth;
res.height = dm.dmPelsHeight;
res.refreshRate = dm.dmDisplayFrequency;
return res;
}
// 列出所有可用的分辨率
std::vector<Resolution> GetAvailableResolutions() {
std::vector<Resolution> resolutions;
DEVMODE dm = { 0 };
dm.dmSize = sizeof(DEVMODE);
for (int i = 0; EnumDisplaySettings(NULL, i, &dm) != 0; i++) {
// 检查是否已经添加过这个分辨率
bool isDuplicate = false;
for (const auto& res : resolutions) {
if (res.width == dm.dmPelsWidth &&
res.height == dm.dmPelsHeight &&
res.refreshRate == dm.dmDisplayFrequency) {
isDuplicate = true;
break;
}
}
if (!isDuplicate) {
Resolution res;
res.width = dm.dmPelsWidth;
res.height = dm.dmPelsHeight;
res.refreshRate = dm.dmDisplayFrequency;
resolutions.push_back(res);
}
}
return resolutions;
}
// 设置分辨率
bool SetResolution(int width, int height, int refreshRate = 60) {
DEVMODE dm = { 0 };
dm.dmSize = sizeof(DEVMODE);
if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm)) {
printf("无法获取当前显示设置\n");
return false;
}
// 设置新的分辨率和刷新率
dm.dmPelsWidth = width;
dm.dmPelsHeight = height;
if (refreshRate > 0) {
dm.dmDisplayFrequency = refreshRate;
}
// 指定要修改的字段
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
if (refreshRate > 0) {
dm.dmFields |= DM_DISPLAYFREQUENCY;
}
// 更改显示设置
LONG result = ChangeDisplaySettings(&dm, CDS_UPDATEREGISTRY);
switch (result) {
case DISP_CHANGE_SUCCESSFUL:
printf("成功切换到分辨率 %dx%d @ %dHz\n", width, height, refreshRate);
return true;
case DISP_CHANGE_BADDUALVIEW:
printf("系统不支持双视图,请禁用双视图并重试\n");
break;
case DISP_CHANGE_BADFLAGS:
printf("无效的标志\n");
break;
case DISP_CHANGE_BADMODE:
printf("请求的图形模式不受支持\n");
break;
case DISP_CHANGE_BADPARAM:
printf("参数无效\n");
break;
case DISP_CHANGE_FAILED:
printf("图形模式更改失败\n");
break;
case DISP_CHANGE_NOTUPDATED:
printf("无法将设置写入注册表\n");
break;
case DISP_CHANGE_RESTART:
printf("需要重新启动计算机才能应用请求的图形模式\n");
break;
default:
printf("发生未知错误\n");
break;
}
return false;
}
// 循环切换分辨率
void CycleResolutions(const Resolution& res1, const Resolution& res2, int intervalSeconds) {
bool useFirstResolution = true;
printf("开始循环切换分辨率,间隔时间:%d秒\n", intervalSeconds);
printf("将在以下分辨率间切换:\n");
printf(" - %dx%d @ %dHz\n", res1.width, res1.height, res1.refreshRate);
printf(" - %dx%d @ %dHz\n", res2.width, res2.height, res2.refreshRate);
printf("按 Ctrl+C 终止程序\n");
// 设置控制台控制处理程序以捕获 Ctrl+C
SetConsoleCtrlHandler(ConsoleHandler, TRUE);
g_running = true;
while (g_running) {
if (useFirstResolution) {
SetResolution(res1.width, res1.height, res1.refreshRate);
}
else {
SetResolution(res2.width, res2.height, res2.refreshRate);
}
useFirstResolution = !useFirstResolution;
// 等待指定的间隔时间,每100毫秒检查一次是否应该退出
for (int i = 0; i < intervalSeconds * 10 && g_running; i++) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
// 清除控制台控制处理程序
SetConsoleCtrlHandler(ConsoleHandler, FALSE);
}
int SetDisplayResolutionMain() {
// 获取当前分辨率
Resolution currentRes = GetCurrentResolution();
printf("当前分辨率: %dx%d @ %dHz\n", currentRes.width, currentRes.height, currentRes.refreshRate);
// 获取所有可用分辨率
std::vector<Resolution> availableResolutions = GetAvailableResolutions();
printf("\n可用分辨率列表:\n");
for (size_t i = 0; i < availableResolutions.size(); ++i) {
printf("%zu. %dx%d @ %dHz\n", i + 1,
availableResolutions[i].width,
availableResolutions[i].height,
availableResolutions[i].refreshRate);
}
// 获取用户输入
int choice1 = 0, choice2 = 0;
printf("\n请选择第一个分辨率 (1-%zu): ", availableResolutions.size());
scanf_s("%d", &choice1);
if (choice1 < 1 || choice1 > static_cast<int>(availableResolutions.size())) {
printf("无效选择,将使用当前分辨率\n");
choice1 = 0; // 使用当前分辨率
}
printf("请选择第二个分辨率 (1-%zu): ", availableResolutions.size());
scanf_s("%d", &choice2);
if (choice2 < 1 || choice2 > static_cast<int>(availableResolutions.size())) {
printf("无效选择,将使用默认分辨率 1024x768\n");
choice2 = -1; // 使用默认分辨率
}
// 确定分辨率
Resolution res1, res2;
if (choice1 == 0) {
res1 = currentRes;
}
else {
res1 = availableResolutions[choice1 - 1];
}
if (choice2 == -1) {
res2.width = 1024;
res2.height = 768;
res2.refreshRate = 60;
}
else {
res2 = availableResolutions[choice2 - 1];
}
// 获取切换间隔
int interval;
printf("请输入切换间隔时间(秒): ");
scanf_s("%d", &interval);
if (interval < 1) {
printf("间隔时间无效,将使用默认值 5 秒\n");
interval = 5;
}
// 开始循环切换
try {
CycleResolutions(res1, res2, interval);
}
catch (const std::exception& e) {
printf("发生异常: %s\n", e.what());
}
// 在程序结束时恢复原始分辨率
SetResolution(currentRes.width, currentRes.height, currentRes.refreshRate);
printf("已恢复原始分辨率\n");
// 等待用户按键后退出
printf("按任意键继续...\n");
getchar();
getchar(); // 消耗之前的回车符
return 0;
}
1384

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



