From: Pat Thoyts Date: Sun, 20 Sep 2020 19:34:17 +0000 (+0100) Subject: Initial version, working demo. X-Git-Url: http://privyetmir.co.uk/gitweb.cgi?a=commitdiff_plain;h=a45042b2f14b6b8b68244dbb3d1de3346a3af389;p=accessibility%2Fuiademo.git Initial version, working demo. --- a45042b2f14b6b8b68244dbb3d1de3346a3af389 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fcc9ffb --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vscode/ +build/ +*.aps \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..fddb5e4 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,20 @@ +{ + "files.associations": { + "memory": "cpp" + }, + "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", + "C_Cpp.default.defines": [ + "UNICODE", "_UNICODE", "_WIN32_LEAN_AND_MEAN", "STRICT" + ], + "cmake.configureOnOpen": true, + "C_Cpp.default.cppStandard": "c++14", + "C_Cpp.default.cStandard": "c11", + "c-cpp-flylint.defines": [ + "UNICODE", "_UNICODE", "_WIN32_LEAN_AND_MEAN", "STRICT" + ], + "c-cpp-flylint.standard": [ + "c11", + "c++14" + ], + "c-cpp-flylint.cppcheck.suppressions": [] +} \ No newline at end of file diff --git a/ButtonProvider.cpp b/ButtonProvider.cpp new file mode 100644 index 0000000..615f0a2 --- /dev/null +++ b/ButtonProvider.cpp @@ -0,0 +1,181 @@ +//#include +#include "ButtonProvider.h" +#include +#include +#include +#include + +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); + return provider->QueryInterface(IID_IRawElementProviderSimple, reinterpret_cast(ppProvider)); +} + +DECLSPEC_NOTHROW STDMETHODIMP ButtonProvider::QueryInterface(REFIID riid, void **ppv) +{ + HRESULT hr = S_OK; + *ppv = nullptr; + if (IsEqualIID(riid, IID_IUnknown) + || IsEqualIID(riid, IID_IRawElementProviderSimple)) + { + *ppv = static_cast(this); + this->AddRef(); + } + else if (IsEqualIID(riid, IID_IInvokeProvider)) + { + *ppv = static_cast(this); + this->AddRef(); + } + else if (IsEqualIID(riid, IID_IToggleProvider)) + { + *ppv = static_cast(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; +} + +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"Destroy %p\n", this); OutputDebugStringW(wsz); + delete this; + } + return result; +} + +DECLSPEC_NOTHROW STDMETHODIMP ButtonProvider::get_ProviderOptions(ProviderOptions *pVal) +{ + HRESULT hr = E_POINTER; + if (pVal) + { + if (!IsWindow(_hwnd)) + hr = UIA_E_ELEMENTNOTENABLED; + else + { + *pVal = ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading; + hr = S_OK; + } + } + return hr; +} + +DECLSPEC_NOTHROW STDMETHODIMP ButtonProvider::GetPatternProvider(PATTERNID patternId, IUnknown **ppVal) +{ + HRESULT hr = E_POINTER; + if (ppVal) + { + hr = S_OK; + *ppVal = nullptr; + if (patternId == UIA_InvokePatternId) + { + hr = QueryInterface(IID_IUnknown, reinterpret_cast(ppVal)); + } + else if (patternId == UIA_TogglePatternId) + { + hr = QueryInterface(IID_IUnknown, reinterpret_cast(ppVal)); + } + } + return hr; +} + +DECLSPEC_NOTHROW STDMETHODIMP ButtonProvider::GetPropertyValue(PROPERTYID propertyId, VARIANT *pVal) +{ + if (propertyId == UIA_ControlTypePropertyId) + { + 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); + pVal->vt = VT_BSTR; + pVal->bstrVal = SysAllocString(name); + } + else if (propertyId == UIA_NamePropertyId) + { + int len = GetWindowTextLengthW(_hwnd) + 1; + wchar_t *name = new (std::nothrow) wchar_t[len](); + GetWindowTextW(_hwnd, name, len); + pVal->vt = VT_BSTR; + pVal->bstrVal = SysAllocString(name); + delete[] name; + } + else + { + pVal->vt = VT_EMPTY; + } + return S_OK; +} + +DECLSPEC_NOTHROW STDMETHODIMP ButtonProvider::get_HostRawElementProvider(IRawElementProviderSimple **ppVal) +{ + HRESULT hr = E_POINTER; + if (ppVal) + { + hr = UiaHostProviderFromHwnd(_hwnd, ppVal); + } + return hr; +} + +DECLSPEC_NOTHROW STDMETHODIMP ButtonProvider::Invoke() +{ + HRESULT hr = static_cast(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(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(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 diff --git a/ButtonProvider.h b/ButtonProvider.h new file mode 100644 index 0000000..ae1d551 --- /dev/null +++ b/ButtonProvider.h @@ -0,0 +1,30 @@ +#include +#include +#include + +class ButtonProvider : public IRawElementProviderSimple, public IInvokeProvider, public IToggleProvider +{ +public: + static HRESULT CreateInstance(HWND hwnd, IRawElementProviderSimple **ppProvider); + + STDMETHOD(QueryInterface)(REFIID riid, void **ppv); + STDMETHOD_(ULONG, AddRef)(); + STDMETHOD_(ULONG, Release)(); + + STDMETHOD(get_ProviderOptions)(ProviderOptions *pVal); + STDMETHOD(GetPatternProvider)(PATTERNID patternId, IUnknown **ppVal); + STDMETHOD(GetPropertyValue)(PROPERTYID propertyId, VARIANT *pVal); + STDMETHOD(get_HostRawElementProvider)(IRawElementProviderSimple **ppVal); + + STDMETHOD(Invoke)(); + + 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; + HWND _hwnd; +}; diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a2db266 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,19 @@ +# 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.0) + +ENABLE_LANGUAGE(RC) + +project(UIADemo VERSION 1.0) +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}) diff --git a/PolyButton.cpp b/PolyButton.cpp new file mode 100644 index 0000000..65d6932 --- /dev/null +++ b/PolyButton.cpp @@ -0,0 +1,184 @@ +#include "PolyButton.h" +#include "ButtonProvider.h" +#include +#include +#include + +static LRESULT CALLBACK WndProc(HWND hwnd, UINT messageId, WPARAM wparam, LPARAM lparam); + +PolyButton::PolyButton(HWND hwnd) : _hwnd(hwnd), _sides(6), _state(PolyButtonState::Normal), _provider(nullptr) +{ +} + +PolyButton::~PolyButton() +{ + if (_provider) + { + _provider->Release(); + _provider = nullptr; + } +} + +void PolyButton::RegisterControl(HINSTANCE hInstance) +{ + WNDCLASS wc = {}; + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WndProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.lpszClassName = L"POLYBUTTON"; + RegisterClass(&wc); +} + +IRawElementProviderSimple *PolyButton::GetUIAutomationProvider(HWND hwnd) +{ + if (!_provider) + { + HRESULT hr = ButtonProvider::CreateInstance(hwnd, &_provider); + } + return _provider; +} + +LRESULT CALLBACK WndProc(HWND hwnd, UINT messageId, WPARAM wparam, LPARAM lparam) +{ + switch (messageId) + { + case WM_CREATE: + { + PolyButton *ctrl = new (std::nothrow) PolyButton(hwnd); + if (!ctrl) + { + PostQuitMessage(-1); + } + SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(ctrl)); + } + break; + case WM_DESTROY: + { + PolyButton *ctrl = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + UiaReturnRawElementProvider(hwnd, 0, 0, nullptr); + UiaDisconnectProvider(ctrl->GetUIAutomationProvider(hwnd)); + delete ctrl; + } + break; + case WM_GETOBJECT: + if (static_cast(lparam) == static_cast(UiaRootObjectId)) + { + PolyButton *ctrl = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + IRawElementProviderSimple *provider = ctrl->GetUIAutomationProvider(hwnd); + return UiaReturnRawElementProvider(hwnd, wparam, lparam, provider); + } + break; + case WM_PAINT: + { + PolyButton *ctrl = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + ctrl->OnPaint(); + return 1L; + } + break; + case WM_SETFOCUS: + { + PolyButton *ctrl = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + ctrl->OnSetFocus(); + } + break; + case WM_KILLFOCUS: + { + PolyButton *ctrl = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + ctrl->OnKillFocus(); + } + break; + case WM_LBUTTONDOWN: + { + PolyButton *ctrl = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + ctrl->InvokeButton(); + } + break; + case BM_CLICK: + { + PolyButton *ctrl = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + ctrl->InvokeButton(); + } + break; + case BM_GETCHECK: + { + PolyButton *ctrl = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + return ctrl->IsChecked() ? BST_CHECKED : BST_UNCHECKED; + } + } + return DefWindowProc(hwnd, messageId, wparam, lparam); +} + +void PolyButton::OnSetFocus() +{ + _state |= PolyButtonState::Focussed; + RECT rc = {0}; + GetClientRect(_hwnd, &rc); + InvalidateRect(_hwnd, &rc, TRUE); +} + +void PolyButton::OnKillFocus() +{ + _state &= ~PolyButtonState::Focussed; + InvalidateRect(_hwnd, nullptr, TRUE); +} + +inline Gdiplus::RectF RectItoF (const Gdiplus::Rect &rc) +{ + return Gdiplus::RectF(float(rc.X), float(rc.Y), float(rc.Width), float(rc.Height)); +} + +void PolyButton::OnPaint() +{ + PAINTSTRUCT ps = {0}; + RECT rc; + GetClientRect(_hwnd, &rc); + HDC hdc = BeginPaint(_hwnd, &ps); + { + Gdiplus::Graphics g(hdc); + Gdiplus::Rect clientRect(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); + Gdiplus::Pen pen(Gdiplus::Color::Black, 1.0F); + Gdiplus::SolidBrush redBrush(Gdiplus::Color::Red); + Gdiplus::SolidBrush greenBrush(Gdiplus::Color::Green); + Gdiplus::Brush *brush = IsChecked() ? &redBrush : &greenBrush; + g.FillRectangle(brush, clientRect); + g.DrawRectangle(&pen, clientRect); + + Gdiplus::SolidBrush textBrush(Gdiplus::Color::Black); + Gdiplus::Font font(L"Segoe UI", 10); + Gdiplus::RectF layoutRect(float(clientRect.X), float(clientRect.Y), float(clientRect.Width), float(clientRect.Height)); + Gdiplus::StringFormat format(Gdiplus::StringFormat::GenericDefault()); + 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; + } + if ((_state & PolyButtonState::Focussed) == PolyButtonState::Focussed) + DrawFocusRect(hdc, &rc); + EndPaint(_hwnd, &ps); +} + +void PolyButton::InvokeButton() +{ + if ((_state & PolyButtonState::Disabled) != PolyButtonState::Disabled) + { + if ((_state & PolyButtonState::Focussed) != PolyButtonState::Focussed) + SetFocus(_hwnd); + _state ^= PolyButtonState::Checked; + if (UiaClientsAreListening()) + { + // Raise an event. + IRawElementProviderSimple *p = nullptr; + if (_provider) + { + _provider->QueryInterface(&p); + UiaRaiseAutomationEvent(p, UIA_Invoke_InvokedEventId); + p->Release(); + } + } + InvalidateRect(_hwnd, nullptr, TRUE); + } +} \ No newline at end of file diff --git a/PolyButton.h b/PolyButton.h new file mode 100644 index 0000000..b262484 --- /dev/null +++ b/PolyButton.h @@ -0,0 +1,36 @@ +// Provide a polygonal button control. +// Used to demo UIAutomation support for custom controls. + +#include +#include +#include + +enum class PolyButtonState { + Normal = 0, + Active = (1 << 0), + Pressed = (1 << 1), + Focussed = (1 << 2), + Checked = (1 << 3), + Disabled = (1 << 4) +}; +DEFINE_ENUM_FLAG_OPERATORS(PolyButtonState); + +class PolyButton +{ +public: + explicit PolyButton(HWND hwnd); + virtual ~PolyButton(); + IRawElementProviderSimple *GetUIAutomationProvider(HWND hwnd); + void InvokeButton(); + static void RegisterControl(HINSTANCE instance); + bool IsChecked() const { return ((_state & PolyButtonState::Checked) == PolyButtonState::Checked); } + void OnPaint(); + void OnSetFocus(); + void OnKillFocus(); +private: + PolyButton() {} + HWND _hwnd; + PolyButtonState _state; + int _sides; + IRawElementProviderSimple * _provider; +}; diff --git a/README.md b/README.md new file mode 100644 index 0000000..eede211 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Demonstration of UI Accessibility for Custom Control + +PolyButton is a custom toggle button with UIA support. \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..6f09f76 --- /dev/null +++ b/main.cpp @@ -0,0 +1,37 @@ +#include +#include +#include "resource.h" +#include "PolyButton.h" + +#pragma comment(lib, "gdiplus") +#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 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; +} + +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; +} diff --git a/main.rc b/main.rc new file mode 100644 index 0000000..595a68a --- /dev/null +++ b/main.rc @@ -0,0 +1,162 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "Direct2D sample application" + VALUE "CompanyName", "Renishaw plc." + VALUE "FileDescription", "Direct2D sample application" + VALUE "FileVersion", "1, 0, 0, 0" + VALUE "InternalName", "D2DDemo" + VALUE "LegalCopyright", "Copyright (c) 2020 Renishaw plc." + VALUE "OriginalFilename", "D2DDemo.exe" + VALUE "ProductVersion", "1, 0, 0, 0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (United Kingdom) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include \r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOGEX 0, 0, 309, 176 +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 +BEGIN + CONTROL "Check1",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,112,10 + 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 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 302 + TOPMARGIN, 7 + BOTTOMMARGIN, 169 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// AFX_DIALOG_LAYOUT +// + +IDD_DIALOG1 AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +#endif // English (United Kingdom) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/resource.h b/resource.h new file mode 100644 index 0000000..c312e64 --- /dev/null +++ b/resource.h @@ -0,0 +1,22 @@ +//{{NO_DEPENDENCIES}} +// 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 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#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_SYMED_VALUE 101 +#endif +#endif