Condividi tramite


Registrare proprietà, eventi e pattern di controllo personalizzati

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

La registrazione prevede il passaggio di un GUID all'automazione dell'interfaccia utente, insieme a informazioni dettagliate sulla proprietà personalizzata, sull'evento o sul modello di controllo. 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 di automazione interfaccia utente, Automazione interfaccia utente convaliderà le informazioni di registrazione personalizzate e userà il codice già registrato anziché l'implementazione del framework "ufficiale", riducendo al minimo i problemi di compatibilità delle applicazioni. Non è possibile rimuovere proprietà, eventi o pattern di controllo già registrati.

Questo argomento contiene le sezioni seguenti:

Registrazione di proprietà ed 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 un UIAutomationPropertyInfo o una struttura UIAutomationEventInfo con informazioni sulla proprietà o sull'evento, inclusi il GUID e una stringa nonlocalizzabile che contiene il nome della proprietà o dell'evento personalizzato. Per le proprietà personalizzate è necessario specificare anche il tipo di dati della proprietà, ad esempio se la proprietà contiene un numero intero o una stringa. Il tipo di dati deve essere uno dei tipi seguenti specificati dall'enumerazioneUIAutomationType. Nessun altro tipo di dati è supportato per le proprietà personalizzate.
    • UIAutomationType_Bool
    • UIAutomationType_Double
    • UIAutomationType_Element
    • UIAutomationType_Int
    • UIAutomationType_Point
    • UIAutomationType_String
  3. Utilizzare la funzioneCoCreateInstance 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 di 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;
}

Gli identificatori di proprietà ed eventi recuperati dai metodi diIUIAutomationRegistrar::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 integer 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. Invece, la registrazione viene annullata in modo implicito quando viene rilasciato l'ultimo oggetto di UI Automation.

Importante

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

 

Implementazione di modelli di controllo personalizzati

Un pattern di controllo personalizzato non è incluso nell'API di automazione interfaccia utente, ma viene fornito da terze parti 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 pattern di controllo. Dopo aver definito il pattern di controllo, sia il client che il provider devono implementare oggetti COM (Component Object Model) di supporto, insieme al codice per registrare il pattern di controllo in fase di esecuzione. Un pattern di controllo personalizzato richiede l'implementazione di due oggetti COM: un wrapper client e un gestore di criteri.

Nota

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

 

Il Wrapper del Client e il Gestore del Pattern

Il wrapper client implementa l'API usata dal client per recuperare le proprietà e chiamare i metodi esposti dal pattern 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 quindi effettua il marshalling delle richieste e delle chiamate al provider.

Il codice che registra un pattern di controllo personalizzato deve fornire una fabbrica di classi che Automazione Interfaccia Utente può usare per creare istanze dell'oggetto wrapper del client. Quando un pattern di controllo personalizzato viene registrato correttamente, Automazione interfaccia utente restituisce un puntatore all'interfaccia IUIAutomationPatternInstance usato dal client per inoltrare le richieste di proprietà e le chiamate di metodo al core di Automazione interfaccia utente.

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

Il codice che registra un modello di controllo personalizzato crea l'oggetto del gestore di modelli e, quando si registra il modello di controllo, fornisce all'Automazione interfaccia utente un puntatore all'interfaccia IUIAutomationPatternHandler.

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

diagramma che mostra il flusso dal wrapper client al gestore di modelli e ai del provider

Gli oggetti che implementano le interfacce del wrapper client e del gestore dei modelli devono essere a thread libero. Inoltre, il core di UI Automation deve essere in grado di chiamare direttamente gli oggetti senza alcun codice di marshaling intermedio.

Implementazione del wrapper client

Il wrapper client è un oggetto che espone un'interfaccia IXxxPattern usata dal client per richiedere le proprietà e chiamare i metodi supportati dal pattern di controllo personalizzato. L'interfaccia è costituita da una coppia di metodi "getter" per ogni proprietà supportata (get_CurrentXxx e get_CachedXxx metodo) e da un metodo "chiamante" per ogni metodo supportato. Quando viene creata un'istanza dell'oggetto, il costruttore dell'oggetto riceve un puntatore all'interfaccia IUIAutomationPatternInstance, implementata dal core di UI Automation. 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 semplice pattern di controllo personalizzato che supporta una singola proprietà. Per un esempio più complesso, vedere 'implementazione di esempio di un pattern 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 criteri è un oggetto che implementa l'interfaccia IUIAutomationPatternHandler. Questa interfaccia include due metodi: IUIAutomationPatternHandler::CreateClientWrapper e Dispatch. Il metodo CreateClientWrapper viene chiamato dal core UI Automation e riceve un puntatore all'interfacciaIUIAutomationPatternInstance. CreateClientWrapper risponde istanziando l'oggetto client wrapper e passando il puntatore dell'interfaccia IUIAutomationPatternInstance al costruttore del client wrapper.

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

L'oggetto gestore del pattern viene creato dallo stesso codice che registra il modello di controllo personalizzato, prima che venga registrato il modello di controllo. Il codice deve passare il puntatore dell'interfaccia dell'oggetto IUIAutomationPatternHandler al core di Automazione dell'interfaccia utente al momento della registrazione.

Nell'esempio seguente viene illustrato come implementare un oggetto gestore pattern per un semplice pattern 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 pattern di controllo personalizzato

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

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

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

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

  1. Compilare una struttura UIAutomationPatternInfo con le informazioni precedenti.
  2. Utilizzare la funzioneCoCreateInstance 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 strutturaUIAutomationPatternInfo.

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

Non esiste alcun metodo che annulla la registrazione di un pattern di controllo personalizzato. Invece, la registrazione viene annullata implicitamente quando viene rilasciato l'ultimo oggetto di Automazione Interfaccia Utente.

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

Implementazione di esempio di un pattern di controllo personalizzato

Questa sezione contiene codice di esempio che illustra come implementare gli oggetti wrapper client e gestori di criteri per un pattern di controllo personalizzato. Nell'esempio viene implementato un pattern di controllo personalizzato basato sul pattern 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;
}

concettuale

Progettazione di Proprietà, Eventi e Pattern di Controllo Personalizzati

Panoramica delle proprietà di automazione UI

Panoramica degli eventi di automazione dell'interfaccia utente

Panoramica modelli di controllo dell'automazione dell'interfaccia utente