Bagikan melalui


Menerapkan Penyedia Automasi UI Server-Side

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

Untuk contoh kode yang menunjukkan cara menerapkan penyedia sisi server, lihat topik How-To 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 menerapkan IRawElementProviderFragment sementara elemen akar aplikasi harus menerapkan IRawElementProviderFragmentRoot. Selain itu, setiap elemen penyedia harus menautkan ke:

  • ortu
  • unsur penyedia layanan 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 UI Automation harus menerapkan setidaknya antarmuka IRawElementProviderSimple. Antarmuka IRawElementProviderFragment dan IRawElementProviderFragmentRoot bersifat opsional, tetapi sebaiknya diimplementasikan untuk elemen dalam kontrol kompleks agar 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 kompleks, termasuk menemukan elemen turunan pada koordinat tertentu dan mengatur status fokus untuk seluruh kontrol.

 

Nota

Di API Automasi UI 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 acara.
IRawElementProviderHwndOverride Memungkinkan reposisi elemen berbasis jendela di pohon UI Otomatisasi sebuah 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 Pelaksanaan
Mengekspos penyedia ke Otomatisasi Antarmuka Pengguna. Sebagai respons terhadap pesan WM_GETOBJECT yang dikirim ke jendela kontrol, kembalikan objek yang mengimplementasikan IRawElementProviderSimple. Untuk fragmen, ini harus menjadi penyedia untuk induk 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 Anda dari IRawElementProviderSimple::GetPatternProvider.
Memicu kejadian. UiaRaiseAutomationEvent, metode IProxyProviderWinEventSink.
Aktifkan menavigasi dan memfokuskan di dalam fragmen. Terapkan IRawElementProviderFragment untuk setiap elemen dalam fragmen. Tidak perlu untuk elemen yang bukan bagian dari fragmen.
Aktifkan kemampuan untuk memfokuskan dan menemukan sub-elemen dalam sebuah fragmen. Terapkan IRawElementProviderFragmentRoot. Tidak perlu untuk elemen yang bukan merupakan akar fragmen.

 

Nilai Properti

Penyedia Automasi UI untuk kontrol kustom harus mendukung properti tertentu yang dapat digunakan oleh Automasi UI dan oleh aplikasi klien. Untuk elemen yang dihosting di windows, Automation 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 ditempatkan dalam jendela diperoleh dari jendela tersebut. Namun, elemen fragmen di bawah induk, seperti item daftar dalam kotak daftar, harus menyediakan identifikasi mereka sendiri. Untuk informasi selengkapnya, lihat IRawElementProviderFragment::GetRuntimeId.

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

Properti Nama biasanya disediakan oleh penyedia host.

Acara dari Penyedia

Penyedia Automasi UI harus menaikkan peristiwa untuk memberi tahu aplikasi klien tentang perubahan dalam status UI. Fungsi berikut digunakan untuk memicu peristiwa.

Fungsi Deskripsi
UiaRaiseAutomationEvent Meningkatkan berbagai peristiwa, termasuk peristiwa yang dipicu oleh pola kontrol.
UiaRaiseAutomationPropertyChangedEvent Memicu peristiwa saat properti UI Automation berubah.
UiaRaiseStructureChangedEvent Menaikkan 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 memicu sebuah event terlepas dari apakah perubahan dipicu oleh input pengguna atau oleh aplikasi klien yang menggunakan UI Automation. 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 menaikkan peristiwa, atau tidak menimbulkan peristiwa 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 kejadian UI Automation.
IRawElementProviderAdviseEvents Menerapkan antarmuka ini pada akar fragmen memungkinkan penyedia untuk diberi tahu ketika klien mendaftar dan membatalkan pendaftaran penanganan aktivitas untuk peristiwa pada fragmen.

 

Nota

Mirip dengan menerapkan penghitungan referensi dalam pemrograman COM, penting bagi penyedia Automation UI untuk memperlakukan metode IRawElementProviderAdviseEvents::AdviseEventAdded dan metode AdviseEventRemoved seperti metode IUnknown::AddRef dan Release dari 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. Sebagai alternatif, penyedia UI Automation dapat menggunakan fungsi UiaClientsAreListening untuk menentukan apakah setidaknya satu klien mendengarkan dan, jika demikian, memunculkan 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 menerapkan penyedia untuk kontrol kustom yang kompleks, Anda harus mendukung navigasi antara simpul akar fragmen dan keturunannya, dan antara simpul saudara.

Nota

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

 

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

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

Elemen fragmen yang bukan akar harus mendukung navigasi ke induk, dan kepada saudara kandung dan anak apa pun yang mereka miliki.

Menetapkan Induk Baru

Jendela pop-up sebenarnya adalah jendela tingkat atas, dan secara default, muncul dalam pohon Otomasi Antarmuka Pengguna sebagai bagian dari desktop. Namun, dalam banyak kasus, jendela pop-up secara logis merupakan turunan dari beberapa kontrol lain. Misalnya, daftar tarik-turun dari kotak pilihan secara logis adalah bagian dari kotak pilihan. Demikian pula, jendela pop-up menu secara logis merupakan anak dari menu. 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 memerlukan agar kelas jendela pop-up diketahui sebelumnya.
  2. Terapkan semua properti dan pola kontrol sebagaimana biasanya untuk jendela pop-up tersebut, seakan-akan itu adalah kontrol tersendiri.
  3. Terapkan properti IRawElementProviderSimple::HostRawElementProvider sehingga mengembalikan nilai yang diperoleh dari UiaHostProviderFromHwnd, di mana parameter adalah handle jendela pop-up.
  4. Terapkan IRawElementProviderFragment::Navigasikan untuk jendela pop-up dan induknya sehingga navigasi ditangani dengan benar dari induk logis ke anak logis, dan antara anak saudara.

Ketika Automasi UI menemukan jendela pop-up, ia mengenali bahwa navigasi telah diubah dari default, dan melewati jendela pop-up ketika ditemui sebagai elemen anak dari 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, kendali rebar dapat menghosting semua jenis jendela dalam pitanya. Untuk menangani kasus ini, Automation UI mendukung bentuk alternatif relokasi jendela, seperti yang dijelaskan di bagian berikutnya.

Reposisi Penyedia

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

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

Untuk mencapai hal ini, penyedia akar fragmen untuk kontrol rebar mengekspos sekumpulan anak yang mewakili pita. Setiap pita memiliki satu penyedia yang dapat mengekspos properti dan pola kontrol. Dalam implementasinya IRawElementProviderSimple::HostRawElementProvider, penyedia band mengembalikan penyedia jendela default untuk jendela kontrol, yang diperolehnya dengan memanggil UiaHostProviderFromHwnd, mengoper handle jendela kontrol (HWND). Terakhir, penyedia akar fragmen untuk rebar mengimplementasikan antarmukaIRawElementProviderHwndOverride, dan dalam implementasinya IRawElementProviderHwndOverride::GetOverrideProviderForHwnd, mengembalikan penyedia band yang sesuai untuk kontrol yang terkandung di jendela yang ditentukan.

Memutus Sambungan Penyedia

Aplikasi biasanya membuat kontrol sesuai kebutuhan dan menghancurkannya setelahnya. Setelah memusnahkan kontrol, sumber daya penyedia UI Automation yang terkait dengan kontrol harus dilepaskan 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 Automasi UI