Registrieren von benutzerdefinierten Eigenschaften, Ereignissen und Steuerelementmustern

Bevor eine benutzerdefinierte Eigenschaft, ein Ereignis oder ein Steuerelementmuster verwendet werden kann, müssen sowohl der Anbieter als auch der Client die Eigenschaft, das Ereignis oder das Steuerelementmuster zur Laufzeit registrieren. Die Registrierung ist global innerhalb eines Anwendungsprozesses wirksam und bleibt wirksam, bis der Prozess geschlossen wird oder das letzte Microsoft Benutzeroberflächenautomatisierung-Elementobjekt (IUIAutomation oder IRawElementProviderSimple) innerhalb des Prozesses freigegeben wird.

Die Registation umfasst das Übergeben einer GUID an Benutzeroberflächenautomatisierung Benutzer sowie ausführliche Informationen zur benutzerdefinierten Eigenschaft, dem Ereignis oder dem Steuerelementmuster. Der Versuch, dieselbe GUID ein zweites Mal mit den gleichen Informationen zu registrieren, ist erfolgreich, aber der Versuch, dieselbe GUID ein zweites Mal, aber mit unterschiedlichen Informationen (z. B. einer benutzerdefinierten Eigenschaft eines anderen Typs) zu registrieren, ist nicht erfolgreich. Wenn die benutzerdefinierte Spezifikation akzeptiert und in den Benutzeroberflächenautomatisierung-Kern integriert wird, überprüft Benutzeroberflächenautomatisierung zukünftig die benutzerdefinierten Registrierungsinformationen und verwendet den bereits registrierten Code anstelle der "offiziellen" Frameworkimplementierung, wodurch Probleme mit der Anwendungskompatibilität minimiert werden. Sie können keine Eigenschaften, Ereignisse oder Steuerelementmuster entfernen, die bereits registriert sind.

Dieses Thema enthält folgende Abschnitte:

Registrieren von benutzerdefinierten Eigenschaften und Ereignissen

Durch das Registrieren einer benutzerdefinierten Eigenschaft oder eines benutzerdefinierten Ereignisses können anbieter und client eine ID für die Eigenschaft oder das Ereignis abrufen, die dann an verschiedene API-Methoden übergeben werden kann, die IDs als Parameter verwenden.

So registrieren Sie eine Eigenschaft oder ein Ereignis:

  1. Definieren Sie eine GUID für die benutzerdefinierte Eigenschaft oder das benutzerdefinierte Ereignis.
  2. Füllen Sie eine UIAutomationPropertyInfo- oder UIAutomationEventInfo-Struktur mit Informationen über die Eigenschaft oder das Ereignis aus, einschließlich der GUID und einer nicht lokalisierbaren Zeichenfolge, die den Namen der benutzerdefinierten Eigenschaft oder des Ereignisses enthält. Benutzerdefinierte Eigenschaften erfordern auch, dass der Datentyp der Eigenschaft angegeben wird, z. B. ob die Eigenschaft eine ganze Zahl oder eine Zeichenfolge enthält. Der Datentyp muss einer der folgenden Typen sein, die von der UIAutomationType-Enumeration angegeben werden. Für benutzerdefinierte Eigenschaften werden keine anderen Datentypen unterstützt.
    • UIAutomationType _ Bool
    • UIAutomationType _ Double
    • UIAutomationType-Element _
    • UIAutomationType _ Int
    • _UIAutomationType-Punkt
    • _UIAutomationType-Zeichenfolge
  3. Verwenden Sie die CoCreateInstance-Funktion, um eine Instanz des CUIAutomationRegistrar-Objekts zu erstellen und einen Zeiger auf die IUIAutomationRegistrar-Schnittstelle des Objekts abzurufen.
  4. Rufen Sie die IUIAutomationRegistrar::RegisterProperty- oder RegisterEvent-Methode auf, und übergeben Sie die Adresse der UIAutomationPropertyInfo-Struktur oder der UIAutomationEventInfo-Struktur.

