Bagikan melalui


Menerapkan Penyedia Automasi UI Server-Side

Topik ini menjelaskan cara mengimplementasikan penyedia Microsoft UI Automation sisi server untuk kontrol kustom yang ditulis dalam C++. Hal ini berisi bagian-bagian berikut:

Untuk contoh kode yang menunjukkan cara mengimplementasikan penyedia sisi server, lihat Topik Panduan untuk Penyedia Automasi UI.

Struktur Pohon Penyedia

Anda harus menerapkan penyedia UIA untuk setiap elemen UI yang perlu dapat diakses oleh klien UIA.

Misalnya, setiap elemen harus mengimplementasikan IRawElementProviderFragment sementara elemen akar aplikasi harus mengimplementasikan IRawElementProviderFragmentRoot. Selain itu, setiap elemen penyedia harus menautkan ke:

  • induk
  • elemen penyedia sebelumnya
  • elemen penyedia berikutnya
  • anak penyedia pertama
  • anak penyedia terakhir

Antarmuka Penyedia

Antarmuka Model Objek Komponen (COM) berikut menyediakan fungsionalitas untuk kontrol kustom. Untuk menyediakan fungsionalitas dasar, setiap penyedia Automation UI harus menerapkan setidaknya antarmuka IRawElementProviderSimple . Antarmuka IRawElementProviderFragment dan IRawElementProviderFragmentRoot bersifat opsional, tetapi harus diimplementasikan untuk elemen dalam kontrol yang kompleks untuk menyediakan fungsionalitas tambahan.

Antarmuka Deskripsi
IRawElementProviderSimple Menyediakan fungsionalitas dasar untuk kontrol yang dihosting di jendela, termasuk dukungan untuk pola kontrol dan properti.
IRawElementProviderFragment Menambahkan fungsionalitas untuk elemen dalam kontrol yang kompleks, termasuk menavigasi dalam fragmen, mengatur fokus, dan mengembalikan persegi panjang pembatas elemen.
IRawElementProviderFragmentRoot Menambahkan fungsionalitas untuk elemen akar dalam kontrol yang kompleks, termasuk menemukan elemen turunan pada koordinat yang ditentukan dan mengatur status fokus untuk seluruh kontrol.

 

Catatan

Di UI Automation API untuk kode terkelola, antarmuka ini membentuk hierarki pewarisan. Ini tidak terjadi di C++, di mana antarmukanya benar-benar terpisah.

 

Antarmuka berikut menyediakan fungsionalitas tambahan tetapi implementasinya bersifat opsional.

Antarmuka Deskripsi
IRawElementProviderAdviseEvents Memungkinkan penyedia untuk melacak permintaan kejadian.
IRawElementProviderHwndOverride Memungkinkan reposisi elemen berbasis jendela di pohon Automation UI dari fragmen.

 

Fungsionalitas yang Diperlukan untuk Penyedia Automasi UI

Untuk berkomunikasi dengan Automation UI, kontrol Anda harus menerapkan area utama fungsionalitas yang dijelaskan dalam tabel berikut.

Fungsionalitas Implementasi
Mengekspos penyedia ke Automasi UI. Menanggapi pesan WM_GETOBJECT yang dikirim ke jendela kontrol, kembalikan objek yang mengimplementasikan IRawElementProviderSimple. Untuk fragmen, implementasi ini harus menjadi penyedia untuk akar fragmen.
Berikan nilai properti. Terapkan IRawElementProviderSimple::GetPropertyValue untuk memberikan atau mengambil alih nilai.
Aktifkan klien untuk berinteraksi dengan kontrol. Terapkan antarmuka yang mendukung setiap pola kontrol yang sesuai, seperti IInvokeProvider. Kembalikan penyedia pola kontrol ini dalam implementasi IRawElementProviderSimple::GetPatternProvider Anda.
Naikkan peristiwa. UiaRaiseAutomationEvent, metode IProxyProviderWinEventSink.
Aktifkan menavigasi dan memfokuskan dalam fragmen. Terapkan IRawElementProviderFragment untuk setiap elemen dalam fragmen. Tidak perlu untuk elemen yang bukan bagian dari fragmen.
Aktifkan memfokuskan dan menemukan elemen anak dalam fragmen. Menerapkan IRawElementProviderFragmentRoot. Tidak perlu untuk elemen yang bukan akar fragmen.

 

Nilai Properti

Penyedia Automation UI untuk kontrol kustom harus mendukung properti tertentu yang dapat digunakan oleh UI Automation dan oleh aplikasi klien. Untuk elemen yang dihosting di windows, Automasi UI dapat mengambil beberapa properti dari penyedia jendela default, tetapi harus mendapatkan yang lain dari penyedia kustom.

Biasanya, penyedia untuk kontrol berbasis jendela tidak perlu menyediakan properti berikut yang diidentifikasi oleh PROPERTYID:

