初始化项目结构,添加基本依赖和窗口信息获取功能
This commit is contained in:
120
src/main.rs
Normal file
120
src/main.rs
Normal file
@@ -0,0 +1,120 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user