Die IUIAutomationRegistrar::RegisterProperty- oder RegisterEvent-Methode gibt eine Eigenschaften-ID oder Ereignis-ID zurück, die eine Anwendung an eine beliebige Benutzeroberflächenautomatisierung-Methode übergeben kann, die einen solchen Bezeichner als Parameter akzeptiert. Beispielsweise können Sie eine registrierte Eigenschaften-ID an die IUIAutomationElement::GetCurrentPropertyValue-Methode oder an die IUIAutomation::CreatePropertyCondition-Methode übergeben.

Im folgenden Beispiel wird veranschaulicht, wie eine benutzerdefinierte Eigenschaft registriert wird.

// Declare a variable for holding the custom property ID.
PATTERNID g_MyCustomPropertyID;
// Define a GUID for the custom property.
GUID GUID_MyCustomProperty = { 0x82f383ff, 0x4b4d, 0x40d3, 
    { 0x8e, 0xd2, 0x90, 0xb5, 0x25, 0x8e, 0xaa, 0x19 } };

HRESULT RegisterProperty()
{
    // Fill the structure with the GUID, name, and data type.
    UIAutomationPropertyInfo MyCustomPropertyInfo = 
    {
        GUID_MyCustomProperty,
        L"MyCustomProp",
        UIAutomationType_String
    };

    // Create the registrar object and get the IUIAutomationRegistrar 
    // interface pointer. 
    IUIAutomationRegistrar * pUIARegistrar = NULL;
    CoCreateInstance(CLSID_CUIAutomationRegistrar, NULL, CLSCTX_INPROC_SERVER, 
            IID_IUIAutomationRegistrar, (void **)&pUIARegistrar);

    if (pUIARegistrar == NULL)
        return E_NOINTERFACE;

    // Register the property and retrieve the property ID. 
    HRESULT hr = pUIARegistrar->RegisterProperty(&MyCustomPropertyInfo, &g_MyCustomPropertyID);
    pUIARegistrar->Release();

    return hr;
}

Die Eigenschaften- und Ereignisbezeichner, die von den Methoden IUIAutomationRegistrar::RegisterProperty und RegisterEvent abgerufen werden, sind nur im Kontext der Anwendung gültig, die sie abruft, und nur für die Dauer der Lebensdauer der Anwendung. Die Registrierungsmethoden können unterschiedliche ganzzahlige Werte für dieselbe GUID zurückgeben, wenn sie über verschiedene Laufzeitinstanzen derselben Anwendung aufgerufen wird.

Es gibt keine Methode, mit der die Registrierung einer benutzerdefinierten Eigenschaft oder eines benutzerdefinierten Ereignisses aufgehoben wird. Stattdessen wird die Registrierung implizit aufgehoben, wenn das letzte Benutzeroberflächenautomatisierung-Objekt freigegeben wird.

Wichtig

Wenn Es sich bei Ihrem Code um Microsoft Active Accessibility (MSAA)-Client handelt, müssen Sie die NotifyWinEvent-Funktion aufrufen, wenn Sie den Wert einer benutzerdefinierten Eigenschaft ändern.

Implementieren von benutzerdefinierten Steuerelementmustern

Ein benutzerdefiniertes Steuerelementmuster ist nicht in der Benutzeroberflächenautomatisierung-API enthalten, wird jedoch zur Laufzeit von einem Drittanbieter bereitgestellt. Entwickler von Client- und Anbieteranwendungen müssen zusammenarbeiten, um ein benutzerdefiniertes Steuerelementmuster zu definieren, einschließlich der Methoden, Eigenschaften und Ereignisse, die vom Steuerelementmuster unterstützt werden. Nach dem Definieren des Steuerelementmusters müssen sowohl der Client als auch der Anbieter unterstützende Component Object Model-Objekte (COM) sowie Code implementieren, um das Steuerelementmuster zur Laufzeit zu registrieren. Ein benutzerdefiniertes Steuerelementmuster erfordert die Implementierung von zwei COM-Objekten: einem Client-Wrapper und einem Musterhandler.

