Alternative all'annotazione dinamica
Esistono altri modi per fornire supporto IAccessible personalizzato per gli elementi dell'interfaccia utente e, in alcuni casi, sono la soluzione corretta. Prima dell'annotazione dinamica, queste tecniche alternative erano le uniche opzioni disponibili per gli sviluppatori. Includono l'implementazione di tutte le tecniche IAccessible e a livello di codice.
Implementazione di tutte le interfacce IAccessible
Una tecnica alternativa consiste nell'implementare tutte le interfacce IAccessible . Questo approccio è spesso necessario per controlli personalizzati o elementi dell'interfaccia utente radicalmente diversi; Tuttavia, i costi di sviluppo e test sono sufficientemente significativi da evitare, a meno che non sia veramente necessario. Se l'obiettivo è modificare una singola proprietà, il costo è difficile da giustificare.
Tecniche a livello di codice
Un'altra opzione consiste nell'usare tecniche di sottoclasse e wrapping per modificare le informazioni esposte per una proprietà specifica. Questa è la tecnica che l'annotazione dinamica deve sostituire. Per eseguire l'override di una singola proprietà usando la sottoclasse e il wrapping, lo sviluppatore deve eseguire la procedura seguente:
- Sottoclasse il valore HWND dell'oggetto IAccessible .
- Intercettare il messaggio WM_GETOBJECT per il valore IParam/OBJID corretto.
- Inoltrare il messaggio WM_GETOBJECT alla classe base usando la funzione di callback CallWndProc . Se viene restituito zero, chiamare CreateStdAccessibleObject; in caso contrario, chiamare LresultFromObject sul valore restituito per ottenere il puntatore dell'interfaccia IAccessible nativo del controllo.
- Creare una classe wrapper, che implementa IAccessible ed esegue il wrapping del puntatore all'interfaccia IAccessible restituito dal passaggio precedente. Questa classe wrapper invia tutti i metodi e le proprietà al puntatore di interfaccia IAccessible originale, ad eccezione di quelli di cui eseguire l'override. Ciò comporta la scrittura di codice di inoltro per tutte le 21 proprietà e i metodi dell'interfaccia IAccessible , indipendentemente dal numero effettivamente sottoposto a override.
Inoltre, gli sviluppatori devono verificare le condizioni seguenti:
- Il metodo o la proprietà sottoposta a override devono gestire solo gli ID figlio necessari e inoltrare tutti gli altri al puntatore di interfaccia IAccessible originale.
- Il wrapping deve anche inoltrare le interfacce IEnumVARIANT e IOleWindow solo se l'oggetto originale le supporta.
- Il conteggio dei riferimenti deve essere gestito correttamente, soprattutto se sono supportate altre interfacce.
- I Valori restituiti IDispatch devono essere gestiti correttamente, in particolare con il metodo ITypeInfo::Invoke, che deve essere chiamato con un puntatore di interfaccia all'interfaccia wrapper, non un puntatore all'interfaccia IAccessible originale.
Queste tecniche richiedono una notevole quantità di lavoro, anche se è necessario eseguire l'override solo di una o due proprietà. La maggior parte del codice risultante riguarda la sottoclasse e il wrapping e solo una piccola frazione fornisce effettivamente le informazioni sottoposte a override.
Tuttavia, esistono scenari in cui sono necessarie queste tecniche. Ad esempio, se si apportano modifiche strutturali per creare un elemento dell'interfaccia utente segnaposto, è consigliabile usare queste tecniche anziché l'annotazione dinamica.
Correzione dei nomi derivati dalle etichette
Alcuni controlli comuni di Microsoft Win32, ad esempio il controllo casella di modifica, vengono quasi sempre usati con un'etichetta (una voce LTEXT nel file di risorse) o una casella di gruppo (GROUPBOX nel file di risorse). Microsoft Active Accessibility deriva automaticamente la proprietà name del controllo dalla relativa etichetta. Per tali controlli, il testo della finestra (visualizzato in Microsoft Visual Studio come proprietà Name o ID) viene ignorato, perché in genere viene generato automaticamente e raramente molto descrittivo; ad esempio "IDC_EDIT1".
Se l'interfaccia utente dell'applicazione non è progettata correttamente, Microsoft Active Accessibility potrebbe non essere in grado di impostare correttamente il nome. Per essere associato a un controllo, l'etichetta o la casella di gruppo devono essere posizionate immediatamente prima del controllo dinamico nell'ordine di tabulazioni.
È possibile modificare l'ordine di tabulazione usando lo strumento in Visual Studio (nel menu Formato quando l'editor di risorse è aperto) o modificando direttamente il file di risorse.
Nell'esempio seguente viene illustrata la descrizione di un file di risorse di una finestra di dialogo contenente due caselle di modifica etichettate.
IDD_INPUTNAME DIALOGEX 22, 17, 312, 118
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "Enter your name"
FONT 8, "System", 0, 0, 0x0
BEGIN
DEFPUSHBUTTON "OK",IDOK,179,35,30,11,WS_GROUP
LTEXT "First Name:",IDC_STATIC,8,16,43,8
LTEXT "Last Name:",IDC_STATIC,8,33,43,8
EDITTEXT IDC_EDITFIRSTNAME,53,15,120,12,ES_AUTOHSCROLL
EDITTEXT IDC_EDITLASTNAME,53,34,120,12,ES_AUTOHSCROLL
END
In questo esempio le etichette e i controlli non sono elencati nell'ordine di tabulazioni corretto. Di conseguenza, Microsoft Active Accessibility assegna il nome "Cognome" alla casella di modifica del nome e nessun nome nella casella di modifica del cognome.
L'esempio seguente mostra l'elenco di risorse corretto. Si noti anche che i tasti di scelta rapida sono stati designati nelle etichette.
IDD_INPUTNAME DIALOGEX 22, 17, 312, 118
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "Enter your name"
FONT 8, "System", 0, 0, 0x0
BEGIN
LTEXT "&First Name:",IDC_STATIC,8,16,43,8
EDITTEXT IDC_EDITFIRSTNAME,53,15,120,12,ES_AUTOHSCROLL
LTEXT "&Last Name:",IDC_STATIC,8,33,43,8
EDITTEXT IDC_EDITLASTNAME,53,34,120,12,ES_AUTOHSCROLL
DEFPUSHBUTTON "OK",IDOK,179,35,30,11,WS_GROUP
END
Quando i controlli hanno etichette supplementari, ad esempio per i valori minimo e massimo su una barra di avanzamento, queste etichette devono essere inserite dopo il controllo nell'ordine di tabulazioni. L'etichetta principale del controllo deve essere visualizzata immediatamente prima del controllo stesso.
Denominazione dei controlli senza etichette
Non è sempre possibile o auspicabile avere un'etichetta visibile per ogni controllo. Tuttavia, è comunque possibile specificare un nome per il controllo aggiungendo un'etichetta invisibile. Come sempre, l'etichetta invisibile deve precedere immediatamente il controllo nell'ordine di tabulazioni.
Se si usa l'Editor risorse in Microsoft Visual Studio .NET, è possibile impostare la proprietà Visible su False. Per rendere invisibile l'etichetta durante la modifica del file di risorse (rc), aggiungere NOT WS_VISIBLE o alla parte di stile del controllo etichetta, come illustrato nell'esempio seguente.
LTEXT "&FullName:",IDC_STATIC,111,23,44,8,NOT WS_VISIBLE
Si noti che qualsiasi tasto di scelta rapida designato funziona anche se l'etichetta è invisibile.