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

C++实现类似CSS backdrop-filter效果 对窗口指定矩形区域内容反色

无闪烁稳定窗口区域反色实现方案

你要实现的指定区域反色效果如下:
效果示例图
你的原有方案闪烁的核心原因是先重绘原始窗口内容、再执行反色操作的两步执行逻辑会产生可见的中间帧,同时直接操作目标窗口DC会和窗口自身的绘制逻辑冲突,导致内容更新后效果失效。
下面分两种场景提供可行方案:

场景1:目标窗口是你自行开发的程序窗口

优先采用子类化窗口、接管WM_PAINT消息的方案,稳定性最高:

  • 对目标窗口进行子类化,重写其窗口过程
  • 在WM_PAINT消息的默认绘制逻辑执行完成后,使用双缓冲执行反色操作,避免闪烁
    参考代码示例:
LRESULT CALLBACK SubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
    if (uMsg == WM_PAINT) {
        // 先执行原始绘制逻辑
        LRESULT res = DefSubclassProc(hwnd, uMsg, wParam, lParam);
        HDC hdc = GetDC(hwnd);
        // 创建内存DC做双缓冲
        HDC memDC = CreateCompatibleDC(hdc);
        // 实际反色区域:(300,100) 到 (600,500),宽300、高400
        RECT invertRect = {300, 100, 600, 500};
        int width = invertRect.right - invertRect.left;
        int height = invertRect.bottom - invertRect.top;
        HBITMAP memBmp = CreateCompatibleBitmap(hdc, width, height);
        HBITMAP oldBmp = (HBITMAP)SelectObject(memDC, memBmp);
        // 把窗口对应区域内容拷贝到内存DC
        BitBlt(memDC, 0, 0, width, height, hdc, 300, 100, SRCCOPY);
        // 内存DC中反色
        BitBlt(memDC, 0, 0, width, height, NULL, 0, 0, DSTINVERT);
        // 一次性拷贝回窗口DC,无中间闪烁
        BitBlt(hdc, 300, 100, width, height, memDC, 0, 0, SRCCOPY);
        // 释放GDI资源,避免泄漏
        SelectObject(memDC, oldBmp);
        DeleteObject(memBmp);
        DeleteDC(memDC);
        ReleaseDC(hwnd, hdc);
        return res;
    }
    // 其他消息走默认逻辑
    return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}

只要窗口触发重绘就会自动执行反色,不会出现重复反色、效果失效的问题。

场景2:目标窗口是第三方程序窗口

如果无法修改目标窗口的代码,采用分层覆盖窗口方案:

  • 创建一个带有WS_EX_LAYERED、WS_EX_TRANSPARENT扩展属性的无边框顶层窗口,设置鼠标穿透属性,不会影响原窗口的交互
  • 把覆盖窗口的位置和大小固定为你要反色的区域,同步跟随目标窗口移动、缩放
  • 定时监听目标窗口的内容更新,将目标窗口对应区域的内容读取后反色,绘制到覆盖窗口上即可
  • 可配合GetWindowPlacement判断目标窗口的状态、WindowFromPoint判断目标区域是否被遮挡,同步调整覆盖窗口的显隐
    该方案反色逻辑完全在独立的覆盖窗口执行,不会和原窗口的绘制逻辑冲突,也不会出现闪烁。

原有代码问题提示

你原来的代码有2个明显问题:

  1. BitBlt的第4、5个参数是区域的宽高,不是右下角坐标,你填的600, 500实际会截取从(300,100)到(900,600)的区域,和你的预期不符
  2. 每次调用GetDC后没有调用ReleaseDC,会造成GDI资源泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 07:54:05