Hinweis

Die Beispiele in den folgenden Themen veranschaulichen, wie ein benutzerdefiniertes Steuerelementmuster implementiert wird, das die Funktionalität des vorhandenen Value-Steuerelementmusters dupliziert. Diese Beispiele dienen nur zu Anweisungszwecken. Ein tatsächliches benutzerdefiniertes Steuerelementmuster sollte Funktionen bereitstellen, die in den Standardsteuermustern Benutzeroberflächenautomatisierung verfügbar sind.

Der Client-Wrapper und der Musterhandler

Der Client-Wrapper implementiert die API, die vom Client zum Abrufen von Eigenschaften und Aufrufen von Methoden verwendet wird, die vom benutzerdefinierten Steuerelementmuster verfügbar gemacht werden. Die API wird als COM-Schnittstelle implementiert, die alle Eigenschaftenanforderungen und Methodenaufrufe an den Benutzeroberflächenautomatisierung-Kern übergibt, der dann die Anforderungen und Aufrufe an den Anbieter marshallt.

Der Code, der ein benutzerdefiniertes Steuerelementmuster registriert, muss eine Klassen factory Benutzeroberflächenautomatisierung, die zum Erstellen von Instanzen des Client-Wrapperobjekts verwendet werden kann. Wenn ein benutzerdefiniertes Steuerelementmuster erfolgreich registriert wurde, gibt Benutzeroberflächenautomatisierung einen IUIAutomationPatternInstance-Schnittstellenzeiger zurück, der vom Client verwendet wird, um Eigenschaftenanforderungen und Methodenaufrufe an den Benutzeroberflächenautomatisierung weiterleiten.

Auf Anbieterseite übernimmt der Benutzeroberflächenautomatisierung Core die Eigenschaftenanforderungen und Methodenaufrufe vom Client und übergibt sie an das Musterhandlerobjekt. Der Musterhandler ruft dann die entsprechenden Methoden auf der Anbieterschnittstelle für das benutzerdefinierte Steuerelementmuster auf.

Der Code, der ein benutzerdefiniertes Steuerelementmuster registriert, erstellt das Musterhandlerobjekt und stellt beim Registrieren des Steuerelementmusters Benutzeroberflächenautomatisierung mit einem Zeiger auf die IUIAutomationPatternHandler-Schnittstelle des Objekts bereit.

Das folgende Diagramm zeigt, wie eine Clienteigenschaftsanforderung oder ein Methodenaufruf vom Client-Wrapper über die Benutzeroberflächenautomatisierung-Kernkomponenten zum Musterhandler und dann zur Anbieterschnittstelle fließt.

Diagramm, das den Fluss vom Client-Wrapper zum Musterhandler und Anbieter zeigt

Die Objekte, die den Client-Wrapper und die Musterhandlerschnittstellen implementieren, müssen über einen Freethread verfügen. Außerdem muss der Benutzeroberflächenautomatisierung die Objekte direkt aufrufen können, ohne zwischengeschalteten Marshallingcode zu verwenden.

Implementieren des Client-Wrappers

Der Client-Wrapper ist ein Objekt, das eine IXxxPattern-Schnittstelle verfügbar macht, die der Client zum Anfordern von Eigenschaften und Aufrufen von Methoden verwendet, die vom benutzerdefinierten Steuerelementmuster unterstützt werden. Die Schnittstelle besteht aus einem Paar von "getter"-Methoden für jede unterstützte Eigenschaft (get _ CurrentXxx- und get CachedXxx-Methode) und einer "caller"-Methode für jede unterstützte _ Methode. Wenn das Objekt instanziiert wird, empfängt der Objektkonstruktor einen Zeiger auf die IUIAutomationPatternInstance-Schnittstelle, die vom Benutzeroberflächenautomatisierung implementiert wird. Die Methoden der IXxxPattern-Schnittstelle verwenden die Methoden IUIAutomationPatternInstance::GetProperty und CallMethod, um Eigenschaftenanforderungen und Methodenaufrufe an den Benutzeroberflächenautomatisierung weiter zu senden.

