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

如何获取光标下方的像素颜色值?需支持任意非Rust专属窗口

获取任意窗口光标下方像素颜色的Rust实现方案

Windows 平台实现

借助winapi和user32-sys crate调用Windows系统API完成:

  1. 获取光标当前屏幕坐标
  2. 定位光标所在窗口句柄
  3. 获取窗口设备上下文(DC)
  4. 读取对应坐标的像素颜色值

示例代码:

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交互实现:

  1. 查询光标全局位置
  2. 获取光标所在窗口
  3. 读取窗口对应坐标的像素值

示例代码:

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捕获屏幕并读取像素:

  1. 获取光标全局位置(macOS坐标原点在左下角,需转换)
  2. 截取对应位置1x1像素区域
  3. 解析像素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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 02:26:10