Properti RuntimeId dari elemen sederhana atau akar fragmen yang dihosting di jendela diperoleh dari jendela. Namun, elemen fragmen di bawah akar, seperti item daftar dalam kotak daftar, harus menyediakan pengidentifikasi mereka sendiri. Untuk informasi selengkapnya, lihat IRawElementProviderFragment::GetRuntimeId.

Properti IsKeyboardFocusable harus dikembalikan untuk penyedia yang dihosting dalam kontrol Formulir Windows. Dalam kasus ini, penyedia jendela default mungkin tidak dapat mengambil nilai yang benar.

Properti Nama biasanya disediakan oleh penyedia host.

Peristiwa dari Penyedia

Penyedia UI Automation harus memunculkan kejadian untuk memberi tahu aplikasi klien tentang perubahan status UI. Fungsi berikut digunakan untuk menaikkan peristiwa.

Fungsi Deskripsi
UiaRaiseAutomationEvent Memunculkan berbagai kejadian, termasuk kejadian yang dipicu oleh pola kontrol.
UiaRaiseAutomationPropertyChangedEvent Memunculkan kejadian ketika properti UI Automation telah berubah.
UiaRaiseStructureChangedEvent Memunculkan peristiwa ketika struktur pohon Automation UI telah berubah, misalnya, dengan menghapus atau menambahkan elemen.

 

Tujuan dari suatu peristiwa adalah untuk memberi tahu klien tentang sesuatu yang terjadi di UI. Penyedia harus meningkatkan peristiwa terlepas dari apakah perubahan dipicu oleh input pengguna atau oleh aplikasi klien menggunakan Automasi UI. Misalnya, peristiwa yang diidentifikasi oleh UIA_Invoke_InvokedEventId harus dinaikkan setiap kali kontrol dipanggil, baik melalui input pengguna langsung atau oleh aplikasi klien yang memanggil IUIAutomationInvokePattern::Invoke.

Untuk mengoptimalkan performa, penyedia dapat secara selektif memunculkan kejadian, atau tidak memunculkan kejadian sama sekali jika tidak ada aplikasi klien yang terdaftar untuk menerimanya. Elemen API berikut digunakan untuk pengoptimalan.

Elemen API Deskripsi
UiaClientsAreListening Fungsi ini memastikan apakah ada aplikasi klien yang telah berlangganan peristiwa Automation UI.
IRawElementProviderAdviseEvents Menerapkan antarmuka ini pada akar fragmen memungkinkan penyedia untuk diberi tahu ketika klien mendaftar dan membatalkan pendaftaran penanganan aktivitas untuk peristiwa pada fragmen.

 

Catatan

Mirip dengan menerapkan penghitungan referensi dalam pemrograman COM, penting bagi penyedia Automation UI untuk memperlakukan metode IRawElementProviderAdviseEvents::AdviseEventAdded dan AdviseEventRemoved seperti metode IUnknown::AddRef dan Release antarmuka IUnknown . Selama AdviseEventAdded telah dipanggil lebih banyak kali daripada AdviseEventRemoved untuk peristiwa atau properti tertentu, penyedia harus terus meningkatkan peristiwa yang sesuai, karena beberapa klien masih mendengarkan. Atau, penyedia Automation UI dapat menggunakan fungsi UiaClientsAreListening untuk menentukan apakah setidaknya satu klien mendengarkan dan, jika demikian, menaikkan semua peristiwa yang sesuai.

 

Navigasi Penyedia

Penyedia untuk kontrol sederhana, seperti tombol kustom yang dihosting di jendela, tidak perlu mendukung navigasi di pohon Automation UI. Navigasi ke dan dari elemen ditangani oleh penyedia default untuk jendela host, yang ditentukan dalam implementasi IRawElementProviderSimple::HostRawElementProvider. Namun, ketika Anda mengimplementasikan penyedia untuk kontrol kustom yang kompleks, Anda harus mendukung navigasi antara simpul akar fragmen dengan turunannya serta di antara simpul relasi.

Catatan

Elemen fragmen selain root harus mengembalikan NULL dari HostRawElementProvider, karena tidak secara langsung dihosting di jendela, dan tidak ada penyedia default yang dapat mendukung navigasi ke dan dari mereka.

 

Struktur fragmen ditentukan oleh implementasi IRawElementProviderFragment::Navigate Anda. Untuk setiap kemungkinan arah dari setiap fragmen, metode ini mengembalikan objek penyedia untuk elemen di arah tersebut. Jika tidak ada elemen ke arah itu, metode mengembalikan NULL.

Akar fragmen hanya mendukung navigasi ke elemen turunan. Misalnya, kotak daftar mengembalikan item pertama dalam daftar saat arahnya NavigateDirection_FirstChild, dan mengembalikan item terakhir saat arahnya NavigateDirection_LastChild. Akar fragmen tidak mendukung navigasi ke induk atau saudara kandung; ini ditangani oleh penyedia jendela host.

Elemen fragmen yang bukan merupakan akar harus mendukung navigasi ke induk dan ke setiap relasi serta turunan yang mereka miliki.

