如何获取光标下方的像素颜色值?需支持任意非Rust专属窗口
获取任意窗口光标下方像素颜色的Rust实现方案
Windows 平台实现
借助winapi和user32-sys crate调用Windows系统API完成:
- 获取光标当前屏幕坐标
- 定位光标所在窗口句柄
- 获取窗口设备上下文(DC)
- 读取对应坐标的像素颜色值
示例代码:
use winapi::{ shared::windef::{HWND, HDC, POINT}, um::{ winuser::{GetCursorPos, WindowFromPoint, GetDC, ReleaseDC, GetPixel}, wingdi::COLORREF, }, }; fn get_cursor_pixel_color() -> Option<(u8, u8, u8)> { let mut cursor_pos = POINT { x: 0, y: 0 }; if unsafe { GetCursorPos(&mut cursor_pos) } == 0 { return None; } let hwnd = unsafe { WindowFromPoint(cursor_pos) }; let hdc = unsafe { GetDC(hwnd) }; if hdc == std::ptr::null_mut() { return None; } let color: COLORREF = unsafe { GetPixel(hdc, cursor_pos.x, cursor_pos.y) }; unsafe { ReleaseDC(hwnd, hdc) }; let r = ((color >> 0) & 0xFF) as u8; let g = ((color >> 8) & 0xFF) as u8; let b = ((color >> 16) & 0xFF) as u8; Some((r, g, b)) }
Linux 平台实现
使用xcb crate与X11交互实现:
- 查询光标全局位置
- 获取光标所在窗口
- 读取窗口对应坐标的像素值
示例代码:
use xcb::{Connection, xproto}; fn get_cursor_pixel_color() -> Option<(u8, u8, u8)> { let (conn, screen_num) = Connection::connect(None).ok()?; let screen = conn.get_setup().roots().nth(screen_num as usize)?; // 获取光标位置 let query_cookie = conn.send_request(&xproto::QueryPointer { window: screen.root(), }); let reply = conn.wait_for_reply(query_cookie).ok()?; let win = reply.child(); if win == xproto::NONE { return None; } // 获取窗口1x1像素区域 let get_image_cookie = conn.send_request(&xproto::GetImage { format: xproto::IMAGE_FORMAT_Z_PIXMAP, drawable: win, x: reply.root_x() - reply.win_x(), y: reply.root_y() - reply.win_y(), width: 1, height: 1, plane_mask: !0, }); let image = conn.wait_for_reply(get_image_cookie).ok()?; // 解析RGB值(适配不同屏幕深度) let depth = screen.root_depth() as usize; let pixel = image.data()[0..depth/8].to_vec(); let (r, g, b) = match depth { 24 | 32 => (pixel[2], pixel[1], pixel[0]), _ => return None, }; Some((r, g, b)) }
macOS 平台实现
利用core-graphics crate捕获屏幕并读取像素:
- 获取光标全局位置(macOS坐标原点在左下角,需转换)
- 截取对应位置1x1像素区域
- 解析像素RGB值
示例代码:
use core_graphics::{ display::CGDisplay, geometry::{CGPoint, CGRect}, image::CGImage, }; fn get_cursor_pixel_color() -> Option<(u8, u8, u8)> { // 获取光标位置并转换坐标 let cocoa_pos = cocoa::appkit::NSEvent::mouseLocation(); let main_display = CGDisplay::main(); let cursor_pos = CGPoint::new( cocoa_pos.x, main_display.height() - cocoa_pos.y, ); // 截取1x1像素区域 let image = main_display.image(CGRect::new( cursor_pos.x, cursor_pos.y, 1.0, 1.0, ))?; // 读取像素RGB数据 let data = image.data()?; Some((data[0], data[1], data[2])) }
说明
- 以上方案直接调用系统原生API,支持所有类型窗口(包括非Rust编写的窗口)
- 需要根据目标平台在
Cargo.toml中添加对应依赖 - 权限提示:Linux/macOS需开启屏幕录制权限,Windows无需额外权限
内容的提问来源于stack exchange,提问作者Alexdelia
相关产品推荐
相关产品推荐

