You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++实现显示器刷新率变化的非轮询式检测(Windows/Android)

编程检测显示器刷新率变化(无需持续轮询)

可以实现无需持续轮询的显示器刷新率变化检测,以下是Windows和Android平台的具体方案:

Windows平台

方法1:处理WM_DISPLAYCHANGE消息

你之前提到的WM_DISPLAYCHANGE并非仅检测分辨率变化——显示器刷新率变更时系统同样会发送该消息。只需在窗口过程中捕获此消息,再单次调用EnumDisplaySettings获取当前刷新率即可,无需轮询:

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_DISPLAYCHANGE: {
            DEVMODE dm = {0};
            dm.dmSize = sizeof(DEVMODE);
            if (EnumDisplaySettings(nullptr, ENUM_CURRENT_SETTINGS, &dm)) {
                DWORD currentRefreshRate = dm.dmDisplayFrequency;
                // 在这里处理刷新率变化的业务逻辑
            }
            break;
        }
        // 其他消息处理逻辑...
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

方法2:Display Config回调(Windows 10+)

如果需要更精准的显示配置变更通知,可使用Windows 10及以上提供的Display Config API,通过注册回调实现无轮询检测:

  1. 实现IDisplayConfigCallback接口,重写OnDisplayConfigChanged方法——该方法会在显示配置(包括刷新率)变更时触发。
  2. 调用RegisterDisplayConfigChangeNotification注册回调,指定监听范围(单个设备或所有设备)。
  3. 不再需要时调用UnregisterDisplayConfigChangeNotification注销。

核心代码示例:

class DisplayConfigCallback : public IDisplayConfigCallback {
public:
    HRESULT STDMETHODCALLTYPE OnDisplayConfigChanged(
        DISPLAY_CONFIG_TOPOLOGY_ID newTopologyId,
        DISPLAY_CONFIG_PATH_INFO* pathArray,
        UINT32 pathCount,
        DISPLAY_CONFIG_MODE_INFO* modeArray,
        UINT32 modeCount) override {
        // 遍历modeArray可获取各显示器的最新刷新率参数
        // 处理刷新率变化逻辑
        return S_OK;
    }

    // 实现IUnknown接口的基础方法
    ULONG STDMETHODCALLTYPE AddRef() override { return 1; }
    ULONG STDMETHODCALLTYPE Release() override { return 0; }
    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override {
        if (riid == IID_IDisplayConfigCallback || riid == IID_IUnknown) {
            *ppvObject = this;
            return S_OK;
        }
        return E_NOINTERFACE;
    }
};

// 注册回调
DisplayConfigCallback callback;
LARGE_INTEGER notificationCookie;
HRESULT hr = RegisterDisplayConfigChangeNotification(&callback, &notificationCookie);

Android平台

方法1:DisplayManager.DisplayListener监听

通过系统的DisplayManager注册显示器状态监听器,当显示器参数(包括刷新率)变更时会触发回调:

DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
DisplayListener displayListener = new DisplayListener() {
    @Override
    public void onDisplayAdded(int displayId) {}

    @Override
    public void onDisplayRemoved(int displayId) {}

    @Override
    public void onDisplayChanged(int displayId) {
        Display targetDisplay = displayManager.getDisplay(displayId);
        if (targetDisplay != null) {
            float currentRefreshRate = targetDisplay.getRefreshRate();
            // 处理刷新率变化逻辑
        }
    }
};

// 注册监听
displayManager.registerDisplayListener(displayListener, null);

// 不再需要时注销监听
// displayManager.unregisterDisplayListener(displayListener);

方法2:监听系统设置变更

通过ContentObserver监听系统刷新率设置的变更,适合关注系统全局刷新率调整的场景:

ContentObserver refreshRateObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        float currentRefreshRate = Settings.System.getFloat(
                getContentResolver(),
                Settings.System.REFRESH_RATE,
                60.0f); // 默认值60Hz
        // 处理刷新率变化逻辑
    }
};

// 注册观察者
getContentResolver().registerContentObserver(
        Settings.System.getUriFor(Settings.System.REFRESH_RATE),
        false,
        refreshRateObserver);

// 注销观察者
// getContentResolver().unregisterContentObserver(refreshRateObserver);

内容的提问来源于stack exchange,提问作者iexav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 06:40:32