如何在 Windows 上使用 Rust 获取特定窗口的屏幕截图?

问题描述 投票:0回答:1

我想知道如何截取特定窗口的一部分。应用程序顶部可能有一个覆盖层(游戏覆盖层)隐藏了我感兴趣的内容。我想找到一种方法来只截取应用程序的屏幕截图,忽略覆盖层或者会出现什么顶。

而且我想知道是否有可能优化它以获得 ~5 截图/秒

现在我用以下代码尝试了screenshots cargo package:

use opencv::{core, highgui, imgcodecs};
use screenshots::Screen;
use std::{time::Instant};
use opencv::core::{log, Mat};

const WIDTH: i32 = 275;
const HEIGHT: i32 = 275;

fn get_img(screen: Screen) -> Mat {
    let image = screen.capture().unwrap();
    let buffer: Vec<u8> = image.into();

    // Change image type to OpenCV Mat
    let original_image: Mat = imgcodecs::imdecode(&core::Mat::from_slice(buffer.as_slice()).unwrap(), imgcodecs::IMREAD_COLOR).unwrap();
    return original_image;
}

fn main() {
    let window_name = "test".to_owned();
    highgui::named_window(&window_name, highgui::WINDOW_NORMAL).unwrap();
    highgui::resize_window(&window_name, WIDTH, HEIGHT).unwrap();


    let screens = Screen::all().unwrap();
    let screen = screens[1].clone();


    let mut img = get_img(screen);


    loop {
        let now = Instant::now();
        img = get_img(screen);

        // print in console the time it took to process the image
        println!("{} ms", now.elapsed().as_millis());
    }
}

但是似乎不可能只截取叠加层后面的特定窗口的屏幕截图。

我用

cargo run --release

目标操作系统是Windows,我也在Windows下开发。

ps :我将我的图像转换为 OpenCV Mat 用于我的下一部分代码

opencv rust screenshot screen-scraping rust-cargo
1个回答
0
投票

您可以使用

winapi
user32
repo 获取任何窗口截图。

错误的是你可能使用了不能在 Windows 上运行的 onencv 库。

这是我的示例代码。假设我们有一个窗口调用“Chrome”

use winapi::um::winuser::{FindWindowA, GetWindowRect, GetDC, ReleaseDC};
use winapi::shared::windef::RECT;
use std::ptr::null_mut;

fn main() {
    let window_title = "Chrome";
    let hwnd = unsafe { FindWindowA(null_mut(), window_title.as_ptr() as *const i8) };
    let mut rect = RECT::default();
    unsafe {
        GetWindowRect(hwnd, &mut rect);
        let width = rect.right - rect.left;
        let height = rect.bottom - rect.top;
        let hdc = GetDC(hwnd);
        let mut buf: Vec<u32> = vec![0; (width * height) as usize];
        let pitch = width * std::mem::size_of::<u32>() as i32;
        winapi::um::wingdi::BitBlt(hdc, 0, 0, width, height, hdc, 0, 0, winapi::um::wingdi::SRCCOPY);
        winapi::um::wingdi::GetDIBits(hdc, null_mut(), 0, height as u32, buf.as_mut_ptr() as *mut _, 
            &mut winapi::um::wingdi::BITMAPINFO {
                bmiHeader: winapi::um::wingdi::BITMAPINFOHEADER {
                    biSize: std::mem::size_of::<winapi::um::wingdi::BITMAPINFOHEADER>() as u32,
                    biWidth: width,
                    biHeight: height * -1,
                    biPlanes: 1,
                    biBitCount: 32,
                    ..Default::default()
                },
                ..Default::default()
            }, winapi::um::wingdi::DIB_RGB_COLORS);
        ReleaseDC(hwnd, hdc);
    }
}

您可以通过键入

cargo run
来运行它。

希望对你有帮助

© www.soinside.com 2019 - 2024. All rights reserved.