win_wrap/uia/
automation.rs

1/*
2 * Copyright (c) 2024. The RigelA open source project team and
3 * its contributors reserve all rights.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and limitations under the License.
12 */
13
14use 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/// UIAutomation接口本地封装
30#[derive(Clone, Debug)]
31pub struct UiAutomation(Arc<IUIAutomation6>);
32
33impl UiAutomation {
34    /**
35    创建一个UiAutomation对象。
36    */
37    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    /**
47    从MSAA的Accessible对象获取UI元素。
48    `obj` 一个MSAA的Accessible对象。
49    */
50    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    /**
68    获取UI根元素。
69    */
70    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    /**
76    获取UI焦点元素。
77    */
78    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    /// 根据窗口句柄获取ui元素
87    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    /// 根据坐标获取ui元素
99    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    /**
109    创建事件处理器组。
110    */
111    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    /**
121    添加事件处理器组,以便于处理各种事件。
122    `element` 要监听的元素。
123    `group` 通过调用create_event_handler_group函数返回的事件处理器组。
124    */
125    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    /**
137    注册一个焦点改变时的通知函数。
138    处理函数运行在单独的子线程中。
139    `func` 用于接收事件的函数。
140    */
141    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    /**
152    移除已经注册的所有监听器。
153    */
154    pub fn remove_all_event_listeners(&self) {
155        unsafe { self.0.RemoveAllEventHandlers() }.unwrap_or(());
156    }
157
158    /**
159    移除一个事件处理器组。
160    `group` 一个事件处理器组对象的引用。
161    */
162    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 {}