Condividi tramite


Registrare proprietà, eventi e modelli di controllo personalizzati

Prima che sia possibile usare una proprietà personalizzata, un evento o un modello di controllo, sia il provider che il client devono registrare la proprietà, l'evento o il modello di controllo in fase di esecuzione. La registrazione è effettiva a livello globale all'interno di un processo dell'applicazione e rimane effettiva fino alla chiusura del processo o all'ultimo oggetto elemento di Microsoft Automazione interfaccia utente (IUIAutomation o IRawElementProviderSimple) rilasciato all'interno del processo.

La registazione comporta il passaggio di un GUID a Automazione interfaccia utente, insieme a informazioni dettagliate sulla proprietà, l'evento o il modello di controllo personalizzati. Il tentativo di registrare lo stesso GUID una seconda volta con le stesse informazioni avrà esito positivo, ma il tentativo di registrare lo stesso GUID una seconda volta, ma con informazioni diverse (ad esempio, una proprietà personalizzata di un tipo diverso) avrà esito negativo. In futuro, se la specifica personalizzata viene accettata e integrata nel core Automazione interfaccia utente, Automazione interfaccia utente convalida le informazioni di registrazione personalizzate e userà il codice già registrato anziché l'implementazione del framework "ufficiale", riducendo al minimo i problemi di compatibilità dell'applicazione. Non è possibile rimuovere proprietà, eventi o modelli di controllo già registrati.

In questo argomento sono incluse le sezioni seguenti:

Registrazione di proprietà e eventi personalizzati

La registrazione di una proprietà o di un evento personalizzato consente al provider e al client di ottenere un ID per la proprietà o l'evento, che può quindi essere passato a vari metodi API che accettano GLI ID come parametri.

Per registrare una proprietà o un evento:

  1. Definire un GUID per la proprietà o l'evento personalizzato.
  2. Compilare una struttura UIAutomationPropertyInfo o uiAutomationEventInfo con informazioni sulla proprietà o sull'evento, incluso il GUID e una stringa nonlocalizzabile contenente il nome della proprietà o dell'evento personalizzato. Le proprietà personalizzate richiedono anche il tipo di dati della proprietà da specificare, ad esempio se la proprietà contiene un intero o una stringa. Il tipo di dati deve essere uno dei tipi seguenti specificati dall'enumerazione UIAutomationType . Nessun altro tipo di dati è supportato per le proprietà personalizzate.
    • UIAutomationType_Bool
    • UIAutomationType_Double
    • UIAutomationType_Element
    • UIAutomationType_Int
    • UIAutomationType_Point
    • UIAutomationType_String
  3. Usare la funzione CoCreateInstance per creare un'istanza dell'oggetto CUIAutomationRegistrar e recuperare un puntatore all'interfaccia IUIAutomationRegistrar dell'oggetto.
  4. Chiamare il metodo IUIAutomationRegistrar::RegisterProperty o RegisterEvent e passare l'indirizzo della struttura UIAutomationPropertyInfo o della struttura UIAutomationEventInfo .

Il metodo IUIAutomationRegistrar::RegisterProperty o RegisterEvent restituisce un ID proprietà o un ID evento che un'applicazione può passare a qualsiasi metodo Automazione interfaccia utente che accetta tale identificatore come parametro. Ad esempio, è possibile passare un ID proprietà registrato al metodo IUIAutomationElement::GetCurrentPropertyValue o al metodo IUIAutomation::CreatePropertyCondition .

Nell'esempio seguente viene illustrato come registrare una proprietà personalizzata.

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

I metodi IUIAutomationRegistrar::RegisterProperty e RegisterEvent sono validi solo nel contesto dell'applicazione che li recupera e solo per la durata della durata dell'applicazione. I metodi di registrazione possono restituire valori interi diversi per lo stesso GUID quando viene chiamato su istanze di runtime diverse della stessa applicazione.

Non esiste alcun metodo che annulla la registrazione di una proprietà o di un evento personalizzato. Vengono invece annullati in modo implicito quando viene rilasciato l'ultimo oggetto Automazione interfaccia utente.

Importante

Se il codice è un client MICROSOFT Active Accessibility (MSAA), è necessario chiamare la funzione NotifyWinEvent quando si modifica il valore di una proprietà personalizzata.

 

Implementazione di modelli di controllo personalizzati

