win_wrap/uia/
automation.rs1use crate::{
15 common::Result,
16 msaa::object::AccessibleObject,
17 uia::{
18 element::UiAutomationElement,
19 event::{OnFocusChangedCallback, UiAutomationEventHandlerGroup},
20 },
21};
22use std::sync::Arc;
23use windows::Win32::{
24 Foundation::{HWND, POINT},
25 System::Com::{CoCreateInstance, CLSCTX_ALL},
26 UI::Accessibility::{CUIAutomation8, IUIAutomation6, IUIAutomationFocusChangedEventHandler},
27};
28
29#[derive(Clone, Debug)]
31pub struct UiAutomation(Arc<IUIAutomation6>);
32
33impl UiAutomation {
34 pub fn new() -> Self {
38 let automation =
39 unsafe { CoCreateInstance::<_, IUIAutomation6>(&CUIAutomation8, None, CLSCTX_ALL) }
40 .expect("Can't create the ui automation.");
41 UiAutomation {
42 0: automation.into(),
43 }
44 }
45
46 pub fn get_element_from_accessible_object(
51 &self,
52 obj: &AccessibleObject,
53 ) -> Result<UiAutomationElement> {
54 let element = match unsafe {
55 self.0
56 .ElementFromIAccessible(obj.get_raw(), obj.get_child_id())
57 } {
58 Ok(o) => o,
59 Err(e) => return Err(e),
60 };
61 Ok(UiAutomationElement::obtain(
62 Arc::downgrade(&self.0),
63 element,
64 ))
65 }
66
67 pub fn get_root_element(&self) -> UiAutomationElement {
71 let el = unsafe { self.0.GetRootElement() }.expect("Can't get the root element.");
72 UiAutomationElement::obtain(Arc::downgrade(&self.0), el)
73 }
74
75 pub fn get_focused_element(&self) -> Result<UiAutomationElement> {
79 let el = match unsafe { self.0.GetFocusedElement() } {
80 Err(e) => return Err(e),
81 Ok(o) => o,
82 };
83 Ok(UiAutomationElement::obtain(Arc::downgrade(&self.0), el))
84 }
85
86 pub fn element_from_handle(&self, h_wnd: HWND) -> Option<UiAutomationElement> {
88 let el = unsafe { self.0.ElementFromHandle(h_wnd) };
89 if el.is_err() {
90 return None;
91 }
92 Some(UiAutomationElement::obtain(
93 Arc::downgrade(&self.0),
94 el.unwrap(),
95 ))
96 }
97
98 pub fn element_from_point(&self, x: i32, y: i32) -> Option<UiAutomationElement> {
100 let el = unsafe {
101 self.0
102 .ElementFromPoint(POINT { x, y })
103 .expect("Can't get the element from point.")
104 };
105 Some(UiAutomationElement::obtain(Arc::downgrade(&self.0), el))
106 }
107
108 pub fn create_event_handler_group(&self) -> UiAutomationEventHandlerGroup {
112 unsafe {
113 UiAutomationEventHandlerGroup::obtain(
114 Arc::downgrade(&self.0),
115 &self.0.CreateEventHandlerGroup().unwrap(),
116 )
117 }
118 }
119
120 pub fn add_event_handler_group(
126 &self,
127 element: &UiAutomationElement,
128 group: &UiAutomationEventHandlerGroup,
129 ) -> Result<()> {
130 unsafe {
131 self.0
132 .AddEventHandlerGroup(element.get_raw(), group.get_raw())
133 }
134 }
135
136 pub fn add_focus_changed_listener<CB>(&self, func: CB)
142 where
143 CB: Fn(UiAutomationElement) -> () + 'static,
144 {
145 let handler: IUIAutomationFocusChangedEventHandler =
146 OnFocusChangedCallback::new(func, Arc::downgrade(&self.0)).into();
147 unsafe { self.0.AddFocusChangedEventHandler(None, &handler) }
148 .expect("Can't add the focus changed listener.")
149 }
150
151 pub fn remove_all_event_listeners(&self) {
155 unsafe { self.0.RemoveAllEventHandlers() }.unwrap_or(());
156 }
157
158 pub fn remove_event_handler_group(
163 &self,
164 element: &UiAutomationElement,
165 group: &UiAutomationEventHandlerGroup,
166 ) {
167 unsafe {
168 self.0
169 .RemoveEventHandlerGroup(element.get_raw(), group.get_raw())
170 }
171 .unwrap_or(())
172 }
173}
174
175unsafe impl Sync for UiAutomation {}
176
177unsafe impl Send for UiAutomation {}