#[cfg(not(target_os = "windows"))]
fn main() -> Result<(), computeruse::AutomationError> {
eprintln!("This example is currently Windows-only.");
Ok(())
}
#[cfg(target_os = "windows")]
use std::time::{Duration, Instant};
#[cfg(target_os = "windows")]
use computeruse::{AutomationError, Desktop, FontStyle, TextPosition};
#[cfg(target_os = "windows")]
use tokio::time::sleep;
#[cfg(target_os = "windows")]
use windows::Win32::Foundation::POINT;
#[cfg(target_os = "windows")]
use windows::Win32::UI::WindowsAndMessaging::GetCursorPos;
#[cfg(target_os = "windows")]
#[derive(Debug)]
struct CachedElement {
element: computeruse::UIElement,
bounds: (f64, f64, f64, f64), id: String,
name: String,
}
#[cfg(target_os = "windows")]
#[tokio::main]
async fn main() -> Result<(), AutomationError> {
println!("⚡ Fast Real-Time Hover Highlighting");
println!("{}", "=".repeat(50));
let desktop = Desktop::new(false, false)?;
println!("\n🚀 Starting optimized hover mode...");
println!(" Move your mouse around Calculator to see fast highlighting!");
println!(" Press Ctrl+C to exit");
let mut cached_elements: Vec<CachedElement> = Vec::new();
let mut last_highlighted_id: Option<String> = None;
let mut last_highlight_handle: Option<computeruse::HighlightHandle> = None;
let mut last_update = Instant::now();
let mut last_cursor_pos = POINT { x: -1, y: -1 };
let font_style = FontStyle {
size: 12,
bold: true,
color: 0x000000, };
let cache_refresh_interval = Duration::from_secs(2);
loop {
let now = Instant::now();
let mut cursor_pos = POINT { x: 0, y: 0 };
unsafe {
let _ = GetCursorPos(&mut cursor_pos);
}
if cursor_pos.x == last_cursor_pos.x && cursor_pos.y == last_cursor_pos.y {
sleep(Duration::from_millis(100)).await;
continue;
}
last_cursor_pos = cursor_pos;
if cached_elements.is_empty() || (now.duration_since(last_update) > cache_refresh_interval)
{
cached_elements.clear();
let apps = desktop.applications()?;
if let Some(calculator) = apps.iter().find(|app| {
app.name()
.unwrap_or_default()
.to_lowercase()
.contains("calculator")
}) {
for selector in &["role:Button", "role:MenuItem"] {
if let Ok(locator) = calculator.locator(*selector) {
if let Ok(elements) = locator.all(None, None).await {
for element in elements {
if let Ok(bounds) = element.bounds() {
let id = element
.id()
.unwrap_or_else(|| format!("elem_{:p}", &element));
let name = element.name().unwrap_or("Element".to_string());
cached_elements.push(CachedElement {
element,
bounds,
id,
name,
});
}
}
}
}
}
}
last_update = now;
if !cached_elements.is_empty() {
println!(
" 🔄 Cached {} interactive elements",
cached_elements.len()
);
}
}
let mut found_element_id = None;
let cursor_x = cursor_pos.x as f64;
let cursor_y = cursor_pos.y as f64;
for cached in &cached_elements {
let (x, y, width, height) = cached.bounds;
if cursor_x >= x && cursor_x <= (x + width) && cursor_y >= y && cursor_y <= (y + height)
{
found_element_id = Some(cached.id.clone());
break;
}
}
if found_element_id != last_highlighted_id {
if let Some(handle) = last_highlight_handle.take() {
handle.close();
}
if let Some(element_id) = &found_element_id {
if let Some(cached) = cached_elements.iter().find(|c| &c.id == element_id) {
let text = format!("🎯 {}", cached.name);
if let Ok(handle) = cached.element.highlight(
Some(0x0000FF), None, Some(&text), Some(TextPosition::Top), Some(font_style.clone()), ) {
last_highlight_handle = Some(handle);
println!(" ⚡ {}", cached.name);
}
}
}
last_highlighted_id = found_element_id;
}
sleep(Duration::from_millis(100)).await;
}
}