Das folgende Beispiel zeigt, wie ein Client-Wrapperobjekt für ein einfaches benutzerdefiniertes Steuerelementmuster implementiert wird, das eine einzelne Eigenschaft unterstützt. Ein komplexeres Beispiel finden Sie unter Beispielimplementierung eines benutzerdefinierten Steuerelementmusters.

// Define the client interface.
interface __declspec(uuid("c78b266d-b2c0-4e9d-863b-e3f74a721d47"))
IMyCustomPattern : public IUnknown
{
    STDMETHOD (get_CurrentIsReadOnly)(BOOL * pIsReadOnly) = 0;
    STDMETHOD (get_CachedIsReadOnly)(BOOL * pIsReadOnly) = 0;
};

// Implement the client wrapper class.
class CMyValuePatternClientWrapper :
    public IMyCustomPattern
{
    IUIAutomationPatternInstance * _pInstance;
    
public:
    // Get IUIAutomationPatternInstance interface pointer from the
    // UI Automation core.
    CMyValuePatternClientWrapper(IUIAutomationPatternInstance * pInstance)
        : _pInstance(pInstance)
    {
        _pInstance->AddRef();
    }
    
    ~CMyValuePatternClientWrapper()
    {
        _pInstance->Release();
    }

    // Note: Put standard IUnknown implementation here.

    STDMETHODIMP get_CurrentIsReadOnly(BOOL * pIsReadOnly)
    {
        return _pInstance->GetProperty(0, FALSE, UIAutomationType_Bool, pIsReadOnly);
    }

    STDMETHODIMP get_CachedIsReadOnly(BOOL * pIsReadOnly)
    {
        return _pInstance->GetProperty(0, TRUE, UIAutomationType_Bool, pIsReadOnly);
    }
};

Implementieren des Musterhandlers

Der Musterhandler ist ein Objekt, das die IUIAutomationPatternHandler-Schnittstelle implementiert. Diese Schnittstelle verfügt über zwei Methoden: IUIAutomationPatternHandler::CreateClientWrapper und Dispatch. Die CreateClientWrapper-Methode wird vom Benutzeroberflächenautomatisierung Core aufgerufen und empfängt einen Zeiger auf die IUIAutomationPatternInstance-Schnittstelle. CreateClientWrapper antwortet, indem das Clientwrapperobjekt instanziiert und der IUIAutomationPatternInstance-Schnittstellenzeiger an den Clientwrapperkonstruktor übergeben wird.

Die Dispatch-Methode wird vom Benutzeroberflächenautomatisierung Core verwendet, um Eigenschaftenanforderungen und Methodenaufrufe für das benutzerdefinierte Steuerelementmuster an die Anbieterschnittstelle zu übergeben. Zu den Parametern gehören ein Zeiger auf die Anbieterschnittstelle, der nullbasierte Index des aufgerufenen Eigenschaften-Getters oder der aufgerufenen Methode sowie ein Array von UIAutomationParameter-Strukturen, die die an den Anbieter zu übergebenden Parameter enthalten. Der Musterhandler antwortet, indem er den Indexparameter überprüft, um zu bestimmen, welche Anbietermethode aufgerufen werden soll. Anschließend ruft er diese Anbieterschnittstelle auf und übergibt die in den UIAutomationParameter-Strukturen enthaltenen Parameter.

Das Musterhandlerobjekt wird durch denselben Code instanziiert, der das benutzerdefinierte Steuerelementmuster registriert, bevor das Steuerelementmuster registriert wird. Der Code muss den IUIAutomationPatternHandler-Schnittstellenzeiger des Musterhandlerobjekts zur Benutzeroberflächenautomatisierung-Kern übergeben.

