Verifica che gli elementi dell'interfaccia utente siano denominati correttamente

Questo argomento descrive il modo corretto per specificare i nomi degli elementi dell'interfaccia utente nelle applicazioni Microsoft Win32 in modo che Microsoft Active Accessibility possa esporre accuratamente i nomi alle applicazioni client tramite la proprietàIAccessibleName.

Le informazioni contenute in questa sezione si applicano solo a Microsoft Active Accessibility. Non si applica alle applicazioni che usano Microsoft Automazione interfaccia utente o a quelle basate su linguaggi di markup come HTML, DHTML (Dynamic HTML) o XML.

Panoramica

In Microsoft Active Accessibility ogni elemento dell'interfaccia utente in un'applicazione è rappresentato da un oggetto che espone l'interfaccia IAccessible . Le applicazioni client usano le proprietà e i metodi dell'interfaccia IAccessible per interagire con l'elemento dell'interfaccia utente e recuperare informazioni su di esso. Una delle proprietà più importanti esposte dall'interfaccia IAccessible è la proprietà Name. Le applicazioni client si basano sulla proprietà Name per trovare, identificare o annunciare un elemento dell'interfaccia utente all'utente. Se Microsoft Active Accessibility non riesce a esporre correttamente la proprietà Name di un particolare elemento dell'interfaccia utente, le applicazioni client non potranno presentare tale elemento dell'interfaccia utente all'utente e l'elemento dell'interfaccia utente non sarà accessibile agli utenti con disabilità.

Come la denominazione non corretta causa problemi

Per illustrare i problemi causati dalla denominazione non corretta degli elementi dell'interfaccia utente, prendere in considerazione il modulo di immissione del nome illustrato nella figura seguente.

illustration of a simple form for entering first and last name

Anche se gli elementi dell'interfaccia utente nel modulo hanno un aspetto corretto, l'implementazione a livello di codice non è corretta. Per un client Microsoft Active Accessibility, ad esempio un'utilità per la lettura dello schermo, la proprietà Name del controllo di modifica superiore è "Last Name:" e la proprietà Name del controllo di modifica inferiore è una stringa vuota (""). L'utilità per la lettura dello schermo leggerà il controllo di modifica superiore come "Cognome", anche se l'utente deve digitare il nome. L'utilità per la lettura dello schermo leggerà il secondo controllo di modifica come "nessun nome", quindi l'utente non avrà idea di cosa digitare nel secondo controllo di modifica. L'utilità per la lettura dello schermo non è in grado di aiutare l'utente a immettere i dati in questo modulo semplice.

Un altro problema con il modulo è che nessun tasto di scelta rapida viene assegnato a uno dei controlli di modifica. L'utente è costretto a visualizzare una scheda nei controlli o a usare il mouse.

Le sezioni seguenti illustrano l'origine di questi problemi e forniscono linee guida per correggerle.

Modalità con cui MSAA ottiene la proprietà Name

Microsoft Active Accessibility ottiene la stringa della proprietà Name da posizioni diverse a seconda del tipo dell'elemento dell'interfaccia utente. Per la maggior parte degli elementi dell'interfaccia utente a cui è associato il testo della finestra, Microsoft Active Accessibility usa il testo della finestra come stringa della proprietà Name. Esempi di questo tipo di elemento dell'interfaccia utente includono controlli come pulsanti, voci di menu e descrizioni comando.

Per i controlli seguenti, Microsoft Active Accessibility ignora il testo della finestra e cerca invece un'etichetta di testo statica (o etichetta casella di gruppo) immediatamente precedente al controllo nell'ordine di tabulazioni.

  • Caselle combinate
  • Selezione data e ora
  • Modifica e modifica avanzata controlli
  • Controlli indirizzo IP
  • Caselle di riepilogo
  • Visualizzazioni elenco
  • Barre di stato
  • Scrollbars
  • Controlli statici con stile SS_ICON o SS_BITMAP
  • Barre di avanzamento
  • Visualizzazioni albero

Se i controlli precedenti non sono accompagnati da etichette di testo statiche o se le etichette non sono implementate correttamente, Microsoft Active Accessibility non può fornire la proprietà Name corretta alle applicazioni client.

