#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] use eframe::{egui, App, Frame, NativeOptions}; use egui::{FontFamily, FontId, RichText, Vec2, Color32, Rounding, Stroke}; use std::sync::{Arc, Mutex}; use std::thread; use std::time::{Duration, Instant}; use winapi::um::winuser::{GetCursorPos, SetCursorPos, INPUT, INPUT_MOUSE, MOUSEINPUT, SendInput}; use winapi::shared::windef::POINT; use rand::Rng; use chrono::Local; // 应用程序状态 #[derive(Clone)] struct AppState { running: Arc>, interval: Arc>, // 间隔秒数 log_message: Arc>, last_action: Arc>, } impl AppState { fn new() -> Self { AppState { running: Arc::new(Mutex::new(false)), interval: Arc::new(Mutex::new(30)), log_message: Arc::new(Mutex::new(String::from("准备就绪"))), last_action: Arc::new(Mutex::new(Instant::now())), } } } // 模拟鼠标微动 fn simulate_mouse_move() -> Result<(i32, i32), String> { unsafe { let mut point = POINT { x: 0, y: 0 }; if GetCursorPos(&mut point) == 0 { return Err("无法获取鼠标位置".to_string()); } let current_x = point.x; let current_y = point.y; // 随机微动 1-3 像素 let mut rng = rand::thread_rng(); let offset_x: i32 = if rng.gen_bool(0.5) { 1 } else { -1 } * rng.gen_range(1..=3); let offset_y: i32 = if rng.gen_bool(0.5) { 1 } else { -1 } * rng.gen_range(1..=3); let new_x = current_x + offset_x; let new_y = current_y + offset_y; // 移动鼠标到新位置 if SetCursorPos(new_x, new_y) == 0 { return Err("无法移动鼠标".to_string()); } // 短暂延迟后移回原位 thread::sleep(Duration::from_millis(100)); if SetCursorPos(current_x, current_y) == 0 { return Err("无法恢复鼠标位置".to_string()); } Ok((offset_x, offset_y)) } } // 后台工作线程 fn worker_thread(state: AppState) { let mut last_move = Instant::now(); loop { let running = *state.running.lock().unwrap(); if !running { thread::sleep(Duration::from_millis(100)); continue; } let interval = *state.interval.lock().unwrap(); let elapsed = last_move.elapsed().as_secs(); if elapsed >= interval { match simulate_mouse_move() { Ok((offset_x, offset_y)) => { let time_str = Local::now().format("%H:%M:%S").to_string(); let msg = format!("{} - 鼠标微动: ({}, {})", time_str, offset_x, offset_y); *state.log_message.lock().unwrap() = msg; } Err(e) => { let time_str = Local::now().format("%H:%M:%S").to_string(); let msg = format!("{} - 错误: {}", time_str, e); *state.log_message.lock().unwrap() = msg; } } last_move = Instant::now(); } thread::sleep(Duration::from_millis(100)); } } // 主应用程序结构 struct AntiLockScreenApp { state: AppState, interval_input: String, } impl AntiLockScreenApp { fn new() -> Self { AntiLockScreenApp { state: AppState::new(), interval_input: "30".to_string(), } } } impl App for AntiLockScreenApp { fn update(&mut self, ctx: &egui::Context, _frame: &mut Frame) { // 中文字体在第一次更新时加载 static FONT_LOADED: std::sync::Once = std::sync::Once::new(); FONT_LOADED.call_once(|| { let mut fonts = egui::FontDefinitions::default(); // 尝试从系统加载中文字体 let font_paths = [ "C:/Windows/Fonts/msyh.ttc", // 微软雅黑 "C:/Windows/Fonts/simhei.ttf", // 黑体 "C:/Windows/Fonts/simsun.ttc", // 宋体 "C:/Windows/Fonts/msgothic.ttc", // 日文哥特体(备用) ]; for font_path in &font_paths { if let Ok(font_data) = std::fs::read(font_path) { fonts.font_data.insert( "chinese_font".to_owned(), egui::FontData::from_owned(font_data), ); // 更新字体族 fonts.families.get_mut(&egui::FontFamily::Proportional) .unwrap() .insert(0, "chinese_font".to_owned()); fonts.families.get_mut(&egui::FontFamily::Monospace) .unwrap() .push("chinese_font".to_owned()); ctx.set_fonts(fonts); break; } } }); // 主窗口 egui::CentralPanel::default().show(ctx, |ui| { ui.vertical_centered(|ui| { ui.add_space(20.0); // 标题 ui.label( RichText::new("防止锁屏工具") .font(FontId::new(24.0, FontFamily::Proportional)) .strong() .color(Color32::from_rgb(51, 51, 51)) ); ui.add_space(15.0); // 说明文字 ui.label( RichText::new("点击开始后,程序会定期模拟鼠标微动") .font(FontId::new(12.0, FontFamily::Proportional)) .color(Color32::from_rgb(102, 102, 102)) ); ui.label( RichText::new("防止系统自动锁屏") .font(FontId::new(12.0, FontFamily::Proportional)) .color(Color32::from_rgb(102, 102, 102)) ); ui.add_space(20.0); // 间隔设置 ui.horizontal(|ui| { ui.label( RichText::new("微动间隔(秒):") .font(FontId::new(12.0, FontFamily::Proportional)) ); let running = *self.state.running.lock().unwrap(); ui.add_enabled_ui(!running, |ui| { ui.text_edit_singleline(&mut self.interval_input); }); }); ui.add_space(15.0); // 状态显示 let running = *self.state.running.lock().unwrap(); let status_text = if running { "状态: 运行中" } else { "状态: 已停止" }; let status_color = if running { Color32::from_rgb(76, 175, 80) } else { Color32::from_rgb(244, 67, 54) }; ui.label( RichText::new(status_text) .font(FontId::new(14.0, FontFamily::Proportional)) .color(status_color) ); ui.add_space(10.0); // 日志消息 let log_msg = self.state.log_message.lock().unwrap().clone(); ui.label( RichText::new(&log_msg) .font(FontId::new(10.0, FontFamily::Proportional)) .color(Color32::from_rgb(128, 128, 128)) ); ui.add_space(20.0); // 按钮区域 ui.horizontal(|ui| { // 开始按钮 let start_btn = ui.add_sized( [100.0, 40.0], egui::Button::new( RichText::new("开始") .font(FontId::new(14.0, FontFamily::Proportional)) .color(Color32::WHITE) ) .fill(Color32::from_rgb(76, 175, 80)) .rounding(Rounding::same(5.0)) ); if start_btn.clicked() && !running { // 解析间隔时间 if let Ok(interval) = self.interval_input.parse::() { if interval >= 10 && interval <= 300 { *self.state.interval.lock().unwrap() = interval; *self.state.running.lock().unwrap() = true; *self.state.log_message.lock().unwrap() = "防止锁屏已启动".to_string(); } else { *self.state.log_message.lock().unwrap() = "间隔必须在10-300秒之间".to_string(); } } else { *self.state.log_message.lock().unwrap() = "请输入有效的数字".to_string(); } } ui.add_space(20.0); // 停止按钮 let stop_btn = ui.add_sized( [100.0, 40.0], egui::Button::new( RichText::new("停止") .font(FontId::new(14.0, FontFamily::Proportional)) .color(Color32::WHITE) ) .fill(Color32::from_rgb(244, 67, 54)) .rounding(Rounding::same(5.0)) ); if stop_btn.clicked() && running { *self.state.running.lock().unwrap() = false; *self.state.log_message.lock().unwrap() = "防止锁屏已停止".to_string(); } }); }); }); // 请求连续更新以刷新UI ctx.request_repaint_after(Duration::from_millis(100)); } } fn main() -> Result<(), eframe::Error> { // 启动后台工作线程 let state = AppState::new(); let worker_state = state.clone(); thread::spawn(move || { worker_thread(worker_state); }); // 应用程序选项 let options = NativeOptions { viewport: egui::ViewportBuilder::default() .with_inner_size([400.0, 280.0]) .with_resizable(false), ..Default::default() }; // 运行应用程序 eframe::run_native( "防止锁屏工具", options, Box::new(|_cc| Box::new(AntiLockScreenApp::new())), ) }