Das folgende Beispiel zeigt, wie ein Musterhandlerobjekt für ein einfaches benutzerdefiniertes Steuerelementmuster implementiert wird, das eine einzelne Eigenschaft unterstützt. Ein komplexeres Beispiel finden Sie unter Beispielimplementierung eines benutzerdefinierten Steuerelementmusters.

// Define the provider interface.
interface __declspec(uuid("9f5266dd-f0ab-4562-8175-c383abb2569e"))
IMyValueProvider : public IUnknown
{
    STDMETHOD (get_IsReadOnly)(BOOL * pIsReadOnly) = 0;
};            

// Index used by IUIAutomationPatternHandler::Dispatch.
const int MyValue_GetIsReadOnly = 0; 
            
// Define the pattern handler class.        
class CMyValuePatternHandler : public IUIAutomationPatternHandler
{
public:
    
    // Put standard IUnknown implementation here.

    STDMETHODIMP CreateClientWrapper(
            IUIAutomationPatternInstance * pPatternInstance, 
            IUnknown ** pClientWrapper)
    {
        *pClientWrapper = new CMyValuePatternClientWrapper(pPatternInstance);
        if (*pClientWrapper == NULL)
            return E_INVALIDARG;
        return S_OK;
    }
    
    STDMETHODIMP Dispatch (IUnknown * pTarget, UINT index, 
            const struct UIAutomationParameter *pParams, UINT cParams)
    {
        switch(index)
        {
        case MyValue_GetIsReadOnly:
            return ((IMyValueProvider*)pTarget)->get_IsReadOnly((BOOL*)pParams[0].pData);
        }
        return E_INVALIDARG;
    }
};

Registrieren eines benutzerdefinierten Steuerelementmusters

Bevor es verwendet werden kann, muss ein benutzerdefiniertes Steuerelementmuster sowohl vom Anbieter als auch vom Client registriert werden. Die Registrierung stellt dem Benutzeroberflächenautomatisierung-Kern ausführliche Informationen zum Steuerelementmuster zur Verfügung und stellt dem Anbieter oder Client die Steuerelementmuster-ID sowie IDs für die Eigenschaften und Ereignisse zur Verfügung, die vom Steuerelementmuster unterstützt werden. Auf Anbieterseite muss das benutzerdefinierte Steuerelementmuster registriert werden, bevor das zugeordnete Steuerelement die WM _ GETOBJECT-Nachricht verarbeitet, oder gleichzeitig.

Beim Registrieren eines benutzerdefinierten Steuerelementmusters stellt der Anbieter oder Client die folgenden Informationen zur Verfügung:

  • Die GUID des benutzerdefinierten Steuerelementmusters.
  • Eine nicht lokalisierbare Zeichenfolge, die den Namen des benutzerdefinierten Steuerelementmusters enthält.
  • Die GUID der Anbieterschnittstelle, die das benutzerdefinierte Steuerelementmuster unterstützt.
  • Die GUID der Clientschnittstelle, die das benutzerdefinierte Steuerelementmuster unterstützt.
  • Ein Array von UIAutomationPropertyInfo-Strukturen, die die vom benutzerdefinierten Steuerelementmuster unterstützten Eigenschaften beschreiben. Für jede Eigenschaft müssen die GUID, der Eigenschaftenname und der Datentyp angegeben werden.
  • Ein Array von UIAutomationMethodInfo-Strukturen, die die vom benutzerdefinierten Steuerelementmuster unterstützten Methoden beschreiben. Für jede Methode enthält die -Struktur die folgenden Informationen: den Methodennamen, die Anzahl der Parameter, eine Liste der Parameterdatentypen und eine Liste der Parameternamen.
  • Ein Array von UIAutomationEventInfo-Strukturen, die die vom benutzerdefinierten Steuerelementmuster ausgelösten Ereignisse beschreiben. Für jedes Ereignis müssen die GUID und der Ereignisname angegeben werden.
  • Die Adresse der IUIAutomationPatternHandler-Schnittstelle des Musterhandlerobjekts, das das benutzerdefinierte Steuerelementmuster für Clients verfügbar macht.

