Поделиться через


Регистрация настраиваемых свойств, событий и шаблонов элементов управления

Прежде чем можно будет использовать пользовательское свойство, событие или шаблон элемента управления, поставщик и клиент должны зарегистрировать свойство, событие или шаблон элемента управления во время выполнения. Регистрация действует глобально в рамках процесса приложения и остается в действии до тех пор, пока процесс не закроется или не будет выпущен последний объект элемента Microsoft модель автоматизации пользовательского интерфейса (IUIAutomation или IRawElementProviderSimple).

Registation включает в себя передачу GUID в модель автоматизации пользовательского интерфейса вместе с подробными сведениями о пользовательском свойстве, событии или шаблоне элемента управления. Попытка повторно зарегистрировать один и тот же GUID с теми же сведениями будет успешной, но попытка зарегистрировать тот же GUID во второй раз, но с другими сведениями (например, пользовательское свойство другого типа) завершится ошибкой. В будущем, если пользовательская спецификация будет принята и интегрирована в ядро модель автоматизации пользовательского интерфейса, модель автоматизации пользовательского интерфейса проверит сведения о пользовательской регистрации и будет использовать уже зарегистрированный код вместо "официальной" реализации платформы. тем самым сводя к минимуму проблемы совместимости приложений. Нельзя удалить уже зарегистрированные свойства, события или шаблоны элементов управления.

Этот раздел состоит из следующих подразделов.

Регистрация пользовательских свойств и событий

Регистрация настраиваемого свойства или события позволяет поставщику и клиенту получить идентификатор свойства или события, который затем может быть передан различным методам API, которые принимают идентификаторы в качестве параметров.

Чтобы зарегистрировать свойство или событие, выполните приведенные далее действия.

  1. Определите GUID для настраиваемого свойства или события.
  2. Заполните структуру UIAutomationPropertyInfo или UIAutomationEventInfo сведениями о свойстве или событии, включая GUID и нелокальную строку, содержащую имя настраиваемого свойства или события. Настраиваемые свойства также требуют указания типа данных свойства, например, содержит ли свойство целое число или строку. Тип данных должен быть одним из следующих типов, заданных перечислением UIAutomationType . Другие типы данных не поддерживаются для пользовательских свойств.
    • UIAutomationType_Bool
    • UIAutomationType_Double
    • UIAutomationType_Element
    • UIAutomationType_Int
    • UIAutomationType_Point
    • UIAutomationType_String
  3. Используйте функцию CoCreateInstance для создания экземпляра объекта CUIAutomationRegistrar и получения указателя на интерфейс IUIAutomationRegistrar объекта.
  4. Вызовите метод IUIAutomationRegistrar::RegisterProperty или RegisterEvent и передайте адрес структуры UIAutomationPropertyInfo или структуры UIAutomationEventInfo .

Метод IUIAutomationRegistrar::RegisterProperty или RegisterEvent возвращает идентификатор свойства или идентификатор события, который приложение может передать любому методу модель автоматизации пользовательского интерфейса, который принимает такой идентификатор в качестве параметра. Например, можно передать зарегистрированный идентификатор свойства методу IUIAutomationElement::GetCurrentPropertyValue или методу IUIAutomation::CreatePropertyCondition .

В следующем примере показано, как зарегистрировать пользовательское свойство.

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

Идентификаторы свойств и событий, полученные методами IUIAutomationRegistrar::RegisterProperty и RegisterEvent , действительны только в контексте приложения, которое их извлекает, и только на протяжении времени существования приложения. Методы регистрации могут возвращать разные целочисленные значения для одного и того же GUID при вызове для разных экземпляров среды выполнения одного приложения.

Нет метода, отменяющего регистрацию настраиваемого свойства или события. Вместо этого они неявно отменяются при освобождении последнего объекта модель автоматизации пользовательского интерфейса.

Важно!

Если ваш код является клиентом Microsoft Active Accessibility (MSAA), необходимо вызвать функцию NotifyWinEvent при изменении значения настраиваемого свойства.

 

Реализация пользовательских шаблонов элементов управления

Пользовательский шаблон элемента управления не включается в API модель автоматизации пользовательского интерфейса, но предоставляется сторонним поставщиком во время выполнения. Разработчики клиентских и поставщиков приложений должны совместно определять пользовательский шаблон элемента управления, включая методы, свойства и события, которые будет поддерживать шаблон элемента управления. После определения шаблона элемента управления клиент и поставщик должны реализовать вспомогательные com-объекты вместе с кодом для регистрации шаблона элемента управления во время выполнения. Для пользовательского шаблона элемента управления требуется реализация двух COM-объектов: клиентской оболочки и обработчика шаблонов.

