通过程序自动在两个分辨率之间循环调整分辨率测试代码

因复现问题,需要通过程序可以自动在两个分辨率之间循环调整系统分辨率,于是有了下面代码

代码在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;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

danxuezx

如果对你有用是我的快乐

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值