Velvet Star Monitor

Standout celebrity highlights with iconic style.

news

How to get a screenshot of a specific window with Rust on Windows?

Writer Matthew Martinez

I would like to know how to take screenshots of a part of a specific window. There may be an overlay on top of the application (a game overlay) that hides what I'm interested in. I would like to find a way to take a screenshot of the application only, ignoring the overlay or what would be on top.

And I wonder if it's possible to optimize it in order to have ~5 screenshots/seconds

For now i tried the screenshots cargo package with the following code :

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()); }
}

But it seem not possible to take screenshot of just a specific window behind an overlay.

I use cargo run --release

The target os is Windows and I'm also developing under Windows.

ps : I convert my image to OpenCV Mat for the next part of my code

3

1 Answer

You can use winapi and user32 repo to get any window screenshot.

Wrong that you had made maybe using onencv library that not working on Windows.

Here's my example code. Let's say we have a window call '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); }
}

you can run it by typing cargo run.

3

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.