Un modello di controllo personalizzato non è incluso nell'API Automazione interfaccia utente, ma viene fornito da una terza parte in fase di esecuzione. Gli sviluppatori di applicazioni client e provider devono collaborare per definire un modello di controllo personalizzato, inclusi i metodi, le proprietà e gli eventi supportati dal modello di controllo. Dopo aver definito il modello di controllo, sia il client che il provider devono implementare oggetti Component Object Model (COM), insieme al codice per registrare il modello di controllo in fase di esecuzione. Un modello di controllo personalizzato richiede l'implementazione di due oggetti COM: un wrapper client e un gestore di modelli.

Nota

Gli esempi negli argomenti seguenti illustrano come implementare un modello di controllo personalizzato che duplica la funzionalità del modello di controllo Valore esistente. Questi esempi sono solo a scopo informativo. Un modello di controllo personalizzato effettivo deve fornire funzionalità non disponibili dai modelli di controllo standard Automazione interfaccia utente.

 

Wrapper client e gestore modelli

Il wrapper client implementa l'API usata dal client per recuperare proprietà e chiamare metodi esposti dal modello di controllo personalizzato. L'API viene implementata come interfaccia COM che passa tutte le richieste di proprietà e le chiamate al metodo al core di Automazione interfaccia utente, che esegue quindi il marshalling delle richieste e delle chiamate al provider.

Il codice che registra un modello di controllo personalizzato deve fornire una classe factory che Automazione interfaccia utente può usare per creare istanze dell'oggetto wrapper client. Quando viene registrato correttamente un modello di controllo personalizzato, Automazione interfaccia utente restituisce un puntatore dell'interfaccia IUIAutomationPatternInstance utilizzato dal client per inoltrare richieste e metodi di proprietà al core di Automazione interfaccia utente.

Sul lato provider, il core Automazione interfaccia utente accetta le richieste di proprietà e le chiamate al metodo dal client e li passa all'oggetto gestore pattern. Il gestore dei modelli chiama quindi i metodi appropriati nell'interfaccia del provider per il modello di controllo personalizzato.

Il codice che registra un modello di controllo personalizzato crea l'oggetto gestore pattern e, durante la registrazione del modello, fornisce Automazione interfaccia utente con un puntatore all'interfaccia IUIAutomationPatternHandler dell'oggetto.

Il diagramma seguente illustra come viene eseguita una richiesta di proprietà client o una chiamata al metodo dal wrapper client, tramite i componenti principali di Automazione interfaccia utente al gestore dei modelli e quindi all'interfaccia del provider.

diagramma che mostra il flusso dal wrapper client al gestore dei modelli e al provider

Gli oggetti che implementano le interfacce del wrapper client e del gestore dei modelli devono essere thread gratuiti. Inoltre, il core Automazione interfaccia utente deve essere in grado di chiamare direttamente gli oggetti senza alcun codice di marshalling intermedio.

Implementazione del wrapper client

Il wrapper client è un oggetto che espone un'interfaccia IXxxPattern usata dal client per richiedere proprietà e chiamare metodi supportati dal modello di controllo personalizzato. L'interfaccia è costituita da una coppia di metodi "getter" per ogni proprietà supportata (get_CurrentXxx e get_CachedXxx metodo) e un metodo "chiamante" per ogni metodo supportato. Quando l'oggetto viene creata un'istanza, il costruttore dell'oggetto riceve un puntatore all'interfaccia IUIAutomationPatternInstance, implementata dal core Automazione interfaccia utente. I metodi dell'interfaccia IXxxPattern usano i metodi IUIAutomationPatternInstance::GetProperty e CallMethod per inoltrare richieste di proprietà e chiamate di metodo al core di Automazione interfaccia utente.

Nell'esempio seguente viene illustrato come implementare un oggetto wrapper client per un modello di controllo personalizzato semplice che supporta una singola proprietà. Per un esempio più complesso, vedere Implementazione di esempio di un modello di controllo personalizzato.

// 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);
    }
};

Implementazione del gestore dei modelli

Il gestore dei modelli è un oggetto che implementa l'interfaccia IUIAutomationPatternHandler . Questa interfaccia include due metodi: IUIAutomationPatternHandler::CreateClientWrapper e Dispatch. Il metodo CreateClientWrapper viene chiamato dal core Automazione interfaccia utente e riceve un puntatore all'interfaccia IUIAutomationPatternInstance. CreateClientWrapper risponde creando un'istanza dell'oggetto wrapper client e passando il puntatore dell'interfaccia IUIAutomationPatternInstance al costruttore wrapper client.

