diff options
-rw-r--r-- | c/common.cpp | 32 | ||||
-rw-r--r-- | c/common.h | 44 | ||||
-rw-r--r-- | c/main.cpp | 31 |
3 files changed, 45 insertions, 62 deletions
diff --git a/c/common.cpp b/c/common.cpp index 155c099..c4624c0 100644 --- a/c/common.cpp +++ b/c/common.cpp @@ -4,8 +4,8 @@ /* Win32Error: Exception for Windows API errors. */ -Win32Error::Win32Error() : m_dwErr(GetLastError()) {} -Win32Error::Win32Error(const DWORD dwErr) : m_dwErr(dwErr) {} +Win32Error::Win32Error() : dwErr(GetLastError()) {} +Win32Error::Win32Error(const DWORD dwErr) : dwErr(dwErr) {} Win32Error::~Win32Error() { @@ -15,34 +15,6 @@ Win32Error::~Win32Error() HeapFree(GetProcessHeap(), 0, m_wszMsg); } -template <> -const char* Win32Error::what() const noexcept -{ - if (!m_szMsg) - FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - m_dwErr, - MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), - (char*)&m_szMsg, - 0, NULL); - return m_szMsg; -} - -template <> -const wchar_t* Win32Error::what() const noexcept -{ - if (!m_wszMsg) - FormatMessageW( - FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - m_dwErr, - MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), - (wchar_t*)&m_wszMsg, - 0, NULL); - return m_wszMsg; -} - /* Library: Wrapper for loading and freeing dynamically linked libraries. */ Library::Library(const TCHAR* const tszLibrary) @@ -14,19 +14,45 @@ template <typename T> std::basic_string<T> BstrFromSz(const char* sz, int iCp = CP_UTF8); int EBMessageBox(const TCHAR* tszText, const TCHAR* tszCaption, unsigned uType); +/* Conditionally choose between two values. */ +template <bool B, typename X, typename Y> +constexpr std::enable_if_t<B == true, X> choose(X x, Y) { return x; } +template <bool B, typename X, typename Y> +constexpr std::enable_if_t<B == false, Y> choose(X, Y y) { return y; } + +/* Conditionally choose between ANSI and wide string literal. */ +#define AWTEXT(t, s) choose<std::is_same_v<t, wchar_t>>(L"" s, s) + +/* Conditionally choose between ANSI and wide Windows API function. */ +#define AWFUN(t, f) choose<std::is_same_v<t, wchar_t>>(f##W, f##A) + struct Win32Error : public std::exception { Win32Error(); Win32Error(DWORD dwErr); ~Win32Error(); template <typename T = char> const T* what() const noexcept; - + DWORD dwErr; private: - DWORD m_dwErr; char* m_szMsg = NULL; wchar_t* m_wszMsg = NULL; }; +template <typename T> +const T* Win32Error::what() const noexcept +{ + TCHAR* tszMsg = choose<std::is_same_v<T, wchar_t>>(m_wszMsg, m_szMsg); + if (!tszMsg) + AWFUN(T, FormatMessage)( + FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dwErr, + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + (TCHAR*)&tszMsg, + 0, NULL); + return tszMsg; +} + struct Library { Library(const TCHAR* tszLibrary); @@ -79,20 +105,6 @@ inline T prefer(const T x) return x; } -/* Conditionally choose between two values. This template is necessary - * because the ternary conditional operator can choose only between - * values of the same type. */ -template <bool B, typename X, typename Y> -constexpr std::enable_if_t<B == true, X> choose(X x, Y) { return x; } -template <bool B, typename X, typename Y> -constexpr std::enable_if_t<B == false, Y> choose(X, Y y) { return y; } - -/* Conditionally choose between ANSI and wide string literal. */ -#define AWTEXT(t, s) choose<std::is_same_v<t, wchar_t>>(L"" s, s) - -/* Conditionally choose between ANSI and wide Windows API function. */ -#define AWFUN(t, f) choose<std::is_same_v<t, wchar_t>>(f##W, f##A) - /* Return integer scaled for current DPI. */ inline int Dpi(const int i) { @@ -167,22 +167,21 @@ static LRESULT CALLBACK CBTProc(const int nCode, const WPARAM wParam, const LPAR g_hWnd = (HWND)wParam; /* Look up constants. */ - if (auto opLib = maybe_make<Library>(TEXT("User32.dll"))) - if (auto GetDpiForWindow = opLib->GetProcAddress<UINT(HWND)>("GetDpiForWindow")) - g_iDPI = GetDpiForWindow(g_hWnd); - - if (auto opLib = maybe_make<Library>(TEXT("uxtheme.dll"))) - if (opLib->GetProcAddress<void>("SetWindowTheme")) - g_bThemes = 1; - - if (auto opLib = maybe_make<Library>(TEXT("User32.dll"))) { - if (opLib->GetProcAddress<void>("SystemParametersInfo" WA)) { - NONCLIENTMETRICS m; - m.cbSize = sizeof(NONCLIENTMETRICS); - require(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, - sizeof(NONCLIENTMETRICS), &m, 0)); - g_hfNormal = require(CreateFontIndirect(&m.lfMessageFont)); - } + if (auto opLib = maybe_make<Library>(TEXT("User32.dll")); + auto GetDpiForWindow = opLib->GetProcAddress<UINT(HWND)>("GetDpiForWindow")) + g_iDPI = GetDpiForWindow(g_hWnd); + + if (auto opLib = maybe_make<Library>(TEXT("uxtheme.dll")); + opLib->GetProcAddress<void>("SetWindowTheme")) + g_bThemes = 1; + + if (auto opLib = maybe_make<Library>(TEXT("User32.dll")); + opLib->GetProcAddress<void>("SystemParametersInfo" WA)) { + NONCLIENTMETRICS m; + m.cbSize = sizeof(NONCLIENTMETRICS); + require(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, + sizeof(NONCLIENTMETRICS), &m, 0)); + g_hfNormal = require(CreateFontIndirect(&m.lfMessageFont)); } else g_hfNormal = static_cast<HFONT>(require(GetStockObject(DEFAULT_GUI_FONT))); |