论坛似乎不能夜间模式-可能我没找到。
Dark reader开启似乎也无能为力?-要下载的链接在最下面,使用说明也在最下面,前面是开发的四轮完整对话。当然你也可以直接自己开发一个
不用担心,立即定制软件。“这种时候该Trae出手了”。[对话轮数:4次]
人:
给我一个方案我想写一个程序控制原生windows放大镜的接口实现对屏幕选定区域进行色反靠屏幕按钮控制需要稳定运行,只作为滤镜可以实时展示更新内容,可以将鼠标滚轮,点击操作无视-仅作为无感的一个滤镜程序-需要稳定运行不影响其它项目程序
Trae:
现成的“原生 Windows 放大镜(Magnifier.exe)”本身**没有稳定公开的控制接口**可以让你精确指定“只对屏幕某个矩形区域做色反、并作为滤镜覆盖显示”。最稳的做法是:**不用去操控 Magnifier.exe,而是直接使用 Windows 提供的原生 Magnification API(Magnification.dll)自己做一个“放大镜控件窗口”**,这仍然属于“原生放大镜接口”,但可控性/稳定性远高于 UI 自动化去点系统放大镜按钮。
下面给你一套可落地、稳定运行的方案。
总体方案(推荐)
- 技术路线:Win32 + Magnification API(
MagInitialize / WC_MAGNIFIER / MagSetWindowSource / MagSetColorEffect)
- 展示形态:一个“透明顶置覆盖层窗口”只负责显示滤镜区域;一个“独立小按钮窗口”负责开关/选择区域(按钮可点,其余区域完全穿透)
- 输入策略:滤镜覆盖层设置 点击穿透 + 不激活,保证鼠标滚轮/点击都落到下面的真实应用;只有你的小按钮响应点击
模块拆分
- 滤镜覆盖层(核心)
- 顶层窗口:
WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW
TRANSPARENT:鼠标事件穿透到底层应用
NOACTIVATE:不会抢焦点,不影响其他程序输入
- 覆盖层里创建一个 Magnifier 子窗口(类名
WC_MAGNIFIER)
- 将 magnifier 窗口大小固定为你选择的矩形区域(例如 400×300)
- 关键:把源区域设置为同一块屏幕矩形,倍率设为 1.0,相当于“原样复制”
MagSetWindowSource(magHwnd, selectedRectOnScreen)
- 放大倍数 1.0:视觉上不放大,只做滤镜
- 色反:对 Magnifier 设置颜色矩阵(反相矩阵),例如典型的“RGB 取反”矩阵:
R' = 1 - R, G' = 1 - G, B' = 1 - B(用 MAGCOLOREFFECT 的 5x5 矩阵实现)
- 实时性:Magnifier 控件会自动刷新;你只需在区域移动/分辨率变化/DPI 变化时更新 source rect
- 屏幕按钮(控制面板)
- 单独一个小窗口(同样 TopMost,但不穿透),放一个按钮:启用/停用、重新框选区域、锁定位置
- 这个窗口可以是:
- 纯 Win32(最稳、依赖最少)
- 或 WPF/WinUI3 做 UI(但核心滤镜仍用 Win32 magnifier,WPF 需做窗口互操作)
- 区域选择(框选)
- 进入“选择模式”时,临时启用一个可交互的全屏半透明选择层(捕获鼠标按下/移动/抬起)
- 用户拖出矩形后:
- 计算屏幕坐标 rect(注意多显示器、负坐标)
- 退出选择层
- 将滤镜覆盖层移动/缩放到该 rect,并更新 magnifier source
稳定运行要点(你关心的“不影响其它程序”)
- 不装全局钩子(避免输入延迟/兼容性问题),只用窗口穿透实现“无视滚轮/点击”
- 覆盖层窗口必须
WS_EX_NOACTIVATE,并在显示/移动时避免 SetForegroundWindow
- 处理 DPI:设置 Per-Monitor V2 DPI Awareness,否则框选坐标会漂移(尤其 125%/150% 缩放)
- 处理显示变化:监听
WM_DISPLAYCHANGE、WM_DPICHANGED,必要时重算 source rect
- 性能:倍率 1.0 + 仅一个矩形区域,CPU/GPU 开销很小;避免高频定时器轮询,尽量事件驱动更新
你提到“控制原生放大镜”可选路径对比
- 方案 A(推荐):Magnification API 自建 magnifier 窗口
- 优点:稳定、可控、可做色反、可做区域化、不会依赖系统放大镜 UI 变化
- 缺点:你做的是“自己的滤镜应用”,不是在操控 Magnifier.exe
- 方案 B:UI Automation/发送快捷键操控 Magnifier.exe
- 缺点:脆弱(系统更新/UI 语言/焦点变化都可能导致失效),且很难做到“只对某个矩形区域色反”
实现语言建议
- 最稳最直接:C++/Win32
- 想快速开发 UI:C# 也行,但核心 magnifier 仍建议 Win32(C# 用 P/Invoke 调用 Magnification API + 创建原生窗口)
MVP 交付标准(最小可用版本)
- 小按钮:开启/关闭滤镜、重新选择区域
- 框选区域后:该区域实时显示“反相”,其余屏幕不变
- 鼠标在滤镜区域内点击/滚轮:底层应用正常响应(滤镜不吃输入)
- 稳定运行:不抢焦点、不卡顿,最小化后不残留覆盖
如果你希望我直接在你当前这个工程目录里把 MVP 做出来,我会先检测你要用 C++ 还是 C#、是否已有项目结构(VS solution / CMake / dotnet),然后按上面的架构把窗口、框选、色反矩阵、穿透与 DPI 处理一并落地。
人:方案A
Trae:
我先快速看一下当前目录结构与现有工程类型,然后直接把方案 A 的最小可用版本(可框选区域、实时色反、完全鼠标穿透、带屏幕按钮)落地成可编译项目。
toolName: view_folder
status: success
e:\648\26-1月\屏幕选定区域色反
toolName: view_folder
status: success
e:\648\26-1月\屏幕选定区域色反
toolName: file_search
status: success
file_pattern: */
toolName: todo_write
status: success
Todos updated: 4 items
toolName: apply_patch
status: failed
toolName: write_to_file
status: success
filePath: e:\648\26-1月\屏幕选定区域色反\CMakeLists.txt
content: undefined
toolName: write_to_file
status: success
filePath: e:\648\26-1月\屏幕选定区域色反\src/main.cpp
content: undefined
toolName: todo_write
status: failed
Todos updated: 0 items
toolName: todo_write
status: success
Todos updated: 4 items
toolName: GetDiagnostics
status: success
toolName: run_command
status: success
command: cmake -S . -B build -G “Visual Studio 17 2022” -A x64 undefined
toolName: run_command
status: success
command: cmake --build build --config Release undefined
toolName: view_files
status: success
filePath: e:\648\26-1月\屏幕选定区域色反\src\main.cpp
toolName: apply_patch
status: failed
toolName: edit_file_update
status: success
filePath: e:\648\26-1月\屏幕选定区域色反\CMakeLists.txt
changes:
toolName: apply_patch
status: failed
toolName: edit_file_update
status: success
filePath: e:\648\26-1月\屏幕选定区域色反\src/main.cpp
changes:
toolName: GetDiagnostics
status: success
toolName: run_command
status: success
command: cmake --build build --config Release undefined
toolName: run_command
status: running
command: .\build\Release\ScreenInvertFilter.exe undefined
toolName: check_command_status
status: success
toolName: todo_write
status: success
Todos updated: 4 items
toolName: apply_patch
status: failed
toolName: write_to_file
status: success
filePath: e:\648\26-1月\屏幕选定区域色反\README.md
content: undefined
toolName: todo_write
status: success
Todos updated: 4 items
已按方案 A 落地了一个可编译的 Win32 滤镜程序:框选屏幕任意矩形区域后,该区域会实时色反显示,且鼠标点击/滚轮完全穿透到底层应用,不抢焦点、不影响其它程序。
已实现
- 区域色反滤镜:Magnification API(
WC_MAGNIFIER + MagSetWindowSource + MagSetColorEffect 反相矩阵)
- 透明顶置覆盖层:
TOPMOST + TRANSPARENT + NOACTIVATE,覆盖层与滤镜窗口均不吃输入
- 区域框选:全屏选择层拖拽框选,
ESC 取消
- 屏幕按钮:开启/关闭滤镜、重新选择区域
代码位置
- 入口与核心逻辑:[main.cpp](file:///e:/648/26-1月/屏幕选定区域色反/src/main.cpp)
- 构建配置:[CMakeLists.txt](file:///e:/648/26-1月/屏幕选定区域色反/CMakeLists.txt)
- 构建与使用说明:[README.md](file:///e:/648/26-1月/屏幕选定区域色反/README.md)
构建与运行(Release)
cmake -S . -B build -G "Visual Studio 17 2022" -A x64
cmake --build build --config Release
.\build\Release\ScreenInvertFilter.exe
运行后会出现“小控制窗”,点“选择区域”拖拽框选即可开始色反;点“关闭滤镜/开启滤镜”可开关显示。
人:
适配屏幕帧率 或者直接设置为120?主要是我主副屏幕一个144hz 一个好像更高 30有点卡顿有时
Trae:
我先把定时刷新改成“按所选区域所在显示器刷新率自适应”,并在切换区域/开关时动态调整刷新间隔,然后重新编译验证。
toolName: todo_write
status: success
Todos updated: 3 items
toolName: view_files
status: success
filePath: e:\648\26-1月\屏幕选定区域色反\src\main.cpp
toolName: apply_patch
status: failed
toolName: edit_file_update
status: success
filePath: e:\648\26-1月\屏幕选定区域色反\src/main.cpp
changes:
toolName: todo_write
status: success
Todos updated: 3 items
toolName: GetDiagnostics
status: success
toolName: run_command
status: success
command: cmake --build build --config Release undefined
toolName: run_command
status: success
command: powershell -NoProfile -Command “Stop-Process -Name ScreenInvertFilter -Force -ErrorAction SilentlyContinue” undefined
toolName: run_command
status: success
command: cmake --build build --config Release undefined
toolName: todo_write
status: success
Todos updated: 3 items
toolName: run_command
status: running
command: .\build\Release\ScreenInvertFilter.exe undefined
toolName: check_command_status
status: success
toolName: todo_write
status: success
Todos updated: 3 items
已把刷新从固定 30fps 改成“按所选区域所在屏幕刷新率自适应”。
现在的行为
- 框选完成后,会取“选区中心点所在显示器”的当前刷新率(例如 144Hz/240Hz),自动算出定时刷新间隔:
- 144Hz ≈ 7ms
- 120Hz ≈ 8ms
- 60Hz ≈ 17ms
- 无法读取时默认按 120Hz(≈8ms)
- 关闭滤镜时会停止定时器(不再空转发 WM_TIMER)
改动位置
- 自适应刷新率与定时器控制逻辑在 [main.cpp](file:///e:/648/26-1月/屏幕选定区域色反/src/main.cpp#L46-L111)
- 覆盖层创建/定时刷新在 [OverlayProc](file:///e:/648/26-1月/屏幕选定区域色反/src/main.cpp#L236-L292)
说明
- 这仍然使用
SetTimer,在多数 Win10/11 环境能明显更顺滑;如果你还觉得“偶发卡顿”,下一步我可以改成“专用高精度 waitable timer + PostMessage 刷新”的方式,通常会比 SetTimer 更稳定贴近 144/240。
后续则是放在Git仓库中:GitHub - gotocx/screen-invert-filter-open: 屏幕选定区域色反滤镜(Win32 + Magnification API)——开源版
以及软件分享:-放在仓库了,论坛不能上传。注意软件打开会随机出现在你某个屏幕某个位置,不注意看可能看不见。
使用示例:1.选择选定区域 2.可以自由开启和关闭
最后总结/感悟:
- 这个时代软件是定制化的-大胆做,四五个对话就可以解决一个需求和痛点
- 这是面对和我一样的敏感白光的群体