Skip to content

Commit ccd3c64

Browse files
authored
feat: windows utils 添加单元测试 (#212)
* feat: windows utils 添加单元测试 * chore: 修改版本号
1 parent 4024152 commit ccd3c64

File tree

5 files changed

+166
-7
lines changed

5 files changed

+166
-7
lines changed

Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "xcap"
3-
version = "0.4.0"
3+
version = "0.4.1"
44
edition = "2021"
55
description = "XCap is a cross-platform screen capture library written in Rust. It supports Linux (X11, Wayland), MacOS, and Windows. XCap supports screenshot and video recording (WIP)."
66
license = "Apache-2.0"
@@ -33,8 +33,8 @@ objc2-core-media = "0.3"
3333
objc2-core-video = "0.3"
3434

3535
[target.'cfg(target_os = "windows")'.dependencies]
36-
widestring = "1.1"
37-
windows = { version = "0.59", features = [
36+
widestring = "1.2"
37+
windows = { version = "0.60", features = [
3838
"Win32_Foundation",
3939
"Win32_Graphics_Gdi",
4040
"Win32_Graphics_Dwm",
@@ -61,3 +61,4 @@ libwayshot = "0.3"
6161

6262
[dev-dependencies]
6363
fs_extra = "1.3"
64+
windows = { version = "0.60", features = ["Win32_UI_HiDpi"] }

src/windows/capture.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,3 +215,31 @@ pub fn capture_window(hwnd: HWND, scale_factor: f32) -> XCapResult<RgbaImage> {
215215
.to_rgba8())
216216
}
217217
}
218+
219+
#[cfg(test)]
220+
mod tests {
221+
use super::*;
222+
use windows::Win32::UI::WindowsAndMessaging::GetDesktopWindow;
223+
224+
#[test]
225+
fn test_capture_monitor() {
226+
let result = capture_monitor(0, 0, 100, 100);
227+
assert!(result.is_ok());
228+
let image = result.unwrap();
229+
assert_eq!(image.width(), 100);
230+
assert_eq!(image.height(), 100);
231+
}
232+
233+
#[test]
234+
fn test_capture_window() {
235+
unsafe {
236+
let hwnd = GetDesktopWindow();
237+
let result = capture_window(hwnd, 1.0);
238+
assert!(result.is_ok());
239+
240+
let image = result.unwrap();
241+
assert!(image.width() > 0);
242+
assert!(image.height() > 0);
243+
}
244+
}
245+
}

src/windows/impl_monitor.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ use image::RgbaImage;
44
use scopeguard::guard;
55
use widestring::U16CString;
66
use windows::{
7-
core::{s, w, HRESULT, PCWSTR},
7+
core::{s, w, BOOL, HRESULT, PCWSTR},
88
Win32::{
99
Devices::Display::DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL,
10-
Foundation::{GetLastError, BOOL, LPARAM, POINT, RECT, TRUE},
10+
Foundation::{GetLastError, LPARAM, POINT, RECT, TRUE},
1111
Graphics::Gdi::{
1212
CreateDCW, DeleteDC, EnumDisplayMonitors, EnumDisplaySettingsW, GetDeviceCaps,
1313
GetMonitorInfoW, MonitorFromPoint, DESKTOPHORZRES, DEVMODEW, DMDO_180, DMDO_270,

src/windows/impl_window.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ use std::{ffi::c_void, mem, ptr};
44
use image::RgbaImage;
55
use widestring::U16CString;
66
use windows::{
7-
core::{HSTRING, PCWSTR},
7+
core::{BOOL, HSTRING, PCWSTR},
88
Win32::{
9-
Foundation::{GetLastError, BOOL, HANDLE, HWND, LPARAM, MAX_PATH, RECT, TRUE},
9+
Foundation::{GetLastError, HANDLE, HWND, LPARAM, MAX_PATH, RECT, TRUE},
1010
Graphics::{
1111
Dwm::{DwmGetWindowAttribute, DWMWA_CLOAKED, DWMWA_EXTENDED_FRAME_BOUNDS},
1212
Gdi::{IsRectEmpty, MonitorFromWindow, MONITOR_DEFAULTTONEAREST},

src/windows/utils.rs

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,3 +242,133 @@ pub fn get_window_info(hwnd: HWND) -> XCapResult<WINDOWINFO> {
242242

243243
Ok(window_info)
244244
}
245+
246+
#[cfg(test)]
247+
mod tests {
248+
use windows::Win32::Foundation::POINT;
249+
use windows::Win32::Graphics::Gdi::{
250+
EnumDisplaySettingsW, GetMonitorInfoW, MonitorFromPoint, DEVMODEW, ENUM_CURRENT_SETTINGS,
251+
MONITORINFO, MONITOR_DEFAULTTOPRIMARY,
252+
};
253+
use windows::Win32::System::Threading::{
254+
GetCurrentProcessId, PROCESS_QUERY_LIMITED_INFORMATION,
255+
};
256+
use windows::Win32::UI::WindowsAndMessaging::GetDesktopWindow;
257+
258+
use super::*;
259+
260+
/// 特别说明
261+
/// 以下测试均以 windows11 作为测试环境
262+
#[test]
263+
fn test_get_build_number() {
264+
let build = get_build_number();
265+
println!("build {}", build);
266+
assert!(build == 26100, "build number should be 26100");
267+
}
268+
269+
#[test]
270+
fn test_get_os_major_version() {
271+
let version = get_os_major_version();
272+
assert!(version == 11, "os major version should be 11");
273+
}
274+
275+
#[test]
276+
fn test_bgra_to_rgba() {
277+
let input = vec![0, 1, 2, 255, 4, 5, 6, 255];
278+
let output = bgra_to_rgba(input);
279+
assert_eq!(output, vec![2, 1, 0, 255, 6, 5, 4, 255]);
280+
}
281+
282+
#[test]
283+
fn test_bgra_to_rgba_image() {
284+
let width = 2;
285+
let height = 1;
286+
let buffer = vec![0, 1, 2, 255, 4, 5, 6, 255];
287+
let result = bgra_to_rgba_image(width, height, buffer);
288+
289+
assert!(result.is_ok());
290+
291+
let image = result.unwrap();
292+
assert_eq!(image.width(), width);
293+
assert_eq!(image.height(), height);
294+
}
295+
296+
#[test]
297+
fn test_get_process_is_dpi_awareness() {
298+
// // Modify the program's DPI awareness. You can set the value to PROCESS_DPI_UNAWARE or PROCESS_PER_MONITOR_DPI_AWARE for testing.
299+
// SetProcessDpiAwareness(PROCESS_DPI_UNAWARE).unwrap();
300+
301+
// let process = GetCurrentProcess();
302+
// let is_dpi_awareness = get_process_is_dpi_awareness(process).unwrap();
303+
304+
// assert!(!is_dpi_awareness);
305+
}
306+
#[test]
307+
fn test_load_library() {
308+
let scope_guard_hmodule = load_library(w!("Shcore.dll")).unwrap();
309+
310+
assert!(!scope_guard_hmodule.is_invalid());
311+
}
312+
313+
#[test]
314+
fn test_open_process() {
315+
unsafe {
316+
let process_id = GetCurrentProcessId();
317+
let scope_guard_handle =
318+
open_process(PROCESS_QUERY_LIMITED_INFORMATION, true, process_id).unwrap();
319+
320+
assert!(!scope_guard_handle.is_invalid());
321+
}
322+
}
323+
324+
unsafe fn get_monitor_info_ex_w() -> MONITORINFOEXW {
325+
let point = POINT { x: 0, y: 0 };
326+
let h_monitor = MonitorFromPoint(point, MONITOR_DEFAULTTOPRIMARY);
327+
let mut monitor_info_ex_w = MONITORINFOEXW::default();
328+
monitor_info_ex_w.monitorInfo.cbSize = mem::size_of::<MONITORINFOEXW>() as u32;
329+
let monitor_info_ex_w_ptr =
330+
&mut monitor_info_ex_w as *mut MONITORINFOEXW as *mut MONITORINFO;
331+
332+
// https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-getmonitorinfoa
333+
GetMonitorInfoW(h_monitor, monitor_info_ex_w_ptr)
334+
.ok()
335+
.unwrap();
336+
337+
monitor_info_ex_w
338+
}
339+
340+
#[test]
341+
fn test_get_monitor_config() {
342+
unsafe {
343+
let monitor_info_ex_w = get_monitor_info_ex_w();
344+
// 获取显示器配置信息
345+
let monitor_config = get_monitor_config(monitor_info_ex_w).unwrap();
346+
347+
assert!(!monitor_config.monitorFriendlyDeviceName.is_empty());
348+
}
349+
}
350+
351+
#[test]
352+
fn test_get_window_info() {
353+
unsafe {
354+
let monitor_info_ex_w = get_monitor_info_ex_w();
355+
let mut dev_mode_w = DEVMODEW {
356+
dmSize: mem::size_of::<DEVMODEW>() as u16,
357+
..DEVMODEW::default()
358+
};
359+
EnumDisplaySettingsW(
360+
PCWSTR(monitor_info_ex_w.szDevice.as_ptr()),
361+
ENUM_CURRENT_SETTINGS,
362+
&mut dev_mode_w,
363+
)
364+
.ok()
365+
.unwrap();
366+
367+
let hwnd = GetDesktopWindow();
368+
let window_info = get_window_info(hwnd).unwrap();
369+
let width = (window_info.rcWindow.right - window_info.rcWindow.left) as u32;
370+
371+
assert!(width == dev_mode_w.dmPelsWidth);
372+
}
373+
}
374+
}

0 commit comments

Comments
 (0)