aboutsummaryrefslogtreecommitdiff
path: root/c/win32.h
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2022-09-02 20:16:04 +0200
committerJohn Ankarström <john@ankarstrom.se>2022-09-02 20:16:18 +0200
commitbc4cef92d8efbf97a9215122abc2d7247c287f12 (patch)
treea5ca307281c4f143b5f172428c9fd2b629d6b426 /c/win32.h
parent5c1c2ce2bdbf9735ad8a4d162609a8c22a4f0954 (diff)
downloadEpisodeBrowser-bc4cef92d8efbf97a9215122abc2d7247c287f12.tar.gz
Improve Window object.
Diffstat (limited to 'c/win32.h')
-rw-r--r--c/win32.h147
1 files changed, 147 insertions, 0 deletions
diff --git a/c/win32.h b/c/win32.h
new file mode 100644
index 0000000..c4e57b7
--- /dev/null
+++ b/c/win32.h
@@ -0,0 +1,147 @@
+#ifndef WIN32_H
+#define WIN32_H
+
+#include <optional>
+#include <string_view>
+#include <windows.h>
+#include <commctrl.h>
+
+/* Convert narrow to wide string. */
+std::wstring WideFromNarrow(const std::string_view src, const int cp = CP_UTF8);
+
+/* Run given procedure at creation of next window. */
+void WithNextWindow(void (*proc)(HWND));
+
+/* Display message box centered in main window. */
+int EBMessageBox(std::wstring_view text, std::wstring_view data, UINT uType);
+
+/* Show message box for current exception. */
+void ShowException(
+ const wchar_t* fmt = L"An error occurred: %s",
+ const wchar_t* title = L"Error",
+ UINT uType = MB_ICONWARNING) noexcept;
+
+/* Retrieve mouse position relative to given window's client area. */
+int GetRelativeCursorPos(HWND hWnd, POINT* pt) noexcept;
+
+/* Cached values from GetSystemMetrics. */
+template <int I> auto Metric = GetSystemMetrics(I);
+
+struct WideException : public std::exception
+{
+ virtual const char* what() const noexcept = 0;
+ virtual const wchar_t* What() const noexcept = 0;
+};
+
+/* Exception for Windows API errors. */
+struct Win32Error : public WideException
+{
+ Win32Error(DWORD code = GetLastError(), HMODULE hModule = nullptr) noexcept;
+ ~Win32Error() noexcept;
+ const char* what() const noexcept override;
+ const wchar_t* What() const noexcept override;
+ DWORD code;
+private:
+ HMODULE hModule;
+ char* m_szMsg = nullptr;
+ wchar_t* m_wszMsg = nullptr;
+};
+
+/* Exception for extended Wininet errors. */
+struct InternetError : public WideException
+{
+ InternetError(DWORD codeSystem = GetLastError());
+ ~InternetError() noexcept;
+ const char* what() const noexcept override;
+ const wchar_t* What() const noexcept override;
+ DWORD code;
+private:
+ char* m_szMsg = nullptr;
+ wchar_t* m_wszMsg = nullptr;
+};
+
+/* Wrapper for loading and freeing dynamically linked libraries. */
+struct Library
+{
+ /* Non-throwing named constructor. */
+ static std::optional<Library> Maybe(const wchar_t* lib) noexcept;
+
+ Library(const wchar_t* lib);
+ ~Library() noexcept;
+
+ template <class T> T* GetProcAddress(const char* szProc) noexcept;
+private:
+ /* Non-throwing constructor used by Maybe. */
+ Library(HMODULE hModule) noexcept;
+ HMODULE m_hModule;
+};
+
+template <typename T>
+T* Library::GetProcAddress(const char* const szProc) noexcept
+{
+ return (T*)(void*)::GetProcAddress(m_hModule, szProc);
+}
+
+/* Check result of Windows API call, throwing error on null. */
+template <typename T>
+inline T Require(const T x)
+{
+ if (!x) throw Win32Error();
+ return x;
+}
+
+/* Check result of Windows API call, showing a warning on null. */
+template <typename T>
+inline T Prefer(const T x)
+{
+ if (!x) {
+ EBMessageBox(Win32Error().What(), L"System Error", MB_ICONWARNING);
+ return (T)0;
+ }
+ return x;
+}
+
+/* Return integer scaled for current DPI. */
+inline int Dpi(const int i)
+{
+ extern int g_dpi;
+ return MulDiv(i, g_dpi, 96);
+}
+
+/* Retrieve given window's rectangle relative to parent's client area. */
+inline BOOL GetRelativeRect(const HWND hWnd, RECT* const rr)
+{
+ if (!GetClientRect(hWnd, rr)) return 0;
+ return MapWindowPoints(hWnd, GetParent(hWnd), reinterpret_cast<POINT*>(rr), 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);
+}
+
+/* The following two functions call uxtheme.dll functions, if
+ * uxtheme.dll exists, and otherwise do nothing. */
+inline BOOL EBIsThemeActive()
+{
+ extern BOOL (__stdcall *IsThemeActive)();
+ return IsThemeActive? IsThemeActive(): 0;
+}
+
+inline HRESULT EBSetWindowTheme(const HWND hWnd, const wchar_t* const pszSubAppName,
+ const wchar_t* const pszSubIdList)
+{
+ extern HRESULT (__stdcall *SetWindowTheme)(HWND, const wchar_t*, const wchar_t*);
+ return SetWindowTheme? SetWindowTheme(hWnd, pszSubAppName, pszSubIdList): 0;
+}
+
+#endif