Files
kevisual-rust/src/main.rs

120 lines
3.3 KiB
Rust

use windows::{
core::*,
Win32::Foundation::{HWND, LPARAM},
Win32::UI::WindowsAndMessaging::{
EnumWindows, GetForegroundWindow, GetWindowTextW, GetWindowTextLengthW,
GetWindowThreadProcessId, IsWindowVisible,
},
Win32::System::Threading::{OpenProcess, QueryFullProcessImageNameW, PROCESS_QUERY_INFORMATION, PROCESS_NAME_WIN32},
};
use serde::Serialize;
use serde_json;
#[derive(Serialize)]
struct WindowInfo {
hwnd: String,
title: String,
pid: u32,
process_name: String,
is_active: bool,
}
#[derive(Serialize)]
struct WindowList {
active_window: Option<WindowInfo>,
all_windows: Vec<WindowInfo>,
}
fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
unsafe {
// 获取当前激活窗口
let active_hwnd = GetForegroundWindow();
let active_info = if !active_hwnd.is_invalid() {
Some(get_window_info(active_hwnd))
} else {
None
};
// 获取所有窗口
let mut all_windows: Vec<WindowInfo> = Vec::new();
EnumWindows(
Some(enum_windows_callback),
LPARAM(&mut all_windows as *mut Vec<WindowInfo> as isize),
)?;
let result = WindowList {
active_window: active_info,
all_windows,
};
let json = serde_json::to_string_pretty(&result)
.map_err(|e| Box::new(e) as Box<dyn std::error::Error>)?;
println!("{}", json);
Ok(())
}
}
unsafe fn get_window_info(hwnd: HWND) -> WindowInfo {
// 获取窗口标题
let len = GetWindowTextLengthW(hwnd);
let title = if len > 0 {
let mut buffer = vec![0u16; len as usize + 1];
let actual_len = GetWindowTextW(hwnd, &mut buffer);
if actual_len > 0 {
String::from_utf16_lossy(&buffer[..actual_len as usize])
} else {
String::new()
}
} else {
String::new()
};
// 获取进程ID
let mut pid: u32 = 0;
GetWindowThreadProcessId(hwnd, Some(&mut pid));
// 获取进程名称
let process_name = get_process_name(pid).unwrap_or_else(|_| String::from("Unknown"));
// 检查是否为激活窗口
let is_active = hwnd == GetForegroundWindow();
WindowInfo {
hwnd: format!("{:?}", hwnd.0),
title,
pid,
process_name,
is_active,
}
}
unsafe fn get_process_name(pid: u32) -> Result<String> {
let process_handle = OpenProcess(PROCESS_QUERY_INFORMATION, false, pid)?;
let mut buffer = vec![0u16; 1024];
let mut size = buffer.len() as u32;
QueryFullProcessImageNameW(process_handle, PROCESS_NAME_WIN32, PWSTR(buffer.as_mut_ptr()), &mut size)?;
let path = String::from_utf16_lossy(&buffer[..size as usize]);
// 提取文件名
let process_name = path.split('\\').last().unwrap_or(&path).to_string();
Ok(process_name)
}
unsafe extern "system" fn enum_windows_callback(
hwnd: HWND,
lparam: LPARAM,
) -> windows::Win32::Foundation::BOOL {
if IsWindowVisible(hwnd).as_bool() {
let len = GetWindowTextLengthW(hwnd);
if len > 0 {
let windows = &mut *(lparam.0 as *mut Vec<WindowInfo>);
windows.push(get_window_info(hwnd));
}
}
windows::Win32::Foundation::TRUE
}