2025-11-28 00:35:46 +09:00

171 lines
4.5 KiB
C++

/*************************************************************************************************
* Description: Implementation of the Provider class, which implements IRawElementProviderSimple
* and IInvokeProvider for a simple custom control.
*
* Copyright (C) Microsoft Corporation. All rights reserved.
*
* This source code is intended only as a supplement to Microsoft
* Development Tools and/or on-line documentation. See these other
* materials for detailed information regarding Microsoft code samples.
*
* THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
* PARTICULAR PURPOSE.
*
*************************************************************************************************/
#define INITGUID
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <ole2.h>
#include <UIAutomationCore.h>
#include <UIAutomationCoreAPI.h>
#include "Provider.h"
// Various identifiers that have to be looked up.
struct UiaIdentifiers
{
PROPERTYID NameProperty;
PROPERTYID ControlTypeProperty;
PATTERNID InvokePattern;
CONTROLTYPEID ButtonControlType;
} UiaIds;
// Look up identifiers.
void Provider::InitIds()
{
static bool inited = false;
if (!inited)
{
inited = true;
UiaIds.NameProperty = UiaLookupId(AutomationIdentifierType_Property, &Name_Property_GUID);
UiaIds.ControlTypeProperty = UiaLookupId(AutomationIdentifierType_Property, &ControlType_Property_GUID);
UiaIds.InvokePattern = UiaLookupId(AutomationIdentifierType_Pattern, &Invoke_Pattern_GUID);
UiaIds.ButtonControlType = UiaLookupId(AutomationIdentifierType_ControlType, &Button_Control_GUID);
}
}
Provider::Provider(HWND hwnd): m_refCount(1), m_controlHWnd(hwnd)
{
InitIds();
}
Provider::~Provider()
{
// Nothing to do.
}
// IUnknown implementation.
IFACEMETHODIMP_(ULONG) Provider::AddRef()
{
return InterlockedIncrement(&m_refCount);
}
IFACEMETHODIMP_(ULONG) Provider::Release()
{
long val = InterlockedDecrement(&m_refCount);
if (val == 0)
{
delete this;
}
return val;
}
IFACEMETHODIMP Provider::QueryInterface(REFIID riid, void** ppInterface)
{
if (riid == __uuidof(IUnknown))
{
*ppInterface =static_cast<IRawElementProviderSimple*>(this);
}
else if (riid == __uuidof(IRawElementProviderSimple))
{
*ppInterface =static_cast<IRawElementProviderSimple*>(this);
}
else if (riid == __uuidof(IInvokeProvider))
{
*ppInterface =static_cast<IInvokeProvider*>(this);
}
else
{
*ppInterface = NULL;
return E_NOINTERFACE;
}
(static_cast<IUnknown*>(*ppInterface))->AddRef();
return S_OK;
}
// IRawElementProviderSimple implementation
// Get provider options.
IFACEMETHODIMP Provider::get_ProviderOptions( ProviderOptions* pRetVal )
{
*pRetVal = ProviderOptions_ServerSideProvider;
return S_OK;
}
// Get the object that supports IInvokePattern.
IFACEMETHODIMP Provider::GetPatternProvider(PATTERNID patternId, IUnknown** pRetVal)
{
if (patternId == UiaIds.InvokePattern)
{
AddRef();
*pRetVal = static_cast<IRawElementProviderSimple*>(this);
}
else
{
*pRetVal = NULL;
}
return S_OK;
}
// Gets custom properties.
IFACEMETHODIMP Provider::GetPropertyValue(PROPERTYID propertyId, VARIANT* pRetVal)
{
if (propertyId == UiaIds.ControlTypeProperty)
{
pRetVal->vt = VT_I4;
pRetVal->lVal = UiaIds.ButtonControlType;
}
// The Name property comes from the Caption property of the control window, if it has one.
// The Name is overridden here for the sake of illustration.
else if (propertyId == UiaIds.NameProperty)
{
pRetVal->vt = VT_BSTR;
pRetVal->bstrVal = SysAllocString(L"ColorButton");
}
else
{
pRetVal->vt = VT_EMPTY;
// UI Automation will attempt to get the property from the host window provider.
}
return S_OK;
}
// Gets the UI Automation provider for the host window. This provider supplies most properties.
IFACEMETHODIMP Provider::get_HostRawElementProvider(IRawElementProviderSimple** pRetVal)
{
return UiaHostProviderFromHwnd(m_controlHWnd, pRetVal);
}
// IInvokeProvider implementation.
IFACEMETHODIMP Provider::Invoke()
{
PostMessage(m_controlHWnd, WM_LBUTTONDOWN, NULL, NULL);
return S_OK;
}