#ifndef COMMON_H #define COMMON_H #include #include #include #ifdef UNICODE #define WA "W" #else #define WA "A" #endif template std::basic_string BstrFromSz(const char* sz, int iCp = CP_UTF8); int EBMessageBox(const TCHAR* tszText, const TCHAR* tszCaption, unsigned uType); /* Conditionally choose between two values. */ template constexpr std::enable_if_t choose(X x, Y) { return x; } template constexpr std::enable_if_t choose(X, Y y) { return y; } /* Conditionally choose between ANSI and wide string literal. */ #define AWTEXT(t, s) choose>(L"" s, s) /* Conditionally choose between ANSI and wide Windows API function. */ #define AWFUN(t, f) choose>(f##W, f##A) struct Win32Error : public std::exception { Win32Error(); Win32Error(DWORD dwErr); ~Win32Error(); template const T* what() const noexcept; DWORD dwErr; private: char* m_szMsg = NULL; wchar_t* m_wszMsg = NULL; }; template const T* Win32Error::what() const noexcept { TCHAR* tszMsg = choose>(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); ~Library(); template T* GetProcAddress(const char* szProc); private: HMODULE m_hModule; }; template T* Library::GetProcAddress(const char* const szProc) { return (T*)(void*)::GetProcAddress(m_hModule, szProc); } /* Create and return an object of type C. If construction fails, * return nothing. The returned value must be checked before being * used, as dereferencing is undefined if the value is empty. */ template std::optional maybe_make(U... xs) { try { return T(xs...); } catch (...) { return {}; } } /* Variable template for caching values from GetSystemMetrics. */ template const auto Metric = GetSystemMetrics(I); /* Check result of Windows API call, throwing error on NULL. */ template inline T require(const T x) { if (!x) throw Win32Error(); return x; } /* Check result of Windows API call, showing a warning on NULL. */ template inline T prefer(const T x) { if (!x) { EBMessageBox(Win32Error().what(), TEXT("System Error"), MB_ICONWARNING); return (T)NULL; } return x; } /* Return integer scaled for current DPI. */ inline int Dpi(const int i) { extern int g_iDPI; return MulDiv(i, g_iDPI, 96); } inline int Cmp(const int a, const int b) { if (a == b) return 0; if (a > b) return 1; return -1; } /* Get window rectangle relative to parent. */ inline BOOL GetRelativeRect(const HWND hWnd, RECT* const pRr) { if (!GetClientRect(hWnd, pRr)) return 0; return MapWindowPoints(hWnd, GetParent(hWnd), (POINT*)pRr, 2); } inline BOOL SetWindowRect(const HWND hWnd, const long left, const long top, const long right, const long bottom) { return MoveWindow(hWnd, left, top, right-left, bottom-top, TRUE); } inline BOOL SetWindowRect(const HWND hWnd, const RECT r) { return SetWindowRect(hWnd, r.left, r.top, r.right, r.bottom); } #endif