Sicherstellen, dass Benutzeroberflächenelemente richtig benannt sind

In diesem Thema wird die richtige Methode beschrieben, um die Namen der Benutzeroberflächenelemente in Ihren Microsoft Win32-Anwendungen anzugeben, sodass Microsoft Active Accessibility die Namen über die IAccessibleNamenseigenschaft korrekt für Clientanwendungen verfügbar machen kann.

Die Informationen in diesem Abschnitt gelten nur für Microsoft Active Accessibility. Sie gilt nicht für Anwendungen, welche die Microsoft UI Automation verwenden oder die auf Markupsprachen wie HTML, Dynamic HTML (DHTML) oder XML basieren.

Überblick

In Microsoft Active Accessibility wird jedes Benutzeroberflächenelement in einer Anwendung durch ein Objekt dargestellt, das die IAccessible-Schnittstelle verfügbar macht. Clientanwendungen verwenden die Eigenschaften und Methoden der IAccessible-Schnittstelle, um mit dem Benutzeroberflächenelement zu interagieren und Informationen darüber abzurufen. Eine der wichtigsten Eigenschaften, die von der IAccessible-Schnittstelle verfügbar gemacht werden, ist die Namenseigenschaft. Clientanwendungen verwenden die Namenseigenschaft, um ein Benutzeroberflächenelement für den Benutzer zu suchen, zu identifizieren oder anzukündigen. Wenn Microsoft Active Accessibility die Namenseigenschaft eines bestimmten Benutzeroberflächenelements nicht ordnungsgemäß verfügbar macht, können Clientanwendungen dieses Benutzeroberflächenelement dem Benutzer nicht präsentieren, und das Benutzeroberflächenelement ist für Benutzer mit Behinderungen nicht zugänglich.

Wie falsche Benennung Probleme verursacht

Um die Probleme zu veranschaulichen, die durch falsche Benennung von Benutzeroberflächenelementen verursacht werden, sollten Sie sich das in der folgenden Abbildung gezeigte Namenseingabeformular ansehen.

illustration of a simple form for entering first and last name

Obwohl die Benutzeroberflächenelemente im Formular in Ordnung aussehen, ist die programmgesteuerte Implementierung falsch. Für einen Microsoft Active Accessibility-Client, z. B. eine Bildschirmsprachausgabe, lautet die Namenseigenschaft des obersten Bearbeitungssteuerelements „Nachname:“, und die Namenseigenschaft des unteren Bearbeitungssteuerelements ist eine leere Zeichenfolge („ “). Die Sprachausgabe liest das oberste Bearbeitungssteuerelement als „Nachname“, obwohl der Benutzer den Vornamen eingeben soll. Die Sprachausgabe liest das zweite Bearbeitungssteuerelement als „kein Name“, sodass der Benutzer keine Ahnung hat, was in das zweite Bearbeitungssteuerelement eingegeben werden soll. Die Sprachausgabe kann den Benutzer nicht bei der Eingabe von Daten in dieses einfache Formular unterstützen.

Ein weiteres Problem mit dem Formular besteht darin, dass keinem der Bearbeitungssteuerelemente Tastenkombinationen zugewiesen wurden. Der Benutzer wird gezwungen, entweder die TAB-Taste zur Navigation auf die Steuerelemente oder die Maus zu verwenden.

In den folgenden Abschnitten wird die Quelle dieser Probleme erläutert und Richtlinien für die Korrektur bereitgestellt.

So ruft MSAA die Namenseigenschaft ab

Microsoft Active Accessibility ruft die Namenseigenschaftszeichenfolge von verschiedenen Speicherorten abhängig vom Typ des Benutzeroberflächenelements ab. Für die meisten Benutzeroberflächenelemente, die zugeordneten Fenstertext haben, verwendet Microsoft Active Accessibility den Fenstertext als Zeichenfolge der Namenseigenschaft. Beispiele für diese Art von Benutzeroberflächenelement sind Steuerelemente wie Schaltflächen, Menüelemente und QuickInfos.

