From 42fe2ab8506e5cf640ff924a455220436292df11 Mon Sep 17 00:00:00 2001
From: Pat Thoyts <patthoyts@users.sourceforge.net>
Date: Wed, 5 Mar 2025 15:54:02 +0000
Subject: [PATCH] Add comboboxes and list control to the dialog.
---
ButtonProvider.cpp | 10 +++++-----
ButtonProvider.h | 2 +-
PolyButton.cpp | 14 +++++++-------
PolyButton.h | 4 ++--
main.cpp | 38 +++++++++++++++++++++++++++++++-------
main.rc | 32 +++++++++++++++++++++-----------
resource.h | 20 ++++++++++++--------
7 files changed, 79 insertions(+), 41 deletions(-)
diff --git a/ButtonProvider.cpp b/ButtonProvider.cpp
index 1e402e9..1213299 100644
--- a/ButtonProvider.cpp
+++ b/ButtonProvider.cpp
@@ -3,6 +3,7 @@
#include <UIAutomationClient.h>
#include <UIAutomationCoreApi.h>
#include <new>
+#include <string>
#include <stdio.h>
HRESULT ButtonProvider::CreateInstance(HWND hwnd, IRawElementProviderSimple **ppProvider)
@@ -118,11 +119,10 @@ DECLSPEC_NOTHROW STDMETHODIMP ButtonProvider::GetPropertyValue(PROPERTYID proper
else if (propertyId == UIA_NamePropertyId)
{
int len = GetWindowTextLengthW(_hwnd) + 1;
- wchar_t *name = new (std::nothrow) wchar_t[len]();
- GetWindowTextW(_hwnd, name, len);
+ std::wstring name(len - 1, L'\0');
+ GetWindowTextW(_hwnd, name.data(), len);
pVal->vt = VT_BSTR;
- pVal->bstrVal = SysAllocString(name);
- delete[] name;
+ pVal->bstrVal = SysAllocString(name.c_str());
}
else
{
@@ -172,7 +172,7 @@ DECLSPEC_NOTHROW STDMETHODIMP ButtonProvider::get_ToggleState(ToggleState *pVal)
hr = static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE);
else
{
- auto state = SendMessage(_hwnd, BM_GETCHECK, WPARAM(0), LPARAM(0));
+ int state = static_cast<int>(SendMessage(_hwnd, BM_GETCHECK, WPARAM(0), LPARAM(0)));
*pVal = (state == BST_CHECKED) ? ToggleState_On : ToggleState_Off;
hr = S_OK;
}
diff --git a/ButtonProvider.h b/ButtonProvider.h
index 080b025..b8549b3 100644
--- a/ButtonProvider.h
+++ b/ButtonProvider.h
@@ -22,7 +22,7 @@ public:
STDMETHOD(get_ToggleState)(ToggleState *pVal);
private:
- ButtonProvider() : _refcount(0), _hwnd(HWND_DESKTOP) {}
+ ButtonProvider() = delete;
ButtonProvider(HWND hwnd) : _refcount(0), _hwnd(hwnd) {}
virtual ~ButtonProvider() {}
unsigned long _refcount;
diff --git a/PolyButton.cpp b/PolyButton.cpp
index 45ae6f4..fd664b7 100644
--- a/PolyButton.cpp
+++ b/PolyButton.cpp
@@ -7,6 +7,7 @@
#include <new>
#include <string>
#include <vector>
+#include <memory>
static LRESULT CALLBACK WndProc(HWND hwnd, UINT messageId, WPARAM wparam, LPARAM lparam);
@@ -132,7 +133,7 @@ inline Gdiplus::RectF RectItoF (const Gdiplus::Rect &rc)
return Gdiplus::RectF(float(rc.X), float(rc.Y), float(rc.Width), float(rc.Height));
}
-std::vector<Gdiplus::Point> CalculatePoints(Gdiplus::Rect rc, int sidesCount)
+static std::vector<Gdiplus::Point> CalculatePoints(Gdiplus::Rect rc, int sidesCount)
{
std::vector<Gdiplus::Point> points;
Gdiplus::Point center(rc.Width / 2, rc.Height / 2);
@@ -150,7 +151,7 @@ std::vector<Gdiplus::Point> CalculatePoints(Gdiplus::Rect rc, int sidesCount)
return points;
}
-void PolyButton::OnPaint()
+void PolyButton::OnPaint() const
{
PAINTSTRUCT ps = {0};
RECT rc;
@@ -174,10 +175,9 @@ void PolyButton::OnPaint()
format.SetAlignment(Gdiplus::StringAlignmentCenter);
format.SetLineAlignment(Gdiplus::StringAlignmentCenter);
int len = GetWindowTextLength(_hwnd) + 1;
- wchar_t *label = new wchar_t[len]();
- GetWindowTextW(_hwnd, label, len);
- g.DrawString(label, len, &font, layoutRect, &format, &textBrush);
- delete [] label;
+ std::wstring label(len - 1, L'\0');
+ GetWindowTextW(_hwnd, label.data(), len);
+ g.DrawString(label.c_str(), len, &font, layoutRect, &format, &textBrush);
}
if ((_state & PolyButtonState::Focussed) == PolyButtonState::Focussed)
DrawFocusRect(hdc, &rc);
@@ -204,4 +204,4 @@ void PolyButton::InvokeButton()
}
InvalidateRect(_hwnd, nullptr, TRUE);
}
-}
\ No newline at end of file
+}
diff --git a/PolyButton.h b/PolyButton.h
index 19d7e9a..bf972fa 100644
--- a/PolyButton.h
+++ b/PolyButton.h
@@ -24,11 +24,11 @@ public:
void InvokeButton();
static void RegisterControl(HINSTANCE instance);
bool IsChecked() const { return ((_state & PolyButtonState::Checked) == PolyButtonState::Checked); }
- void OnPaint();
+ void OnPaint() const;
void OnSetFocus();
void OnKillFocus();
private:
- PolyButton() {}
+ PolyButton() = delete;
HWND _hwnd;
PolyButtonState _state;
int _sides;
diff --git a/main.cpp b/main.cpp
index ac9dd50..533408c 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,5 +1,6 @@
#include <Windows.h>
#include <gdiplus.h>
+#include <CommCtrl.h>
#include "resource.h"
#include "PolyButton.h"
@@ -7,10 +8,31 @@
#pragma comment(lib, "uiautomationcore")
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+static LPCTSTR comboItems[] = { TEXT("One"), TEXT("Two"), TEXT("Three"), TEXT("Four") };
+
static INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM /*lParam*/)
{
switch (message)
{
+ case WM_INITDIALOG:
+ {
+ HWND hwndCombo = GetDlgItem(hDlg, IDC_COMBO1);
+ HWND hwndComb2 = GetDlgItem(hDlg, IDC_COMBO2);
+ HWND hwndList = GetDlgItem(hDlg, IDC_LIST1);
+ HWND hwndCombx = GetDlgItem(hDlg, IDC_COMBOBOXEX1);
+ COMBOBOXEXITEM item = { 0 };
+ item.mask = CBEIF_TEXT;
+ item.iItem = -1;
+ for (size_t ndx = 0; ndx < sizeof(comboItems) / sizeof(comboItems[0]); ++ndx)
+ {
+ SendMessage(hwndCombo, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(comboItems[ndx]));
+ SendMessage(hwndComb2, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(comboItems[ndx]));
+ SendMessage(hwndList, LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(comboItems[ndx]));
+ item.pszText = const_cast<LPTSTR>(comboItems[ndx]);
+ SendMessage(hwndCombx, CBEM_INSERTITEM, 0, reinterpret_cast<LPARAM>(&item));
+ }
+ break;
+ }
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
@@ -22,16 +44,18 @@ static INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM /
return FALSE;
}
-int PASCAL
-WinMain(HINSTANCE hinst, HINSTANCE, LPSTR, int)
+int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
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::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
+ HRESULT hr = ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
+ if (SUCCEEDED(hr))
+ {
+ PolyButton::RegisterControl(hInstance);
+ DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), nullptr, DlgProc);
+ CoUninitialize();
+ }
Gdiplus::GdiplusShutdown(gdiplusToken);
return 0;
}
diff --git a/main.rc b/main.rc
index e12acb7..a6d2218 100644
--- a/main.rc
+++ b/main.rc
@@ -74,18 +74,18 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
// 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"
@@ -99,7 +99,7 @@ END
// Dialog
//
-IDD_DIALOG1 DIALOGEX 0, 0, 309, 176
+IDD_DIALOG1 DIALOGEX 0, 0, 275, 173
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "UIA Custom Control Demo"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
@@ -108,11 +108,21 @@ BEGIN
GROUPBOX "Static",IDC_STATIC,7,18,105,38
CONTROL "Option 1",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,15,28,91,10
CONTROL "Option 2",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,15,42,92,10
- LTEXT "Label",IDC_STATIC,7,62,18,8
- EDITTEXT IDC_EDIT1,33,59,100,14,ES_AUTOHSCROLL
- CONTROL "Hello",IDC_CUSTOM1,"POLYBUTTON",WS_TABSTOP,15,82,60,27
- DEFPUSHBUTTON "OK",IDOK,198,155,50,14
- PUSHBUTTON "Cancel",IDCANCEL,252,155,50,14
+ LTEXT "Things",IDC_STATIC,125,7,22,8
+ LISTBOX IDC_LIST1,151,7,117,40,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Edit",IDC_STATIC,7,62,31,8
+ EDITTEXT IDC_EDIT1,44,59,101,14,ES_AUTOHSCROLL
+ LTEXT "Combo",IDC_STATIC,7,81,31,8
+ COMBOBOX IDC_COMBO1,44,79,101,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "EditCombo",IDC_STATIC,153,81,35,8
+ COMBOBOX IDC_COMBO2,191,79,77,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+ LTEXT "ComboEx",IDC_STATIC,7,98,31,8
+ CONTROL "",IDC_COMBOBOXEX1,"ComboBoxEx32",CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP,44,97,101,38
+ CONTROL "Hello",IDC_CUSTOM1,"POLYBUTTON",WS_TABSTOP,21,119,46,40
+ LTEXT "Text",IDC_STATIC,73,116,16,8
+ EDITTEXT IDC_EDIT2,95,116,173,33,ES_MULTILINE | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL
+ DEFPUSHBUTTON "OK",IDOK,166,152,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,218,152,50,14
END
@@ -127,9 +137,9 @@ BEGIN
IDD_DIALOG1, DIALOG
BEGIN
LEFTMARGIN, 7
- RIGHTMARGIN, 302
+ RIGHTMARGIN, 268
TOPMARGIN, 7
- BOTTOMMARGIN, 169
+ BOTTOMMARGIN, 166
END
END
#endif // APSTUDIO_INVOKED
diff --git a/resource.h b/resource.h
index c312e64..0f1dfec 100644
--- a/resource.h
+++ b/resource.h
@@ -2,13 +2,17 @@
// Microsoft Visual C++ generated include file.
// Used by main.rc
//
-
-#define IDD_DIALOG1 101
-#define IDC_CHECK1 102
-#define IDC_RADIO1 103
-#define IDC_RADIO2 104
-#define IDC_EDIT1 105
-#define IDC_CUSTOM1 106
+#define IDD_DIALOG1 101
+#define IDC_CHECK1 102
+#define IDC_RADIO1 103
+#define IDC_RADIO2 104
+#define IDC_EDIT1 105
+#define IDC_CUSTOM1 106
+#define IDC_COMBO1 1005
+#define IDC_COMBOBOXEX1 1006
+#define IDC_COMBO2 1007
+#define IDC_LIST1 1008
+#define IDC_EDIT2 1009
// Next default values for new objects
//
@@ -16,7 +20,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1005
+#define _APS_NEXT_CONTROL_VALUE 1010
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
--
2.23.0