Um das benutzerdefinierte Steuerelementmuster zu registrieren, muss der Anbieter oder Clientcode die folgenden Schritte ausführen:

  1. Füllen Sie eine UIAutomationPatternInfo-Struktur mit den vorherigen Informationen aus.
  2. Verwenden Sie die CoCreateInstance-Funktion, um eine Instanz des CUIAutomationRegistrar-Objekts zu erstellen und einen Zeiger auf die IUIAutomationRegistrar-Schnittstelle des Objekts abzurufen.
  3. Rufen Sie die IUIAutomationRegistrar::RegisterPattern-Methode auf, und übergeben Sie die Adresse der UIAutomationPatternInfo-Struktur.

Die RegisterPattern-Methode gibt eine Steuerelementmuster-ID zusammen mit einer Liste von Eigenschaften-IDs und Ereignis-IDs zurück. Eine Anwendung kann diese IDs an jede Benutzeroberflächenautomatisierung übergeben, die einen solchen Bezeichner als Parameter akzeptiert. Beispielsweise können Sie eine registrierte Muster-ID an die IUIAutomationElement::GetCurrentPattern-Methode übergeben, um einen Zeiger auf die Anbieterschnittstelle für das Steuerelementmuster abzurufen.

Es gibt keine Methode, mit der die Registrierung eines benutzerdefinierten Steuerelementmusters aufgehoben wird. Stattdessen wird die Registrierung implizit aufgehoben, wenn das letzte Benutzeroberflächenautomatisierung freigegeben wird.

Ein Beispiel zum Registrieren eines benutzerdefinierten Steuerelementmusters finden Sie im folgenden Abschnitt.

Beispielimplementierung eines benutzerdefinierten Steuerelementmusters

Dieser Abschnitt enthält Beispielcode, der veranschaulicht, wie der Client-Wrapper und die Musterhandlerobjekte für ein benutzerdefiniertes Steuerelementmuster implementiert werden. Im Beispiel wird ein benutzerdefiniertes Steuerelementmuster implementiert, das auf dem Value-Steuerelementmuster basiert.

// Step 1: Define the public provider and client interfaces using IDL. Interface 
// definitions are in C here to simplify the example.

// Define the provider interface.
interface __declspec(uuid("9f5266dd-f0ab-4562-8175-c383abb2569e"))
IMyValueProvider : public IUnknown
{
    STDMETHOD (get_Value)(BSTR * pValue) = 0;
    STDMETHOD (get_IsReadOnly)(BOOL * pIsReadOnly) = 0;
    STDMETHOD (SetValue)(LPCWSTR pNewValue) = 0;
    STDMETHOD (Reset)() = 0;
};

// Define the client interface.
interface __declspec(uuid("103b8323-b04a-4180-9140-8c1e437713a3"))
IUIAutomationMyValuePattern : public IUnknown
{
    STDMETHOD (get_CurrentValue)(BSTR * pValue) = 0;
    STDMETHOD (get_CachedValue)(BSTR * pValue) = 0;

    STDMETHOD (get_CurrentIsReadOnly)(BOOL * pIsReadOnly) = 0;
    STDMETHOD (get_CachedIsReadOnly)(BOOL * pIsReadOnly) = 0;

    STDMETHOD (SetValue)(LPCWSTR pNewValue) = 0;
    STDMETHOD (Reset)() = 0;
};

// Enumerate the properties and methods starting from 0, and placing the 
// properties first. 
enum
{
    MyValue_GetValue = 0,
    MyValue_GetIsReadOnly = 1,
    MyValue_SetValue = 2,
    MyValue_Reset = 3,
};

