跳转到主内容
极星编程网:以代码为星,赴技术山海!

C#怎么实现屏幕颜色抓取_C#如何获取鼠标位置的像素值【代码】

能用但性能极差,仅适合偶尔取色;GetPixel跨进程调用开销大,60fps循环中会导致卡顿;推荐Graphics.CopyFromScreen截1×1像素再读取,或BitBlt内存缓冲用于高频场景;WPF应改用RenderTargetBitmap。 用
GetPixel
快速读取鼠标坐标颜色,但别在循环里狂调 直接结论:能用,但性能极差,只适合偶尔点一下查色。windows api 的
getpixel
是最简单的方式,它接收屏幕坐标(x, y),返回一个
colorref
,转成
color
就行。 常见错误是把它塞进 60fps 的鼠标跟踪循环里——CPU 占用瞬间飙高,还卡顿。因为每次调用都要跨进程、走 GDI、做坐标转换,本质是“截图单像素”,不是内存读取。 必须先用
GetCursorPos
获取鼠标位置,再传给
GetPixel
GetPixel
读的是**屏幕坐标系**,不是窗体客户区坐标,别忘了用
ScreenToClient
转换(如果真要读自己窗口某点,那得另说) 返回的
COLORREF
是 BGR 格式(低字节是蓝),不是 RGB,
Color.FromArgb(ref)
会自动处理,但手撕位运算时容易翻车 .NET 6+ 推荐用
Graphics.CopyFromScreen
截一小块再取色 比
GetPixel
稳得多,尤其要连续采样(比如做取色器吸管功能)。原理是先截 1×1 像素区域到
Bitmap
,再用
GetPixel(0, 0)
读——这回是托管内存操作,快一个数量级。 关键点在于“截哪”:必须把鼠标屏幕坐标转成目标设备上下文的逻辑坐标。如果只是看当前屏幕颜色,就以
Graphics.FromHwnd(IntPtr.Zero)
创建全屏图面;如果限定在某个窗口内,得先
GetWindowRect
拿窗口边界,再做偏移计算。 截 1×1 比截大图快,但别截 0×0——会抛
ArgumentException
记得
Dispose()
Graphics
和
Bitmap
,不然内存泄漏比颜色还显眼 多显示器环境下,鼠标可能在非主屏,
CopyFromScreen
默认只对主屏有效,需用
Screen.FromPoint
判断并调整源坐标 高频采样场景必须上
BitBlt
+ 内存缓冲 要做实时色值监控(比如录屏分析、辅助瞄准),
GetPixel
和小图截取都扛不住。真正靠谱的是用
BitBlt
把整屏或指定区域拷进内存
Bitmap
,之后所有像素访问都是纯内存操作。 C知道 CSDN推出的一款AI技术问答工具 下载 这不是加个引用就能跑的事:要手动创建兼容 DC、分配 DIB Section、管理位图句柄。.NET 没封装这个路径,得 P/Invoke
CreateCompatibleDC
、
CreateDIBSection
、
SelectObject
,最后
BitBlt
一次拷完。 缓冲区复用很关键——别每帧 new
Bitmap
,重用同一块内存 拷贝区域越小越好,比如只要鼠标周围 5×5,就只拷那么大,别全屏 注意 GDI 对象泄漏:每个
CreateCompatibleDC
都得配对
DeleteDC
,
SelectObject
返回的老位图也要
DeleteObject
WPF 或 WinUI 项目?绕开 GDI,走
RenderTargetBitmap
路线 如果你不在 WinForms 里硬刚 GDI,而是用 WPF,别碰
GetPixel
。WPF 渲染走 DirectX,GDI 读不到 WPF 窗口内容(会读到黑或旧画面)。正确姿势是用
RenderTargetBitmap
把目标
Visual
(比如整个窗口或某个
Canvas
)渲染成位图,再用
Pixels
数组取色。 限制也很明显:它只能抓 WPF 自己画的东西,抓不到其他进程窗口、任务栏、桌面图标——这点和 GDI 方案完全不同。所以“取鼠标下任意屏幕色”这个需求,在 WPF 里天然不成立,得切回 Win32 API。
RenderTargetBitmap
构造时分辨率参数必须和目标控件实际像素尺寸一致,否则缩放失真 读
Pixels
数组前,确保已调用
Render
并等待完成(它异步) 数组是 BGRA 格式、每像素 4 字节、从左到右从上到下排布,索引计算别错位 事情说清了就结束。最常被忽略的是多显示器 DPI 缩放——GetCursorPos 返回的是物理像素坐标,但 BitBlt 或 CopyFromScreen 在高 DPI 下可能按逻辑坐标算,不校正的话颜色会偏移一两个像素。

相关文章