Bei den folgenden Steuerelementen ignoriert Microsoft Active Accessibility den Fenstertext und sucht stattdessen unmittelbar vor dem Steuerelement in der Aktivierreihenfolge nach einer statischen Beschriftung (oder Gruppenfeldbezeichnung).

  • Kombinationsfelder
  • Datums- und Uhrzeitauswahl
  • Bearbeitungs- und Rich-Edit-Steuerelemente
  • IP-Adresssteuerelemente
  • Listenfelder
  • Listenansichten
  • Statusanzeigen
  • Scrollbars
  • Statische Steuerelemente mit SS_ICON oder SS_BITMAP Formatvorlage
  • Trackbars
  • Strukturansichten

Wenn die vorstehenden Steuerelemente nicht von statischen Textbeschriftungen begleitet werden oder die Bezeichnungen nicht ordnungsgemäß implementiert sind, kann Microsoft Active Accessibility nicht die richtige Namenseigenschaft für Clientanwendungen bereitstellen.

Die meisten der vorherigen Steuerelemente verfügen tatsächlich über zugeordneten Fenstertext. Der Ressourcen-Editor generiert automatisch den Fenstertext, der aus einer generischen Zeichenfolge wie „edit1“ oder „listbox3“ besteht. Obwohl Entwickler den generierten Fenstertext durch aussagekräftigeren Text ersetzen können, tun die meisten es nicht. Da der generierte Fenstertext keine Bedeutung für den Benutzer hat, ignoriert Microsoft Active Accessibility ihn und verwendet stattdessen die zugehörige statische Textbezeichnung.

So finden und beheben Sie Namensprobleme

Im Namenseingabeformular, das unter „Probleme bei der falschen Benennung“ angezeigt wird, besteht die Ursache der Probleme darin, dass die Aktivierreihenfolge der Steuerelemente falsch ist. Das Untersuchen der Benutzeroberfläche mit einem Testtool wie Inspect würde die Probleme mit der Objekthierarchie aufdecken. Der folgende Screenshot zeigt die fehlerhafte Objekthierarchie des Namenseingabeformulars, wie es in Inspect angezeigt wird.

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