// Step 2: Implement the client wrapper class.
class CMyValuePatternClientWrapper :
    public IUIAutomationMyValuePattern
{
    IUIAutomationPatternInstance * _pInstance;

public:
    // Get IUIAutomationPatternInstance interface pointer.
    CMyValuePatternClientWrapper(IUIAutomationPatternInstance * pInstance)
    {
        _pInstance = pInstance;
        _pInstance->AddRef();
    }

    // Put standard IUnknown implementation here.

    STDMETHODIMP get_CurrentValue(BSTR * pValue)
    {
        return _pInstance->GetProperty(MyValue_GetValue, FALSE, 
                UIAutomationType_String, pValue);
    }

    STDMETHODIMP get_CachedValue(BSTR * pValue)
    {
        return _pInstance->GetProperty(MyValue_GetValue, TRUE, 
                UIAutomationType_String, pValue);
    }

    STDMETHODIMP get_CurrentIsReadOnly(BOOL * pIsReadOnly)
    {
        return _pInstance->GetProperty(MyValue_GetIsReadOnly, FALSE, 
                UIAutomationType_Bool, pIsReadOnly);
    }

    STDMETHODIMP get_CachedIsReadOnly(BOOL * pIsReadOnly)
    {
        return _pInstance->GetProperty(MyValue_GetIsReadOnly, TRUE, 
                UIAutomationType_Bool, pIsReadOnly);
    }

    STDMETHODIMP SetValue(LPCWSTR pValue)
    {
        UIAutomationParameter SetValueParams[] = 
                { UIAutomationType_String, &pValue };
        return _pInstance->CallMethod(MyValue_SetValue,  SetValueParams, 
                ARRAYSIZE(SetValueParams));
    }

    STDMETHODIMP Reset()
    {
        return _pInstance->CallMethod(MyValue_Reset, NULL, 0);
    }
};

// Step 3: Implement the pattern handler class.
class CMyValuePatternHandler : public IUIAutomationPatternHandler
{
public:

    // Put standard IUnknown implementation here.
    
    STDMETHODIMP CreateClientWrapper(
            IUIAutomationPatternInstance * pPatternInstance, 
            IUnknown ** pClientWrapper)
    {
        *pClientWrapper = new CMyValuePatternClientWrapper(pPatternInstance);
        if (*pClientWrapper == NULL)
            return E_INVALIDARG;
        return S_OK;
    }
    
    STDMETHODIMP Dispatch (IUnknown * pTarget, UINT index, 
            const struct UIAutomationParameter *pParams, 
            UINT cParams)
    {
        switch(index)
        {
        case MyValue_GetValue:
            return ((IMyValueProvider*)pTarget)->get_Value((BSTR*)pParams[0].pData);

        case MyValue_GetIsReadOnly:
            return ((IMyValueProvider*)pTarget)->get_IsReadOnly((BOOL*)pParams[0].pData);

        case MyValue_SetValue:
            return ((IMyValueProvider*)pTarget)->SetValue(*(LPCWSTR*)pParams[0].pData);

        case MyValue_Reset:
            return ((IMyValueProvider*)pTarget)->Reset();
        }
        return E_INVALIDARG;
    }
};

CMyValuePatternHandler g_MyValuePatternHandler;

// Step 4: Declare information about the properties and methods supported
// by the custom control pattern.

// Define GUIDs for the custom control pattern and each of its properties 
// and events.
static const GUID MyValue_Pattern_Guid = { 0xa49aa3c0, 0xe413, 0x4ecf, 
        { 0xa1, 0xc3, 0x37, 0x42, 0xa7, 0x86, 0x67, 0x3f } };
static const GUID MyValue_Value_Property_Guid = { 0xe58f3f67, 0x22c7, 0x44f0, 
        { 0x83, 0x55, 0xd8, 0x76, 0x14, 0xa1, 0x10, 0x81 } };
static const GUID MyValue_IsReadOnly_Property_Guid = { 0x480540f2, 0x9829, 0x4acd, 
        { 0xb8, 0xea, 0x6e, 0x2a, 0xdc, 0xe5, 0x3a, 0xfb } };
static const GUID MyValue_Reset_Event_Guid = { 0x5b80edd3, 0x67f, 0x4a70, 
        { 0xb0, 0x7, 0x4, 0x12, 0x85, 0x11, 0x1, 0x7a } };