Примечание

В примерах в следующих разделах показано, как реализовать пользовательский шаблон элемента управления, который дублирует функциональные возможности существующего шаблона элемента управления "Значение ". Эти примеры предназначены только для обучения. Фактический пользовательский шаблон элемента управления должен предоставлять функциональные возможности, недоступные из стандартных шаблонов элементов управления модель автоматизации пользовательского интерфейса.

 

Клиентская оболочка и обработчик шаблонов

Клиентская оболочка реализует API, который используется клиентом для получения свойств и вызова методов, предоставляемых пользовательским шаблоном элемента управления. API реализуется в виде COM-интерфейса, который передает все запросы свойств и вызовы методов в ядро модель автоматизации пользовательского интерфейса, которое затем маршалирует запросы и вызовы к поставщику.

Код, регистрирующий пользовательский шаблон элемента управления, должен предоставлять фабрику классов, которую модель автоматизации пользовательского интерфейса может использовать для создания экземпляров объекта-оболочки клиента. После успешной регистрации шаблона пользовательского элемента управления модель автоматизации пользовательского интерфейса возвращает указатель интерфейса IUIAutomationPatternInstance, который используется клиентом для пересылки запросов свойств и вызовов методов в ядро модель автоматизации пользовательского интерфейса.

На стороне поставщика ядро модель автоматизации пользовательского интерфейса принимает запросы свойств и вызовы методов от клиента и передает их объекту обработчика шаблонов. Затем обработчик шаблона вызывает соответствующие методы в интерфейсе поставщика для шаблона пользовательского элемента управления.

Код, регистрирующий шаблон пользовательского элемента управления, создает объект обработчика шаблонов и при регистрации шаблона элемента управления предоставляет модель автоматизации пользовательского интерфейса с указателем на интерфейс IUIAutomationPatternHandler объекта.

На следующей схеме показано, как запрос на свойство клиента или вызов метода передается из клиентской оболочки через модель автоматизации пользовательского интерфейса основные компоненты в обработчик шаблонов, а затем в интерфейс поставщика.

Схема, показывающая поток от клиентской оболочки к обработчику шаблонов и поставщику

Объекты, реализующие интерфейсы клиентской оболочки и обработчика шаблонов, должны быть свободно потоками. Кроме того, ядро модель автоматизации пользовательского интерфейса должно иметь возможность вызывать объекты напрямую без промежуточного кода маршалинга.

Реализация клиентской оболочки

Клиентская оболочка — это объект, предоставляющий интерфейс IXxxPattern, который клиент использует для запроса свойств и вызова методов, поддерживаемых шаблоном пользовательского элемента управления. Интерфейс состоит из пары методов getter для каждого поддерживаемого свойства (get_CurrentXxx и get_CachedXxx) и метода "вызывающий" для каждого поддерживаемого метода. При создании экземпляра объекта конструктор объектов получает указатель на интерфейс IUIAutomationPatternInstance, который реализуется ядром модель автоматизации пользовательского интерфейса. Методы интерфейса IXxxPattern используют методы IUIAutomationPatternInstance::GetProperty и CallMethod для пересылки запросов свойств и вызовов методов в ядро модель автоматизации пользовательского интерфейса.

В следующем примере показано, как реализовать объект-оболочку клиента для простого пользовательского шаблона элемента управления, поддерживающего одно свойство. Более сложный пример см. в разделе Пример реализации шаблона пользовательского элемента управления.

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

Реализация обработчика шаблонов

Обработчик шаблона — это объект, реализующий интерфейс IUIAutomationPatternHandler . Этот интерфейс имеет два метода: IUIAutomationPatternHandler::CreateClientWrapper и Dispatch. Метод CreateClientWrapper вызывается ядром модель автоматизации пользовательского интерфейса и получает указатель на интерфейс IUIAutomationPatternInstance. CreateClientWrapper отвечает путем создания экземпляра объекта-оболочки клиента и передачи указателя интерфейса IUIAutomationPatternInstance в конструктор клиентской оболочки.

Метод Dispatch используется ядром модель автоматизации пользовательского интерфейса для передачи запросов свойств и вызовов методов в интерфейс поставщика для пользовательского шаблона элемента управления. Параметры включают указатель на интерфейс поставщика, отсчитываемый от нуля индекс вызываемого метода получения свойства или метода, а также массив структур UIAutomationParameter , содержащих параметры, передаваемые поставщику. Обработчик шаблона отвечает, проверяя параметр индекса, чтобы определить, какой метод поставщика следует вызвать, а затем вызывает интерфейс поставщика, передавая параметры, содержащиеся в структурах UIAutomationParameter .