Beachten Sie im vorstehenden Screenshot, dass die Objekthierarchie nicht mit der Struktur der Steuerelemente übereinstimmt, wie sie auf der Benutzeroberfläche des Namenseingabeformulars angezeigt werden. Beachten Sie außerdem, dass Inspect dem vorletzten Element den falschen Namen zugewiesen hat (es ist das Bearbeitungssteuerelement für die Eingabe des Vornamens und sollte mit „Vorname:“ benannt sein. Beachten Sie schließlich, dass Inspect keinen Namen für das letzte Element finden konnte (es ist das Bearbeitungssteuerelement für die Eingabe des Nachnamens und sollte mit „Nachname:“ benannt sein.

Das folgende Beispiel zeigt den Inhalt der Ressourcendatei für das Namenseingabeformular. Beachten Sie, dass die Aktivierreihenfolge nicht mit der logischen Struktur der Steuerelemente konsistent ist, wie sie auf der Benutzeroberfläche angezeigt werden. Beachten Sie außerdem, dass für die beiden Bearbeitungssteuerelemente keine Tastenkombinationen angegeben wurden.

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

Um die Probleme mit dem Namenseingabeformular zu beheben, sollte die Ressourcendatei (RC) bearbeitet werden, um Tastenkombinationen anzugeben und die Steuerelemente in der folgenden Reihenfolge zu platzieren:

  1. Die statische Beschriftung „&Vorname:“
  2. Das Bearbeitungssteuerelement zum Eingeben des Vornamens (IDC_EDIT1).
  3. Die statische Beschriftung „&Nachname:“
  4. Das Bearbeitungssteuerelement zum Eingeben des Nachnamens (IDC_EDIT2).
  5. Die Standard-Knopfdrucktaste „OK“.

Das folgende Beispiel zeigt die korrigierte Ressourcendatei für das Namenseingabeformular:

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

Um Korrekturen an einer Ressourcendatei vorzunehmen, können Sie die Datei entweder direkt bearbeiten oder das Tool „Aktivierreihenfolge“ (Tab Order) in Microsoft Visual Studio verwenden. Sie können auf das Tool für die Aktivierreihenfolge in Visual Studio zugreifen, indem Sie STRG+D drücken oder im Menü FormatAktivierreihenfolge auswählen.

Nach dem Korrigieren und Neuerstellen der Anwendung sieht die Benutzeroberfläche des Namenseingabeformulars wie zuvor aus. Microsoft Active Accessibility stellt nun jedoch die richtigen Namenseigenschaften für Clientanwendungen bereit und legt den Fokus richtig fest, wenn der Benutzer die Tastenkombinationen ALT+F oder ALT+L drückt. Außerdem zeigt Inspect die richtige Objekthierarchie an, wie der folgende Screenshot zeigt.

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

So benennen Sie eine Trackbar richtig

Stellen Sie beim Definieren einer Trackleiste (oder eines Schiebereglers) sicher, dass die statische Haupttextbeschriftung für die Trackleiste vor der Trackleiste angezeigt wird und dass die statischen Textbeschriftungen für die minimalen und maximalen Bereiche nach der Trackleiste angezeigt werden. Denken Sie daran, dass Microsoft Active Accessibility die statische Textbeschriftung verwendet, die unmittelbar vor einem Steuerelement als Namenseigenschaft für das Steuerelement steht. Wenn Sie die statische Haupttextbeschriftung unmittelbar vor der Trackleiste platzieren und die anderen Bezeichnungen danach, stellen Sie sicher, dass Microsoft Active Accessibility die richtige Namenseigenschaft für einen Client bereitstellt.

Die folgende Abbildung zeigt eine typische Trackleiste mit einer statischen Haupttextbeschriftung namens „Geschwindigkeit“ und statischen Textbeschriftungen für die Minimum- („min“) und Maximumbereiche („max“).

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

Das folgende Beispiel zeigt die richtige Methode zum Definieren einer Trackleiste und der zugehörigen statischen Textbeschriftungen in der Ressourcendatei:

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

Verwenden von unsichtbaren Beschriftungen zum Benennen von Steuerelementen

Es ist nicht immer möglich oder wünschenswert, für jedes Steuerelement eine sichtbare Beschriftung zu haben. Das Hinzufügen von Bezeichnungen kann z. B. zu unerwünschten Änderungen bei der Darstellung der Benutzeroberfläche führen. In diesem Fall können Sie unsichtbare Bezeichnungen verwenden. Microsoft Active Accessibility übernimmt weiterhin den Text, der mit einer unsichtbaren Beschriftung verknüpft ist, aber die Beschriftung wird nicht in der visuellen Benutzeroberfläche angezeigt und beeinträchtigt sie nicht.

Wie bei sichtbaren Beschriftungen muss eine unsichtbare Beschriftung dem Steuerelement in der Aktivierreihenfolge unmittelbar voranstehen. Um eine Beschriftung in einer Ressourcendatei (RC) unsichtbar zu machen, fügen Sie dem Formatvorlagenteil des statischen Textsteuerelements NOT WS_VISIBLE oder |~WS_VISIBLE hinzu. Wenn Sie den Ressourcen-Editor in Visual Studio verwenden, können Sie die Sichtbarkeitseigenschaft auf „False“ festlegen.

So verwenden Sie direkte Anmerkungen zum Angeben der Namenseigenschaft

Die Standardproxys, die in der Microsoft Active Accessibility-Laufzeitkomponente, Oleacc.dll, enthalten sind, stellen automatisch ein IAccessible-Objekt für alle standardmäßigen Windows-Steuerelemente bereit. Wenn Sie ein standardmäßiges Windows-Steuerelement anpassen, versuchen die Standardproxys alle IAccessible-Eigenschaften für Ihr angepasstes Steuerelement so korrekt wie möglich bereitzustellen. Sie sollten ein benutzerdefiniertes Steuerelement gründlich testen, um sicherzustellen, dass die Standardproxys exakte und vollständige Eigenschaftswerte bereitstellen. Wenn beim Testen ungenaue oder unvollständige Eigenschaftswerte angezeigt werden, können Sie möglicherweise Dynamic Annotation verwenden, das als direktes Anmerken bezeichnet wird, um die richtigen Eigenschaftswerte bereitzustellen und die fehlenden hinzuzufügen.

Beachten Sie, dass dynamische Anmerkungen nicht nur für Steuerelemente verwendet werden, die von Microsoft Active Accessibility-Proxys unterstützt werden. Sie können es auch verwenden, um Eigenschaften für jedes Steuerelement zu ändern oder bereitzustellen, das eine eigene IAccessible-Implementierung bereitstellt.

Dieser Abschnitt konzentriert sich auf die Verwendung direkter Anmerkungen, um einen korrekten Wert für die Namenseigenschaft des IAccessible-Objekts für ein Steuerelement bereitzustellen. Sie können direkte Anmerkungen auch verwenden, um andere Eigenschaftenwerte bereitzustellen. Darüber hinaus sind andere Methoden für dynamische Anmerkungen neben den direkten Anmerkungen verfügbar und die Features und Funktionen der dynamischen Anmerkungs-API reichen weit über die in diesem Abschnitt beschriebenen Funktionen hinaus. Weitere Informationen zu dynamischen Anmerkungen finden Sie unter Dynamic Annotation API.

Schritte zum Kommentieren der Namenseigenschaft

Die Verwendung direkter Anmerkungen zum Ändern der Namenseigenschaft eines Steuerelements umfasst die folgenden Schritte.

  1. Fügen Sie die folgenden Headerdateien ein:

    • Initguid.h
    • Oleacc.h

    Hinweis

    Zum Definieren von GUIDs müssen Sie Initguid.h vor Oleacc.h in derselben Datei einschließen.

     

  2. Initialisieren Sie die COM-Bibliothek (Component Object Model), indem Sie die CoInitializeEx-Funktion aufrufen, in der Regel während des Anwendungsinitialisierungsprozesses.

  3. Erstellen Sie kurz nachdem das Zielsteuerelement erstellt wurde (in der Regel während der WM_INITDIALOG-Nachricht) eine Instanz des Anmerkungsmanagers und rufen Sie einen Zeiger auf seine IAccPropServices-Zeiger ab.

  4. Kommentieren Sie die Namenseigenschaft des Zielsteuerelements mithilfe der IAccPropServices::SetHwndPropStr-Methode.

  5. Geben Sie den IAccPropServices-Zeiger frei.

  6. Erstellen Sie bevor das Zielsteuerelement zerstört wird (in der Regel beim Behandeln der WM_DESTROY-Nachricht) eine Instanz des Anmerkungsmanagers, und rufen Sie einen Zeiger auf die IAccPropServices-Schnittstelle ab.

  7. Verwenden Sie die IAccPropServices::ClearHwndProps-Methode, um die Anmerkungen zur Namenseigenschaft aus dem Zielsteuerelement zu löschen.

  8. Geben Sie den IAccPropServices-Zeiger frei.

  9. Geben Sie bevor die Anwendung beendet wird (in der Regel während der Verarbeitung der WM_DESTROY-Nachricht) die COM-Bibliothek frei, indem Sie die CoUninitialize-Funktion aufrufen.

Die Funktion IAccPropServices::SetHwndPropStr verwendet fünf Parameter. Die ersten drei, hwnd, idObject und idChild, vereinen sich, um das Steuerelement zu identifizieren. Der vierte Parameter, idProp, gibt den Bezeichner der zu ändernden Eigenschaft an. Um die Namenseigenschaft zu ändern, legen Sie idProp auf PROPID_ACC_NAME fest. (Eine Liste mit anderen Eigenschaften, die Sie über direkte Anmerkung festlegen können, finden Sie unter Verwenden von Direct Annotation.) Der letzte Parameter von SetHwndPropStr, str, ist die neue Zeichenfolge, die als Namenseigenschaft verwendet werden soll.

Beispiel für Anmerkungen zur Namenseigenschaft

Im folgenden Beispielcode wird gezeigt, wie Sie die Namenseigenschaft des IAccessible-Objekts für ein Steuerelement mithilfe einer direkten Anmerkung ändern. Um die Dinge einfach zu halten, verwendet das Beispiel eine hartcodierte Zeichenfolge („Neuer Steuerelementname“) zum Festlegen der Namenseigenschaft. Hartcodierte Zeichenfolgen sollten nicht in der endgültigen Version Ihrer Anwendung verwendet werden, da sie nicht lokalisiert werden können. Laden Sie stattdessen immer Zeichenfolgen aus der Ressourcendatei. Außerdem zeigt das Beispiel nicht die Aufrufe der Funktionen CoInitializeEx und CoUninitialize an.

#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;
}