2013-04-10 6 views
9

Uczę się UI Automation i odkryłem, że mój klon "Inspect Object" pokazuje, że IsKeyboardFocusable jest zawsze fałszywe, nawet jeśli jest prawdziwe, wszystkie inne informacje są identyczne (jak widać z obrazu). Czy ktoś ma jakiś pomysł, dlaczego widzę tę właściwość jako false, gdy pobrać wartość?IsKeyboardFocusable jest prawdą w Inspect Object, ale zawsze fałszywie w mojej aplikacji

enter image description here

+0

Mam dokładnie ten sam problem. Jest to poważny problem, ponieważ jeśli 'IsKeyboardFocuseable' jest fałszywym wywołaniem' SetFocus() 'rzuci wyjątek. –

Odpowiedz

5

W aplikacji Inspect Object używana jest najnowsza wersja interfejsu Windows Automation COM API (3.0) do wyświetlania wszystkich tych właściwości. Ale domyślna implementacja .NET UIAutomation nie jest oparta na interfejsach COM Windows Automation API 3.0 (w oparciu o poprzednią wersję tego interfejsu COM API). Tak więc niektóre właściwości nie działają poprawnie. Na przykład dla listy kontaktów Skype właściwość AutomationElement.IsKeyboardFocusableProperty mówi, że pobieranie wartości dla tej właściwości nie jest w ogóle obsługiwane. Można to sprawdzić za pomocą następujący fragment kodu:

object isKeyboardFocusable = listItem.GetCurrentPropertyValue(AutomationElement.IsKeyboardFocusableProperty, true); 
if(isKeyboardFocusable == AutomationElement.NotSupported) { 
    // we will always goes here 
} 

Teraz nie wiem sposobów uniknięcia tego problemu przy wykorzystaniu obecnego wdrażania .Net UIAutomation.

Dobrą wiadomością jest to, że istnieje alternatywna implementacja automatyzacji interfejsu użytkownika w .NET, która umożliwia korzystanie z nowych interfejsów COM Windows Automation API 3.0, z ich poprawioną niezawodnością i wydajnością, przy jednoczesnym korzystaniu z tego samego System.Windows.Automation klasy jak we wcześniejszych wersjach Automatyzacji interfejsu użytkownika. Ta implementacja jest dostępna jako projekt na CodePlex: UI Automation COM-to-.NET Adapter

Wypróbowaliśmy tę alternatywną implementację już dziś, a dzięki tej alternatywnej implementacji właściwość IsKeyboardFocusable zwraca ten sam wynik co narzędzie Inspect Objects! Co więcej, teraz możliwe jest użycie niektórych rozszerzonych właściwości, które wyświetlają Inspect Objects (np. LegacyIAccessible members).

3

Wewnętrzna realizacja IsKeyboardFocusable wykorzystuje GetCurrentPropertyValue (właściwość: AutomationElement.IsKeyboardFocusableProperty, ignoreDefaultValue: false) funkcję. W przypadkach, gdy się nie powiedzie, po prostu zwróci false (aw twoim przypadku nie powiedzie się). Dlatego zalecam użycie GetCurrentPropertyValue (właściwość: AutomationElement.IsKeyboardFocusableProperty, ignoreDefaultValue: true) zamiast opcji IsKeyboardFocusable, abyś wiedział, czy się nie powiedzie.

Możesz uzyskać dokładnie taki sam wynik, jak Sprawdź za pomocą funkcji Winapi. Olecc.dll daje IAccessible interface (Jest bardziej szczegółowy description tego interfejsu). Instancja tego interfejsu może mieć instancje podrzędne, część z nich może być aktywowana i część z nich - nie. Jeśli utworzysz IAccessible z HWnd, nie możesz być pewny, że cała kontrola jest możliwa do ustawienia lub nie można jej ustawić. Dla pewności powinieneś stworzyć IAccessible z punktu ekranu - daje to dokładnie to, co IAccessible pod tym punktem (możesz zobaczyć na swoim zrzucie ekranu, że Inspect używa punktu na ekranie - "How found - Mouse move (1120, 470)"). Jeśli przełączysz się z trybu UIAutomation na MSAA w Inspect, możesz zobaczyć, jak wygląda IAccessible.

Ale jeśli jest to możliwe w twoim przypadku, lepiej użyć alternative implementation of UIAutomation. Zwraca poprawną wartość IsKeyboardFocusable (w przeciwieństwie do standardowej implementacji UIAutomation). Nie przetestowałem tej biblioteki samodzielnie (testowałem tylko IsKeyboardFocusable), ale wygląda na to, że działa dobrze i ma te same typy i interfejsy co standardowa implementacja. Podobnie jak w przypadku IAccessible, powinieneś utworzyć AutomationElement z punktu, a nie z HWnd.

O Twoim pytaniu - jeszcze nie wiem, dlaczego standardowa UIAutomation nie może w niektórych przypadkach zwracać automatycznie AutomationElement.IsKeyboardFocusableProperty. Myślę, że to może być błąd.

+1

* Proszę * nie używać IAccessible. Jest to bardzo stare API i ma wiele problemów (gadatliwe interfejsy COM, bloki w nieoczekiwanych punktach itp.). Użyj alternatywnego wiązania UIAutomation. –

+0

@EricBrown: Całkowicie się zgadzam. W przypadkach, w których jest to możliwe, lepiej użyć alternatywnej automatyzacji interfejsu użytkownika. Ale gdy nie jest to możliwe, pozostaje tylko używać IAccessible i tylko znaleźć IsKeyBoardFocusable, jeśli standardowa automatyzacja interfejsu użytkownika zawodzi. –

+0

Win7 natywne automaty proxy UI powrócą do IAccessible; jednak używają IAccessible * inproc * zamiast cross-proc, co powoduje ogromny wzrost wydajności. Naprawdę, nie ma absolutnie żadnego powodu, dla deweloperów piszących aplikacje automatyzacji do używania IAccessible. –

0

Czy wypróbowałeś narzędzie do szpiegowskiej automatyzacji interfejsu użytkownika: https://ddeltasolutions.000webhostapp.com/? Znalazłem przypadki, w których właściwość IsKeyboardFocusableProperty jest prawdziwa, na przykład pasek menu aplikacji Skype.