Экземпляр объекта обработчика шаблонов создается с помощью того же кода, который регистрирует пользовательский шаблон элемента управления, перед регистрацией шаблона элемента управления. Код должен передавать объекту обработчика шаблонов указатель интерфейса IUIAutomationPatternHandler на ядро модель автоматизации пользовательского интерфейса во время регистрации.

В следующем примере показано, как реализовать объект обработчика шаблонов для простого пользовательского шаблона элемента управления, поддерживающего одно свойство. Более сложный пример см. в разделе Пример реализации пользовательского шаблона элемента управления.

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

Регистрация пользовательского шаблона элемента управления

Перед использованием пользовательский шаблон элемента управления должен быть зарегистрирован как поставщиком, так и клиентом. Регистрация предоставляет модель автоматизации пользовательского интерфейса ядру подробные сведения о шаблоне элемента управления и предоставляет поставщику или клиенту идентификатор шаблона элемента управления и идентификаторы свойств и событий, поддерживаемых шаблоном элемента управления. На стороне поставщика пользовательский шаблон элемента управления должен быть зарегистрирован до того, как связанный элемент управления обработает сообщение WM_GETOBJECT или в то же время.

При регистрации пользовательского шаблона элемента управления поставщик или клиент предоставляет следующие сведения:

  • GUID пользовательского шаблона элемента управления.
  • Нелокализируемая строка, содержащая имя шаблона пользовательского элемента управления.
  • GUID интерфейса поставщика, который поддерживает пользовательский шаблон элемента управления.
  • GUID клиентского интерфейса, который поддерживает пользовательский шаблон элемента управления.
  • Массив структур UIAutomationPropertyInfo , описывающих свойства, поддерживаемые пользовательским шаблоном элемента управления. Для каждого свойства необходимо указать GUID, имя свойства и тип данных.
  • Массив структур UIAutomationMethodInfo , описывающих методы, поддерживаемые пользовательским шаблоном элемента управления. Для каждого метода структура включает следующие сведения: имя метода, количество параметров, список типов данных параметров и список имен параметров.
  • Массив структур UIAutomationEventInfo , описывающих события, вызванные пользовательским шаблоном элемента управления. Для каждого события необходимо указать GUID и имя события.
  • Адрес интерфейса IUIAutomationPatternHandler объекта обработчика шаблонов, который делает пользовательский шаблон элемента управления доступным для клиентов.

Чтобы зарегистрировать пользовательский шаблон элемента управления, код поставщика или клиента должен выполнить следующие действия.

  1. Заполните структуру UIAutomationPatternInfo приведенными выше сведениями.
  2. Используйте функцию CoCreateInstance для создания экземпляра объекта CUIAutomationRegistrar и получения указателя на интерфейс IUIAutomationRegistrar объекта.
  3. Вызовите метод IUIAutomationRegistrar::RegisterPattern , передав адрес структуры UIAutomationPatternInfo .

Метод RegisterPattern возвращает идентификатор шаблона элемента управления, а также список идентификаторов свойств и идентификаторов событий. Приложение может передать эти идентификаторы в любой модель автоматизации пользовательского интерфейса метод, который принимает такой идентификатор в качестве параметра. Например, можно передать зарегистрированный идентификатор шаблона в метод IUIAutomationElement::GetCurrentPattern , чтобы получить указатель на интерфейс поставщика для шаблона элемента управления.

Не существует метода, отменяющего регистрацию пользовательского шаблона элемента управления. Вместо этого он неявно отменяется при освобождении последнего объекта модель автоматизации пользовательского интерфейса.

Пример регистрации пользовательского шаблона элемента управления см. в следующем разделе.

Пример реализации пользовательского шаблона элемента управления

В этом разделе содержится пример кода, демонстрирующий реализацию клиентских объектов-оболочек и обработчиков шаблонов для пользовательского шаблона элемента управления. В примере реализуется пользовательский шаблон элемента управления, основанный на шаблоне элемента управления "Значение ".

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

Основные понятия

Проектирование пользовательских свойств, событий и шаблонов элементов управления

Общие сведения о свойствах автоматизированного пользовательского интерфейса

Обзор событий автоматизации пользовательского интерфейса

Общие сведения о шаблонах элементов управления модели автоматизации пользовательского интерфейса