--- /dev/null
+# top-most EditorConfig file
+root = true
+
+# Don't use tabs for indentation.
+[*]
+indent_style = space
+trim_trailing_whitespace = true
+# (Please don't specify an indent_size here; that has too many unintended consequences.)
+
+[*.{c,h,cxx,cpp}]
+indent_size = 4
+
+# Powershell files
+[*.{ps1,psm1,psd1}]
+indent_size = 4
+
+# Xml based files
+[*.{proj,xml,nuspec}]
+indent_size = 2
HRESULT ButtonProvider::CreateInstance(HWND hwnd, IRawElementProviderSimple **ppProvider)
{
ButtonProvider *provider = new (std::nothrow) ButtonProvider(hwnd);
- wchar_t wsz[128]; swprintf_s(wsz, L"Created %p\n", provider); OutputDebugStringW(wsz);
+ wchar_t wsz[128]; swprintf_s(wsz, L"Created %p\n", provider); OutputDebugStringW(wsz);
return provider->QueryInterface(IID_IRawElementProviderSimple, reinterpret_cast<void**>(ppProvider));
}
DECLSPEC_NOTHROW STDMETHODIMP ButtonProvider::QueryInterface(REFIID riid, void **ppv)
{
HRESULT hr = S_OK;
- *ppv = nullptr;
+ *ppv = nullptr;
if (IsEqualIID(riid, IID_IUnknown)
|| IsEqualIID(riid, IID_IRawElementProviderSimple))
{
*ppv = static_cast<IInvokeProvider *>(this);
this->AddRef();
}
- else if (IsEqualIID(riid, IID_IToggleProvider))
- {
- *ppv = static_cast<IToggleProvider *>(this);
- this->AddRef();
- }
+ else if (IsEqualIID(riid, IID_IToggleProvider))
+ {
+ *ppv = static_cast<IToggleProvider *>(this);
+ this->AddRef();
+ }
else
hr = E_NOINTERFACE;
return hr;
DECLSPEC_NOTHROW STDMETHODIMP_(ULONG) ButtonProvider::AddRef()
{
- ULONG result = InterlockedIncrement(&_refcount);
- //wchar_t wsz[128]; swprintf_s(wsz, L"AddRef %lu\n", result); OutputDebugStringW(wsz);
- return result;
+ ULONG result = InterlockedIncrement(&_refcount);
+ //wchar_t wsz[128]; swprintf_s(wsz, L"AddRef %lu\n", result); OutputDebugStringW(wsz);
+ return result;
}
DECLSPEC_NOTHROW STDMETHODIMP_(ULONG) ButtonProvider::Release()
{
unsigned long result = InterlockedDecrement(&_refcount);
- //wchar_t wsz[128]; swprintf_s(wsz, L"Release %lu\n", result); OutputDebugStringW(wsz);
- if (result == 0)
+ //wchar_t wsz[128]; swprintf_s(wsz, L"Release %lu\n", result); OutputDebugStringW(wsz);
+ if (result == 0)
{
- wchar_t wsz[128]; swprintf_s(wsz, L"Destroy %p\n", this); OutputDebugStringW(wsz);
- delete this;
+ wchar_t wsz[128]; swprintf_s(wsz, L"Destroy %p\n", this); OutputDebugStringW(wsz);
+ delete this;
}
return result;
}
HRESULT hr = E_POINTER;
if (pVal)
{
- if (!IsWindow(_hwnd))
- hr = UIA_E_ELEMENTNOTENABLED;
- else
- {
- *pVal = ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading;
- hr = S_OK;
- }
+ if (!IsWindow(_hwnd))
+ hr = UIA_E_ELEMENTNOTENABLED;
+ else
+ {
+ *pVal = ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading;
+ hr = S_OK;
+ }
}
- return hr;
+ return hr;
}
DECLSPEC_NOTHROW STDMETHODIMP ButtonProvider::GetPatternProvider(PATTERNID patternId, IUnknown **ppVal)
{
hr = QueryInterface(IID_IUnknown, reinterpret_cast<void **>(ppVal));
}
- else if (patternId == UIA_TogglePatternId)
- {
- hr = QueryInterface(IID_IUnknown, reinterpret_cast<void **>(ppVal));
- }
+ else if (patternId == UIA_TogglePatternId)
+ {
+ hr = QueryInterface(IID_IUnknown, reinterpret_cast<void **>(ppVal));
+ }
}
return hr;
}
pVal->vt = VT_I4;
pVal->lVal = UIA_ButtonControlTypeId;
}
- else if (propertyId == UIA_IsControlElementPropertyId)
- {
- pVal->vt = VT_BOOL;
- pVal->boolVal = VARIANT_TRUE;
- }
- else if (propertyId == UIA_HasKeyboardFocusPropertyId)
- {
- pVal->vt = VT_BOOL;
- pVal->boolVal = VARIANT_FALSE;
- }
- else if (propertyId == UIA_ClassNamePropertyId)
- {
- wchar_t name[32] = { 0 };
- GetClassNameW(_hwnd, name, 32);
+ else if (propertyId == UIA_IsControlElementPropertyId)
+ {
+ pVal->vt = VT_BOOL;
+ pVal->boolVal = VARIANT_TRUE;
+ }
+ else if (propertyId == UIA_HasKeyboardFocusPropertyId)
+ {
+ pVal->vt = VT_BOOL;
+ pVal->boolVal = VARIANT_FALSE;
+ }
+ else if (propertyId == UIA_ClassNamePropertyId)
+ {
+ wchar_t name[32] = { 0 };
+ GetClassNameW(_hwnd, name, 32);
pVal->vt = VT_BSTR;
pVal->bstrVal = SysAllocString(name);
}
DECLSPEC_NOTHROW STDMETHODIMP ButtonProvider::Invoke()
{
- HRESULT hr = static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE);
- if (IsWindow(_hwnd))
- {
- PostMessage(_hwnd, BM_CLICK, 0L, 0L);
- hr = S_OK;
- }
- return hr;
+ HRESULT hr = static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE);
+ if (IsWindow(_hwnd))
+ {
+ PostMessage(_hwnd, BM_CLICK, 0L, 0L);
+ hr = S_OK;
+ }
+ return hr;
}
DECLSPEC_NOTHROW STDMETHODIMP ButtonProvider::Toggle()
{
- HRESULT hr = static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE);
- if (IsWindow(_hwnd))
- {
- PostMessage(_hwnd, BM_CLICK, 0, 0);
- hr = S_OK;
- }
- return hr;
+ HRESULT hr = static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE);
+ if (IsWindow(_hwnd))
+ {
+ PostMessage(_hwnd, BM_CLICK, 0, 0);
+ hr = S_OK;
+ }
+ return hr;
}
DECLSPEC_NOTHROW STDMETHODIMP ButtonProvider::get_ToggleState(ToggleState *pVal)
{
- HRESULT hr = E_POINTER;
- if (pVal)
- {
- if (!IsWindow(_hwnd))
- hr = static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE);
- else
- {
- auto state = SendMessage(_hwnd, BM_GETCHECK, WPARAM(0), LPARAM(0));
- *pVal = (state == BST_CHECKED) ? ToggleState_On : ToggleState_Off;
- hr = S_OK;
- }
- }
- return hr;
-}
\ No newline at end of file
+ HRESULT hr = E_POINTER;
+ if (pVal)
+ {
+ if (!IsWindow(_hwnd))
+ hr = static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE);
+ else
+ {
+ auto state = SendMessage(_hwnd, BM_GETCHECK, WPARAM(0), LPARAM(0));
+ *pVal = (state == BST_CHECKED) ? ToggleState_On : ToggleState_Off;
+ hr = S_OK;
+ }
+ }
+ return hr;
+}
{
public:
static HRESULT CreateInstance(HWND hwnd, IRawElementProviderSimple **ppProvider);
-
+
STDMETHOD(QueryInterface)(REFIID riid, void **ppv);
STDMETHOD_(ULONG, AddRef)();
STDMETHOD_(ULONG, Release)();
STDMETHOD(Invoke)();
- STDMETHOD(Toggle)();
- STDMETHOD(get_ToggleState)(ToggleState *pVal);
+ STDMETHOD(Toggle)();
+ STDMETHOD(get_ToggleState)(ToggleState *pVal);
private:
ButtonProvider() : _refcount(0), _hwnd(HWND_DESKTOP) {}
ButtonProvider(HWND hwnd) : _refcount(0), _hwnd(hwnd) {}
- virtual ~ButtonProvider() {}
- unsigned long _refcount;
+ virtual ~ButtonProvider() {}
+ unsigned long _refcount;
HWND _hwnd;
};
-# CMAKE_BUILD_TYPE has no effect on the Visual Studio generator.
-# cmake -G"Visual Studio 15 2017 Win64" ..
-# cmake --build . --config Release
-#
-# For LLVM / CLang build:
-# cmake -G"Visual Studio 15 2017 Win64" -T LLVM ..
-# cmake --build . --config Release
+cmake_minimum_required(VERSION 3.26)
-cmake_minimum_required(VERSION 3.0)
+project(UIADemo VERSION 1.0 LANGUAGES CXX RC)
-ENABLE_LANGUAGE(RC)
-
-project(UIADemo VERSION 1.0)
+set(TARGET ${PROJECT_NAME})
set(SOURCE main.cpp main.rc resource.h
PolyButton.cpp PolyButton.h
ButtonProvider.cpp ButtonProvider.h)
-set(CMAKE_CXX_STANDARD 14)
-add_definitions(-DUNICODE -D_UNICODE -DSTRICT -D_WIN32_LEAN_AND_MEAN -D_WIN32_WINNT=_WIN32_WINNT_WIN8)
-add_executable(${PROJECT_NAME} WIN32 ${SOURCE})
+
+add_executable(${TARGET} WIN32 ${SOURCE})
+target_compile_features(${TARGET} PRIVATE cxx_std_17)
+target_compile_definitions(${TARGET} PRIVATE
+ -DUNICODE -D_UNICODE -DSTRICT -D_WIN32_LEAN_AND_MEAN
+ -D_WIN32_WINNT=_WIN32_WINNT_WIN8)
case WM_DESTROY:
{
PolyButton *ctrl = reinterpret_cast<PolyButton *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
- UiaReturnRawElementProvider(hwnd, 0, 0, nullptr);
- UiaDisconnectProvider(ctrl->GetUIAutomationProvider(hwnd));
+ UiaReturnRawElementProvider(hwnd, 0, 0, nullptr);
+ UiaDisconnectProvider(ctrl->GetUIAutomationProvider(hwnd));
delete ctrl;
}
break;
ctrl->InvokeButton();
}
break;
- case BM_CLICK:
- {
- PolyButton *ctrl = reinterpret_cast<PolyButton *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
- ctrl->InvokeButton();
- }
- break;
- case BM_GETCHECK:
- {
- PolyButton *ctrl = reinterpret_cast<PolyButton *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
- return ctrl->IsChecked() ? BST_CHECKED : BST_UNCHECKED;
- }
+ case BM_CLICK:
+ {
+ PolyButton *ctrl = reinterpret_cast<PolyButton *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
+ ctrl->InvokeButton();
+ }
+ break;
+ case BM_GETCHECK:
+ {
+ PolyButton *ctrl = reinterpret_cast<PolyButton *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
+ return ctrl->IsChecked() ? BST_CHECKED : BST_UNCHECKED;
+ }
}
return DefWindowProc(hwnd, messageId, wparam, lparam);
}
{
if ((_state & PolyButtonState::Focussed) != PolyButtonState::Focussed)
SetFocus(_hwnd);
- _state ^= PolyButtonState::Checked;
+ _state ^= PolyButtonState::Checked;
if (UiaClientsAreListening())
{
// Raise an event.
- IRawElementProviderSimple *p = nullptr;
- if (_provider)
- {
- _provider->QueryInterface(&p);
- UiaRaiseAutomationEvent(p, UIA_Invoke_InvokedEventId);
- p->Release();
- }
+ IRawElementProviderSimple *p = nullptr;
+ if (_provider)
+ {
+ _provider->QueryInterface(&p);
+ UiaRaiseAutomationEvent(p, UIA_Invoke_InvokedEventId);
+ p->Release();
+ }
}
InvalidateRect(_hwnd, nullptr, TRUE);
}
#include <uiautomation.h>
enum class PolyButtonState {
- Normal = 0,
- Active = (1 << 0),
- Pressed = (1 << 1),
- Focussed = (1 << 2),
- Checked = (1 << 3),
- Disabled = (1 << 4)
+ Normal = 0,
+ Active = (1 << 0),
+ Pressed = (1 << 1),
+ Focussed = (1 << 2),
+ Checked = (1 << 3),
+ Disabled = (1 << 4)
};
DEFINE_ENUM_FLAG_OPERATORS(PolyButtonState);
IRawElementProviderSimple *GetUIAutomationProvider(HWND hwnd);
void InvokeButton();
static void RegisterControl(HINSTANCE instance);
- bool IsChecked() const { return ((_state & PolyButtonState::Checked) == PolyButtonState::Checked); }
+ bool IsChecked() const { return ((_state & PolyButtonState::Checked) == PolyButtonState::Checked); }
void OnPaint();
void OnSetFocus();
void OnKillFocus();
static INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM /*lParam*/)
{
- switch (message)
- {
- case WM_COMMAND:
- if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
- {
- EndDialog(hDlg, LOWORD(wParam));
- return TRUE;
- }
- break;
- }
- return FALSE;
+ switch (message)
+ {
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
+ {
+ EndDialog(hDlg, LOWORD(wParam));
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
}
int PASCAL
WinMain(HINSTANCE hinst, HINSTANCE, LPSTR, int)
{
- Gdiplus::GdiplusStartupInput gdiplusStartupInput;
- ULONG_PTR gdiplusToken(0);
- Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
- CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
- PolyButton::RegisterControl(hinst);
- DialogBox(hinst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);
- CoUninitialize();
- Gdiplus::GdiplusShutdown(gdiplusToken);
- return 0;
+ Gdiplus::GdiplusStartupInput gdiplusStartupInput;
+ ULONG_PTR gdiplusToken(0);
+ Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
+ CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
+ PolyButton::RegisterControl(hinst);
+ DialogBox(hinst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);
+ CoUninitialize();
+ Gdiplus::GdiplusShutdown(gdiplusToken);
+ return 0;
}
BEGIN
BLOCK "040904b0"
BEGIN
- VALUE "Comments", "Direct2D sample application"
+ VALUE "Comments", "Custom control UI automation example"
VALUE "CompanyName", "Renishaw plc."
- VALUE "FileDescription", "Direct2D sample application"
+ VALUE "FileDescription", "Custom control UI automation example"
VALUE "FileVersion", "1, 0, 0, 0"
- VALUE "InternalName", "D2DDemo"
+ VALUE "InternalName", "UIADemo"
VALUE "LegalCopyright", "Copyright (c) 2020 Renishaw plc."
- VALUE "OriginalFilename", "D2DDemo.exe"
+ VALUE "OriginalFilename", "UIADemo.exe"
VALUE "ProductVersion", "1, 0, 0, 0"
END
END
// TEXTINCLUDE
//
-1 TEXTINCLUDE
+1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
-2 TEXTINCLUDE
+2 TEXTINCLUDE
BEGIN
"#include <winres.h>\r\n"
"\0"
END
-3 TEXTINCLUDE
+3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"