La maggior parte dei controlli precedenti ha effettivamente il testo della finestra associato. L'editor di risorse genera automaticamente il testo della finestra, costituito da una stringa generica, ad esempio "edit1" o "listbox3". Anche se gli sviluppatori possono sostituire il testo della finestra generata con un testo più significativo, la maggior parte delle operazioni non viene mai eseguita. Poiché il testo della finestra generata non ha alcun significato per l'utente, Microsoft Active Accessibility lo ignora e usa invece l'etichetta di testo statica associata.

Come trovare e correggere i problemi di denominazione

Nel modulo di immissione del nome illustrato in How Incorrect Naming Causes Problems, the cause of the problems is that the tab order of the controls is incorrect. Esaminando l'interfaccia utente con uno strumento di test, ad esempio Inspect , vengono rilevati i problemi relativi alla gerarchia di oggetti. La schermata seguente mostra la gerarchia di oggetti interrotta del modulo di immissione del nome come appare in Inspect.

screen shot of the inspect tool showing an incorrect object hierarchy of the name entry form

Nella schermata precedente si noti che la gerarchia degli oggetti non corrisponde alla struttura dei controlli così come vengono visualizzati nell'interfaccia utente del modulo di immissione del nome. Si noti anche che Inspect ha assegnato il nome non corretto all'elemento successivo all'ultimo elemento (è il controllo di modifica per immettere il nome e deve essere denominato "First Name:". Infine, si noti che Inspect non è riuscito a trovare un nome per l'ultimo elemento (è il controllo di modifica per l'immissione del cognome e deve avere un nome "Cognome:".

Nell'esempio seguente viene illustrato il contenuto del file di risorse per il modulo di immissione del nome. Si noti che l'ordine di tabulazioni non è coerente con la struttura logica dei controlli così come vengono visualizzati nell'interfaccia utente. Si noti anche che non vengono specificati tasti di scelta rapida per i due controlli di modifica.

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_EDIT1,53,15,120,12,ES_AUTOHSCROLL
    EDITTEXT        IDC_EDIT2,53,34,120,12,ES_AUTOHSCROLL
END

Per risolvere i problemi relativi al modulo di immissione del nome, è necessario modificare il file della risorsa (rc) per specificare i tasti di scelta rapida e i controlli devono essere inseriti nell'ordine seguente:

  1. Etichetta di testo statica "&First Name:".
  2. Controllo di modifica per l'immissione del nome (IDC_EDIT1).
  3. Etichetta di testo statica "&Last Name:".
  4. Controllo di modifica per l'immissione del cognome (IDC_EDIT2).
  5. Pulsante di pressione predefinito "OK".

Nell'esempio seguente viene illustrato il file di risorse corretto per il modulo di immissione del nome:

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_EDIT1,53,15,120,12,ES_AUTOHSCROLL
    LTEXT           "&Last Name:",IDC_STATIC,8,33,43,8
    EDITTEXT        IDC_EDIT2,53,34,120,12,ES_AUTOHSCROLL
    DEFPUSHBUTTON   "OK",IDOK,179,35,30,11,WS_GROUP
END

Per apportare correzioni a un file di risorse, è possibile modificare direttamente il file oppure usare lo strumento Ordine di tabulazioni in Microsoft Visual Studio. È possibile accedere allo strumento Ordine di tabulazione in Visual Studio premendo CTRL+D oppure selezionando Ordine di tabulazione dal menu Formato.

Dopo aver corretto e ricompilato l'applicazione, l'interfaccia utente del modulo di immissione dei nomi avrà lo stesso aspetto di quello precedente. Tuttavia, Microsoft Active Accessibility fornirà ora le proprietà Name corrette alle applicazioni client e imposterà correttamente lo stato attivo quando l'utente preme i tasti di scelta rapida ALT+F o ALT+L. Inoltre, Inspect mostrerà la gerarchia di oggetti corretta, come illustrato nella schermata seguente.

screen shot of the accessible explorer tool showing a correct object hierarchy of the name entry form

Come denominare correttamente una barra di avanzamento

Quando si definisce una barra di avanzamento (o un dispositivo di scorrimento), assicurarsi che l'etichetta di testo statica principale per la barra di avanzamento venga visualizzata prima della barra di avanzamento e che le etichette di testo statiche per gli intervalli minimo e massimo vengano visualizzate dopo la barra di avanzamento. Tenere presente che Microsoft Active Accessibility usa l'etichetta di testo statica che precede immediatamente un controllo come proprietà Name per il controllo. L'inserimento dell'etichetta di testo statica principale immediatamente prima della barra di avanzamento e delle altre etichette successive garantisce che Microsoft Active Accessibility fornisca la proprietà Name corretta a un client.

La figura seguente mostra una barra di avanzamento tipica con un'etichetta di testo statica principale denominata "Speed" e etichette di testo statiche per gli intervalli minimo ("min") e massimo ("max").

illustration of a trackbar control that has a main label and labels for the minimum and maximum ranges

Nell'esempio seguente viene illustrato il modo corretto per definire una barra di avanzamento e le relative etichette di testo statiche nel file di risorse:

BEGIN
    ...

    LTEXT           "&Speed",IDC_STATIC,47,20,43,8
    CONTROL         "",IDC_SLIDER1,"msctls_trackbar32",
                    TBS_AUTOTICKS | TBS_BOTH | WS_TABSTOP,
                    32,32,62,23
    LTEXT           "min",IDC_STATIC,16,37,15,8
    LTEXT           "max",IDC_STATIC,94,38,43,8

    ...
END

Come usare etichette invisibili per denominare i controlli

Non è sempre possibile o auspicabile avere un'etichetta visibile per ogni controllo. Ad esempio, a volte l'aggiunta di etichette può causare modifiche indesiderate nell'aspetto dell'interfaccia utente. In questo caso, è possibile usare etichette invisibili. Microsoft Active Accessibility continuerà a raccogliere il testo associato a un'etichetta invisibile, ma l'etichetta non verrà visualizzata o interferirà con l'interfaccia utente visiva.

Come per le etichette visibili, un'etichetta invisibile deve precedere immediatamente il controllo nell'ordine di tabulazione. Per rendere invisibile un'etichetta in un file di risorse (rc), aggiungere NOT WS_VISIBLE o |~WS_VISIBLE alla parte di stile del controllo testo statico. Se si usa l'Editor risorse in Visual Studio, è possibile impostare la proprietà Visible su False.

Come utilizzare l'annotazione diretta per specificare la proprietà Name

I proxy predefiniti inclusi nel componente runtime di Microsoft Active Accessibility, Oleacc.dll, forniscono automaticamente un oggetto IAccessible per tutti i controlli Windows standard. Se si personalizza un controllo Windows standard, i proxy predefiniti offrono il massimo per fornire in modo accurato tutte le proprietà IAccessible per il controllo personalizzato. È consigliabile testare accuratamente un controllo personalizzato per assicurarsi che i proxy predefiniti forniscano valori di proprietà accurati e completi. Se il test rivela valori di proprietà non accurati o incompleti, è possibile usare la tecnica di annotazione dinamica denominata annotazione diretta per fornire valori di proprietà corretti e aggiungere quelli mancanti.

Si noti che l'annotazione dinamica non è solo per i controlli supportati dai proxy di Microsoft Active Accessibility. È anche possibile usarlo per modificare o fornire proprietà per qualsiasi controllo che fornisce la propria implementazione IAccessible .

Questa sezione è incentrata sull'uso di annotazioni dirette per fornire un valore corretto per la proprietà Name dell'oggetto IAccessible per un controllo. È possibile usare l'annotazione diretta per fornire anche altri valori delle proprietà. Sono inoltre disponibili altre tecniche di annotazione dinamica accanto all'annotazione diretta e le funzionalità e le funzionalità dell'API di annotazione dinamica si estendono ben oltre quanto descritto in questa sezione. Per altre informazioni sull'annotazione dinamica, vedere API di annotazione dinamica.

Passaggi per annotare la proprietà Name

L'uso dell'annotazione diretta per modificare la proprietà Name di un controllo prevede la procedura seguente.

  1. Includere i file di intestazione seguenti:

    • Initguid.h
    • Oleacc.h

    Nota

    Per definire i GUID, è necessario includere Initguid.h prima di Oleacc.h nello stesso file.

     

  2. Inizializzare la libreria Component Object Model (COM) chiamando la funzione CoInitializeEx , in genere durante il processo di inizializzazione dell'applicazione.

  3. Poco dopo la creazione del controllo di destinazione (in genere durante il messaggio di WM_INITDIALOG ), creare un'istanza della gestione annotazioni e ottenere un puntatore al puntatore IAccPropServices .

  4. Annotare la proprietà Name del controllo di destinazione usando il metodo IAccPropServices::SetHwndPropStr .

  5. Rilasciare il puntatore IAccPropServices .

  6. Prima che il controllo di destinazione venga distrutto (in genere quando si gestisce il messaggio di WM_DESTROY ), creare un'istanza della gestione annotazioni e ottenere un puntatore alla relativa interfaccia IAccPropServices .

  7. Utilizzare il metodo IAccPropServices::ClearHwndProps per cancellare le annotazioni delle proprietà Name dal controllo di destinazione.

  8. Rilasciare il puntatore IAccPropServices .

  9. Prima dell'uscita dell'applicazione (in genere durante l'elaborazione del messaggio di WM_DESTROY ), rilasciare la libreria COM chiamando la funzione CoUninitialize .

La funzione IAccPropServices::SetHwndPropStr accetta cinque parametri. I primi tre, ovvero hwnd, idObject e idChild, combinano per identificare il controllo. Il quarto parametro , idProp, specifica l'identificatore della proprietà da modificare. Per modificare la proprietà Name, impostare idProp su PROPID_ACC_NAME. Per un elenco di altre proprietà che è possibile impostare tramite annotazione diretta, vedere Uso di annotazione diretta. L'ultimo parametro di SetHwndPropStr, str, è la nuova stringa da usare come proprietà Name.

Esempio di annotazione della proprietà Name

Il codice di esempio seguente illustra come usare l'annotazione diretta per modificare la proprietà Name dell'oggetto IAccess per un controllo. Per mantenere le cose semplici, nell'esempio viene usata una stringa hardcoded ("Nuovo nome controllo") per impostare la proprietà Name. Le stringhe hardcoded non devono essere usate nella versione finale dell'applicazione perché non possono essere localizzate. Invece, caricare sempre le stringhe dal file di risorse. L'esempio non mostra inoltre le chiamate alle funzioni CoInitializeEx e CoUninitialize .

#include <initguid.h>
#include <oleacc.h>

// AnnotateControlName - Uses direct annotation to change the Name property 
// of the IAccessible object for a control.
//
// hDlg - Handle of the dialog box that contains the control.
// hwndCtl - Handle of the control whose Name property is to be changed.
HRESULT AnnotateControlName(HWND hDlg, HWND hwndCtl)
{
    HRESULT hr;        

    IAccPropServices *pAccPropSvc = NULL;  

    // Create an instance of the annotation manager and retrieve the 
    // IAccPropServices pointer.
    hr = CoCreateInstance(CLSID_AccPropServices, NULL, CLSCTX_SERVER, 
        IID_IAccPropServices, (void **) &pAccPropSvc);

    if (hr != S_OK || pAccPropSvc == NULL)
        return hr;

    // Set the Name property for the control.
    // Note: A hard-coded string is used here to keep the example simple.
    // Always use localizable string resources in your applications. 
    hr = pAccPropSvc->SetHwndPropStr(hwndCtl, OBJID_CLIENT, CHILDID_SELF, 
        PROPID_ACC_NAME, L"New Control Name");

    pAccPropSvc->Release();
    
    return hr;
}

// RemoveAnnotatedNameFromControl - Removes the annotated name from the 
// Name property of the IAccessible object for a control.
//
// hDlg - Handle of the dialog box that contains the control.
// hwndCtl - Handle of the control whose annotated name is to be removed.
HRESULT RemoveAnnotatedNameFromControl(HWND hDlg, HWND hwndCtl)
{
    HRESULT hr;

    IAccPropServices *pAccPropSvc = NULL;

    // Create an instance of the annotation manager and retrieve the 
    // IAccPropServices pointer.
    hr = CoCreateInstance(CLSID_AccPropServices, NULL, CLSCTX_SERVER, 
        IID_IAccPropServices, (void **) &pAccPropSvc);

    if (hr != S_OK || pAccPropSvc == NULL)
        return hr;

    // Remove the annotated name from the Name property for the control.
    MSAAPROPID propid = PROPID_ACC_NAME;
    hr = pAccPropSvc->ClearHwndProps(hwndCtl, OBJID_CLIENT, CHILDID_SELF, 
        &propid, 1);

    // Release the annotation manager.
    pAccPropSvc->Release();

    return hr;
}

Informazioni concettuali

API di annotazione dinamica

Specificare la proprietà Name

Strumenti di test