uiautomation 源码研究
uiautomation 源码研究
- github https://github.com/leexgone/uiautomation-rs/
- cargo doc https://docs.rs/uiautomation/0.24.0/uiautomation/
结构
项目结构
(略,先不管源码。先看 public api 的结构)
Features
(略,见 README)
包 (Re-exports)
pub use self::errors::Error;
pub use self::errors::Result;
pub use self::core::UIAutomation;
pub use self::core::UIElement;
pub use self::core::UITreeWalker;
pub use self::core::UIMatcher;
模块 (modules)
Demo
github 有个 samples 文件夹,非常不错。这部分详见 ./samples
主要/常用 的 类/模块
见后面章节,后续一个章节一个类/模块
UIAutomation
原型:
// src/core.rs#83
impl UIAutomation {
pub fn new() -> Result<UIAutomation>
// get
pub fn get_focused_element(&self) -> Result<UIElement>
pub fn get_focused_element_build_cache(&self, cache_request: &UICacheRequest) -> Result<UIElement>
pub fn get_root_element(&self) -> Result<UIElement>
pub fn get_root_element_build_cache(&self, cache_request: &UICacheRequest) -> Result<UIElement>
pub fn get_raw_view_walker(&self) -> Result<UITreeWalker>
pub fn get_control_view_condition(&self) -> Result<UICondition>
pub fn get_control_view_walker(&self) -> Result<UITreeWalker>
pub fn get_content_view_condition(&self) -> Result<UICondition>
pub fn get_content_view_walker(&self) -> Result<UITreeWalker>
应用:
fn start_uia_worker(rx: Receiver<UiaMsg>) {
thread::spawn(move || {
// 初始化 uiautomation
let automation = UIAutomation::new().unwrap();
let walker = automation.get_control_view_walker().unwrap();
loop {
match rx.recv() {
Ok(UiaMsg::PrintElement) => {
let _ = get_uia_focused(&walker, &automation, 0);
}
Err(_) => break,
}
}
});
}
UIElement
原型:
// src/core.rs#449
impl UIElement {
find_xxx()
// ...
// get
//
// 环境问题
// VSCode 环境,控制台可能可能会让你按 Alt+Shift+F1, 开启后 VSCode 右下角会显示 "已为屏幕阅读器优化",这种情况下的 vscode 才能获取到信息
// classname: 大部分是空 (浏览器 qq vscode 等空),notepad-- 是 ScintillaEditView,windows notepad 是 RichEditD2DPT
// controltype: 大部分是Edit,windows notepad 是Document,浏览器搜索框是 ComboBox
// name: 窗口名/输入框默认名
//
// cache问题:
// - **实时 vs. 缓存**:`CurrentXXX` 方法每次都实时访问底层数据,`CachedXXX` 方法只返回初始化或上次缓存时的数据。
// - **性能**:缓存方法更快,但有可能不是最新的数据;实时方法更慢,但保证拿到当前状态。
// - **使用场景**:如果只做一次性批量查询,用缓存更高效;如果要跟踪UI的变化,必须用实时方法。
pub fn get_cached_parent(&self) -> Result<UIElement>
pub fn get_cached_children(&self) -> Result<Vec<UIElement>>
pub fn get_runtime_id(&self) -> Result<Vec<i32>>
pub fn get_name(&self) -> Result<String> //
pub fn get_cached_name(&self) -> Result<String>
pub fn get_automation_id(&self) -> Result<String>
pub fn get_cached_automation_id(&self) -> Result<String>
pub fn get_process_id(&self) -> Result<u32>
pub fn get_cached_process_id(&self) -> Result<i32>
pub fn get_classname(&self) -> Result<String> //
pub fn get_cached_classname(&self) -> Result<String>
pub fn get_control_type(&self) -> Result<ControlType> //
pub fn get_cached_control_type(&self) -> Result<ControlType>
pub fn get_localized_control_type(&self) -> Result<String>
pub fn get_cached_localized_control_type(&self) -> Result<String>
pub fn get_accelerator_key(&self) -> Result<String>
pub fn get_cached_accelerator_key(&self) -> Result<String>
pub fn get_access_key(&self) -> Result<String>
pub fn get_cached_access_key(&self) -> Result<String>
// is/has
pub fn has_keyboard_focus(&self) -> Result<bool>
pub fn has_cached_keyboard_focus(&self) -> Result<bool>
pub fn is_keyboard_focusable(&self) -> Result<bool>
pub fn is_cached_keyboard_focusable(&self) -> Result<bool>
pub fn is_enabled(&self) -> Result<bool>
pub fn is_cached_enabled(&self) -> Result<bool>
pub fn get_help_text(&self) -> Result<String>
pub fn get_cached_help_text(&self) -> Result<String>
pub fn get_culture(&self) -> Result<i32>
pub fn get_cached_culture(&self) -> Result<i32>
pub fn is_control_element(&self) -> Result<bool>
pub fn is_cached_control_element(&self) -> Result<bool>
pub fn is_content_element(&self) -> Result<bool>
pub fn is_cached_content_element(&self) -> Result<bool>
pub fn is_password(&self) -> Result<bool>
pub fn is_cached_password(&self) -> Result<bool>
pub fn get_native_window_handle(&self) -> Result<Handle>
pub fn get_cached_native_window_handle(&self) -> Result<Handle>
pub fn get_item_type(&self) -> Result<String>
pub fn get_cached_item_type(&self) -> Result<String>
pub fn is_offscreen(&self) -> Result<bool>
pub fn is_cached_offscreen(&self) -> Result<bool>
pub fn get_orientation(&self) -> Result<OrientationType>
pub fn get_cached_orientation(&self) -> Result<OrientationType>
pub fn get_framework_id(&self) -> Result<String>
pub fn get_cached_framework_id(&self) -> Result<String>
pub fn is_required_for_form(&self) -> Result<bool>
pub fn is_cached_required_for_form(&self) -> Result<bool>
pub fn is_data_valid_for_form(&self) -> Result<bool>
pub fn is_cached_data_valid_for_form(&self) -> Result<bool>
pub fn get_item_status(&self) -> Result<String>
pub fn get_cached_item_status(&self) -> Result<String>
pub fn get_bounding_rectangle(&self) -> Result<Rect>
pub fn get_cached_bounding_rectangle(&self) -> Result<Rect>
pub fn get_labeled_by(&self) -> Result<UIElement>
pub fn get_cached_labeled_by(&self) -> Result<UIElement>
pub fn get_controller_for(&self) -> Result<Vec<UIElement>>
pub fn get_cached_controller_for(&self) -> Result<Vec<UIElement>>
pub fn get_described_by(&self) -> Result<Vec<UIElement>>
pub fn get_cached_described_by(&self) -> Result<Vec<UIElement>>
pub fn get_flows_to(&self) -> Result<Vec<UIElement>>
pub fn get_cached_flows_to(&self) -> Result<Vec<UIElement>>
pub fn get_provider_description(&self) -> Result<String>
pub fn get_cached_provider_description(&self) -> Result<String>
#[cfg(feature = "pattern")]
pub fn get_pattern<T: super::patterns::UIPattern + TryFrom<IUnknown, Error = Error>>(&self) -> Result<T> //
#[cfg(feature = "pattern")]
pub fn get_cached_pattern<T: super::patterns::UIPattern + TryFrom<IUnknown, Error = Error>>(&self) -> Result<T>
pub fn get_clickable_point(&self) -> Result<Option<Point>>
pub fn get_property_value(&self, property: UIProperty) -> Result<Variant>
pub fn get_cached_property_value(&self, property: UIProperty) -> Result<Variant>
pub fn show_context_menu(&self) -> Result<()>
pub fn get_heading_level(&self) -> Result<HeadingLevel>
pub fn get_cached_heading_level(&self) -> Result<HeadingLevel>
pub fn is_dialog(&self) -> Result<bool>
pub fn is_cached_dialog(&self) -> Result<bool>
pub(crate) fn to_elements(elements: IUIAutomationElementArray) -> Result<Vec<UIElement>>
// input类
#[cfg(feature = "input")]
pub fn send_keys(&self, keys: &str, interval: u64) -> Result<()>
#[cfg(feature = "input")]
pub fn hold_send_keys(&self, holdkeys: &str, keys: &str, interval: u64) -> Result<()>
#[cfg(feature = "input")]
pub fn send_text(&self, text: &str, interval: u64) -> Result<()>
#[cfg(all(feature = "input", feature = "clipboard"))]
pub fn send_text_by_clipboard(&self, text: &str) -> Result<()>
#[cfg(feature = "input")]
pub fn click(&self) -> Result<()>
#[cfg(feature = "input")]
pub fn hold_click(&self, holdkeys: &str) -> Result<()>
#[cfg(feature = "input")]
pub fn double_click(&self) -> Result<()>
#[cfg(feature = "input")]
pub fn right_click(&self) -> Result<()>
#[cfg(feature = "input")]
pub fn drag_to(&self, target: &UIElement) -> Result<()>
pub fn get_click_point(&self) -> Result<Point>
}
Walker
walker.get_first_child
可以用来遍历ui树
UITextPattern
Text
uiautomation-rs/crates/uiautomation/src/actions.rs
有获取光标位置的api
链接到当前文件 0
没有文件链接到当前文件