win_wrap/uia/
automation.rsuse crate::{
common::Result,
msaa::object::AccessibleObject,
uia::{
element::UiAutomationElement,
event::{OnFocusChangedCallback, UiAutomationEventHandlerGroup},
},
};
use std::sync::Arc;
use windows::Win32::{
Foundation::{HWND, POINT},
System::Com::{CoCreateInstance, CLSCTX_ALL},
UI::Accessibility::{CUIAutomation8, IUIAutomation6, IUIAutomationFocusChangedEventHandler},
};
#[derive(Clone, Debug)]
pub struct UiAutomation(Arc<IUIAutomation6>);
impl UiAutomation {
pub fn new() -> Self {
let automation =
unsafe { CoCreateInstance::<_, IUIAutomation6>(&CUIAutomation8, None, CLSCTX_ALL) }
.expect("Can't create the ui automation.");
UiAutomation {
0: automation.into(),
}
}
pub fn get_element_from_accessible_object(
&self,
obj: &AccessibleObject,
) -> Result<UiAutomationElement> {
let element = match unsafe {
self.0
.ElementFromIAccessible(obj.get_raw(), obj.get_child_id())
} {
Ok(o) => o,
Err(e) => return Err(e),
};
Ok(UiAutomationElement::obtain(
Arc::downgrade(&self.0),
element,
))
}
pub fn get_root_element(&self) -> UiAutomationElement {
let el = unsafe { self.0.GetRootElement() }.expect("Can't get the root element.");
UiAutomationElement::obtain(Arc::downgrade(&self.0), el)
}
pub fn get_focused_element(&self) -> Result<UiAutomationElement> {
let el = match unsafe { self.0.GetFocusedElement() } {
Err(e) => return Err(e),
Ok(o) => o,
};
Ok(UiAutomationElement::obtain(Arc::downgrade(&self.0), el))
}
pub fn element_from_handle(&self, h_wnd: HWND) -> Option<UiAutomationElement> {
let el = unsafe { self.0.ElementFromHandle(h_wnd) };
if el.is_err() {
return None;
}
Some(UiAutomationElement::obtain(
Arc::downgrade(&self.0),
el.unwrap(),
))
}
pub fn element_from_point(&self, x: i32, y: i32) -> Option<UiAutomationElement> {
let el = unsafe {
self.0
.ElementFromPoint(POINT { x, y })
.expect("Can't get the element from point.")
};
Some(UiAutomationElement::obtain(Arc::downgrade(&self.0), el))
}
pub fn create_event_handler_group(&self) -> UiAutomationEventHandlerGroup {
unsafe {
UiAutomationEventHandlerGroup::obtain(
Arc::downgrade(&self.0),
&self.0.CreateEventHandlerGroup().unwrap(),
)
}
}
pub fn add_event_handler_group(
&self,
element: &UiAutomationElement,
group: &UiAutomationEventHandlerGroup,
) -> Result<()> {
unsafe {
self.0
.AddEventHandlerGroup(element.get_raw(), group.get_raw())
}
}
pub fn add_focus_changed_listener<CB>(&self, func: CB)
where
CB: Fn(UiAutomationElement) -> () + 'static,
{
let handler: IUIAutomationFocusChangedEventHandler =
OnFocusChangedCallback::new(func, Arc::downgrade(&self.0)).into();
unsafe { self.0.AddFocusChangedEventHandler(None, &handler) }
.expect("Can't add the focus changed listener.")
}
pub fn remove_all_event_listeners(&self) {
unsafe { self.0.RemoveAllEventHandlers() }.unwrap_or(());
}
pub fn remove_event_handler_group(
&self,
element: &UiAutomationElement,
group: &UiAutomationEventHandlerGroup,
) {
unsafe {
self.0
.RemoveEventHandlerGroup(element.get_raw(), group.get_raw())
}
.unwrap_or(())
}
}
unsafe impl Sync for UiAutomation {}
unsafe impl Send for UiAutomation {}