Il metodo Dispatch viene usato dal core Automazione interfaccia utente per passare richieste di proprietà e chiamate al metodo all'interfaccia del provider per il modello di controllo personalizzato. I parametri includono un puntatore all'interfaccia del provider, l'indice in base zero della proprietà getter o metodo chiamato e una matrice di strutture UIAutomationParameter che contengono i parametri da passare al provider. Il gestore dei modelli risponde controllando il parametro indice per determinare quale metodo provider chiamare e quindi chiama tale interfaccia del provider, passando i parametri contenuti nelle strutture UIAutomationParameter .

L'oggetto del gestore dei modelli viene creato dallo stesso codice che registra il modello di controllo personalizzato prima della registrazione del modello di controllo. Il codice deve passare il puntatore dell'interfaccia IUIAutomationPatternHandler dell'oggetto del modello al core di Automazione interfaccia utente in fase di registrazione.

Nell'esempio seguente viene illustrato come implementare un oggetto gestore modelli per un semplice modello di controllo personalizzato che supporta una singola proprietà. Per un esempio più complesso, vedere Implementazione di esempio di un modello di controllo personalizzato.

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

Registrazione di un modello di controllo personalizzato

Prima di poterlo usare, è necessario registrare un modello di controllo personalizzato sia dal provider che dal client. La registrazione fornisce al core Automazione interfaccia utente informazioni dettagliate sul modello di controllo e fornisce al provider o al client l'ID del modello di controllo e gli ID per le proprietà e gli eventi supportati dal modello di controllo. Sul lato provider, il modello di controllo personalizzato deve essere registrato prima che il controllo associato gestisca il messaggio WM_GETOBJECT o contemporaneamente.

Quando si registra un modello di controllo personalizzato, il provider o il client fornisce le informazioni seguenti:

  • GUID del modello di controllo personalizzato.
  • Stringa nonlocalizzabile contenente il nome del modello di controllo personalizzato.
  • GUID dell'interfaccia del provider che supporta il modello di controllo personalizzato.
  • GUID dell'interfaccia client che supporta il modello di controllo personalizzato.
  • Matrice di strutture UIAutomationPropertyInfo che descrivono le proprietà supportate dal modello di controllo personalizzato. Per ogni proprietà, è necessario specificare il GUID, il nome della proprietà e il tipo di dati.
  • Matrice di strutture UIAutomationMethodInfo che descrivono i metodi supportati dal modello di controllo personalizzato. Per ogni metodo, la struttura include le informazioni seguenti: il nome del metodo, un numero di parametri, un elenco di tipi di dati dei parametri e un elenco dei nomi dei parametri.
  • Matrice di strutture UIAutomationEventInfo che descrivono gli eventi generati dal modello di controllo personalizzato. Per ogni evento, è necessario specificare il GUID e il nome dell'evento.
  • Indirizzo dell'interfaccia IUIAutomationPatternHandler dell'oggetto gestore pattern che rende disponibile il modello di controllo personalizzato ai client.

Per registrare il modello di controllo personalizzato, il provider o il codice client devono eseguire la procedura seguente:

  1. Compilare una struttura UIAutomationPatternInfo con le informazioni precedenti.
  2. Usare la funzione CoCreateInstance per creare un'istanza dell'oggetto CUIAutomationRegistrar e recuperare un puntatore all'interfaccia IUIAutomationRegistrar dell'oggetto.
  3. Chiamare il metodo IUIAutomationRegistrar::RegisterPattern , passando l'indirizzo della struttura UIAutomationPatternInfo .

Il metodo RegisterPattern restituisce un ID modello di controllo, insieme a un elenco di ID proprietà e ID evento. Un'applicazione può passare questi ID a qualsiasi metodo Automazione interfaccia utente che accetta tale identificatore come parametro. Ad esempio, è possibile passare un ID modello registrato al metodo IUIAutomationElement::GetCurrentPattern per recuperare un puntatore all'interfaccia del provider per il modello di controllo.

Non esiste alcun metodo che annulla la registrazione di un modello di controllo personalizzato. Viene invece annullata la registrazione implicita quando viene rilasciato l'ultimo oggetto Automazione interfaccia utente.

Per un esempio che illustra come registrare un modello di controllo personalizzato, vedere la sezione seguente.

Implementazione di esempio di un modello di controllo personalizzato

Questa sezione contiene codice di esempio che illustra come implementare gli oggetti wrapper client e gestore dei modelli per un modello di controllo personalizzato. L'esempio implementa un modello di controllo personalizzato basato sul modello di controllo Value .

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

Informazioni concettuali

Progettazione di proprietà, eventi e modelli di controllo personalizzati

Cenni preliminari sulle proprietà di automazione interfaccia utente

Cenni preliminari sugli eventi di automazione interfaccia utente

Cenni preliminari sui pattern di controllo per l'automazione interfaccia utente