// Declare information about the properties, in the same order as the
// previously defined "MyValue_" enumerated type.
UIAutomationPropertyInfo g_MyValueProperties[] = 
{
    // GUID, name, data type.
    { MyValue_Value_Property_Guid, L"MyValuePattern.Value", 
                                                    UIAutomationType_String },
    { MyValue_IsReadOnly_Property_Guid, L"MyValuePattern.IsReadOnly", 
                                                    UIAutomationType_Bool },
};

// Declare information about the event.
UIAutomationEventInfo g_MyValueEvents [] =
{
    { MyValue_Reset_Event_Guid,  L"MyValuePattern.Reset" },
};

// Declare the data type and name of the SetValue method parameter. 
UIAutomationType g_SetValueParamTypes[] = { UIAutomationType_String };
LPCWSTR g_SetValueParamNames[] = {L"pNewValue"};

// Declare information about the methods.
UIAutomationMethodInfo g_MyValueMethods[] =
{
    // Name, focus flag, count of in parameters, count of out parameters, types, parameter names.
    { L"MyValuePattern.SetValue", TRUE, 1, 0, g_SetValueParamTypes, g_SetValueParamNames },
    { L"MyValuePattern.Reset", TRUE, 0, 0, NULL, NULL },
};

// Declare the custom control pattern using the previously defined information.
UIAutomationPatternInfo g_ValuePatternInfo =
{
    MyValue_Pattern_Guid,
    L"MyValuePattern",
    __uuidof(IMyValueProvider),
    __uuidof(IUIAutomationMyValuePattern),
    ARRAYSIZE(g_MyValueProperties), g_MyValueProperties, // properties
    ARRAYSIZE(g_MyValueMethods), g_MyValueMethods,       // methods
    ARRAYSIZE(g_MyValueEvents), g_MyValueEvents,         // events 
    &g_MyValuePatternHandler
};

// Step 5: Register the custom control pattern and retrieve the control pattern and property 
// identifiers.

// Control pattern, property, and event IDs.
PATTERNID  g_MyValue_PatternID;
PROPERTYID g_MyValue_Value_PropertyID;
PROPERTYID g_MyValue_IsReadOnly_PropertyID;
EVENTID    g_MyValueReset_EventID;

// ID used by the client to determine whether the custom control pattern is available.
PROPERTYID g_IsMyValuePatternAvailable_PropertyID;

HRESULT RegisterPattern()
{
    // Create the registrar object and get the IUIAutomationRegistrar interface pointer. 
    IUIAutomationRegistrar * pUIARegistrar;
    CoCreateInstance(CLSID_CUIAutomationRegistrar, NULL, CLSCTX_INPROC_SERVER, 
            IID_IUIAutomationRegistrar, (void **)&pUIARegistrar);

    if (pUIARegistrar == NULL)
        return E_NOINTERFACE;

    PROPERTYID propIDs[2]; // Array for property IDs.

    // Register the control pattern.
    HRESULT hr = pUIARegistrar->RegisterPattern(
        &g_ValuePatternInfo,
        &g_MyValue_PatternID,
        &g_IsMyValuePatternAvailable_PropertyID,
        ARRAYSIZE(propIDs), 
        propIDs,
        1,
        &g_MyValueReset_EventID);
            
    if (hr == S_OK)
    {
        // Copy the property IDs.
        g_MyValue_Value_PropertyID = propIDs[0];
        g_MyValue_IsReadOnly_PropertyID = propIDs[1];
    }

    pUIARegistrar->Release();
    return hr;
}

Konzept

Entwerfen von benutzerdefinierten Eigenschaften, Ereignissen und Steuerelementmustern

Übersicht über die Benutzeroberflächenautomatisierungs-Eigenschaften

Übersicht über Benutzeroberflächenautomatisierungs-Ereignisse

Übersicht über Steuerelementmuster für Benutzeroberflächenautomatisierung