Menetapkan Induk Baru

Jendela pop-up sebenarnya adalah jendela tingkat atas, dan secara default, muncul di pohon Automation UI sebagai turunan desktop. Namun, dalam banyak kasus, jendela pop-up secara logis merupakan turunan dari beberapa kontrol lain. Misalnya, daftar drop-down kotak kombo secara logis merupakan turunan kotak kombo tersebut. Demikian pula jendela pop-up menu secara logis merupakan turunan menu tersebut. Automasi UI menyediakan dukungan untuk menetapkan induk baru ke jendela pop-up sehingga tampaknya merupakan anak dari kontrol terkait.

Untuk menetapkan induk baru ke jendela pop-up:

  1. Buat penyedia untuk jendela pop-up. Ini mengharuskan kelas jendela pop-up diketahui terlebih dahulu.
  2. Terapkan semua properti dan pola kontrol seperti biasa untuk pop-up itu, seolah-olah itu adalah kontrol dengan haknya sendiri.
  3. Terapkan properti IRawElementProviderSimple::HostRawElementProvider sehingga mengembalikan nilai yang diperoleh dari UiaHostProviderFromHwnd, di mana parameternya adalah handel jendela jendela pop-up.
  4. Terapkan IRawElementProviderFragment::Navigasikan untuk jendela pop-up dan induknya sehingga navigasi ditangani dengan benar dari induk logis ke anak-anak logis, dan di antara saudara kandung anak.

Ketika UI Automation mendapati jendela pop-up, UI Automation akan mengenali jika navigasi diambil alih dari default, dan melompati jendela pop-up ketika didapati sebagai turunan desktop. Sebaliknya, simpul hanya dapat dijangkau melalui fragmen.

Menetapkan induk baru tidak cocok untuk kasus di mana kontrol dapat menghosting jendela kelas apa pun. Misalnya, kontrol rebar dapat menghosting semua jenis jendela di pitanya. Untuk menangani kasus ini, Automasi UI mendukung bentuk alternatif relokasi jendela, seperti yang dijelaskan di bagian berikutnya.

Reposisi Penyedia

Fragmen Automasi UI mungkin berisi dua elemen atau lebih yang masing-masing terkandung dalam jendela. Karena setiap jendela memiliki penyedia default sendiri yang menganggap jendela sebagai anak dari jendela yang berisi, pohon Automation UI secara default, akan menampilkan jendela dalam fragmen sebagai anak dari jendela induk. Dalam kebanyakan kasus, ini adalah perilaku yang diinginkan, tetapi terkadang dapat menyebabkan kebingungan karena ketidakcocokan dengan struktur logis dari UI tersebut.

Contoh yang baik dari kasus ini adalah kontrol bilah ulang. Kontrol bilah ulang berisi pita, yang masing-masing dapat berisi kontrol berbasis jendela, seperti toolbar, kotak edit, atau kotak kombo. Penyedia jendela default untuk jendela batang ulang melihat jendela kontrol pita sebagai turunan, dan penyedia bilah ulang melihat pita sebagai turunan. Karena penyedia jendela dan penyedia batang ulang bekerja bersamaan dan menggabungkan anak-anak mereka, baik band maupun kontrol berbasis jendela muncul sebagai turunan dari kontrol rebar. Namun, secara logis, hanya band yang akan muncul sebagai anak-anak kontrol rebar, dan setiap penyedia band harus digabungkan dengan penyedia jendela default untuk kontrol yang dikandungnya.

Untuk mencapai hal ini, penyedia akar fragmen untuk kontrol rebar mengekspos satu set anak yang mewakili band. Setiap pita memiliki satu penyedia yang dapat mengekspos properti dan pola kontrol. Dalam implementasi IRawElementProviderSimple::HostRawElementProvider, penyedia band mengembalikan penyedia jendela default untuk jendela kontrol, yang diperolehnya dengan memanggil UiaHostProviderFromHwnd, melewati handel jendela kontrol (HWND). Akhirnya, penyedia akar fragmen untuk rebar mengimplementasikan antarmuka IRawElementProviderHwndOverride , dan dalam implementasi antarmuka IRawElementProviderHwndOverride::GetOverrideProviderForHwnd, ia mengembalikan penyedia band yang sesuai untuk kontrol yang terkandung dalam jendela yang ditentukan.

Memutus Sambungan Penyedia

Aplikasi biasanya membuat kontrol sesuai kebutuhan dan menghancurkannya setelahnya. Setelah menghancurkan kontrol, sumber daya penyedia Automation UI yang terkait dengan kontrol harus dirilis dengan memanggil UiaDisconnectProvider.

Demikian pula, aplikasi harus menggunakan fungsi UiaDisconnectAllProviders untuk merilis semua sumber daya Automation UI yang dipegang oleh semua penyedia dalam aplikasi sebelum dimatikan.

Panduan Programmer Penyedia Automation UI