Mercurial > foo_out_sdl
comparison foosdk/sdk/pfc/win-objects.h @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 1 #pragma once | |
| 2 | |
| 3 #include "ref_counter.h" | |
| 4 | |
| 5 namespace pfc { | |
| 6 BOOL winFormatSystemErrorMessage(pfc::string_base & p_out,DWORD p_code); | |
| 7 | |
| 8 // Prefix filesystem paths with \\?\ and \\?\UNC where appropriate. | |
| 9 void winPrefixPath(pfc::string_base & out, const char * p_path); | |
| 10 // Reverse winPrefixPath | |
| 11 void winUnPrefixPath(pfc::string_base & out, const char * p_path); | |
| 12 | |
| 13 string8 winPrefixPath( const char * in ); | |
| 14 string8 winUnPrefixPath( const char * in ); | |
| 15 | |
| 16 class LastErrorRevertScope { | |
| 17 public: | |
| 18 LastErrorRevertScope() : m_val(GetLastError()) {} | |
| 19 ~LastErrorRevertScope() { SetLastError(m_val); } | |
| 20 | |
| 21 private: | |
| 22 const DWORD m_val; | |
| 23 }; | |
| 24 | |
| 25 string8 getWindowText(HWND wnd); | |
| 26 void setWindowText(HWND wnd, const char * txt); | |
| 27 string8 getWindowClassName( HWND wnd ); | |
| 28 HWND findOwningPopup(HWND wnd); | |
| 29 } | |
| 30 | |
| 31 pfc::string8 format_win32_error(DWORD code); | |
| 32 pfc::string8 format_hresult(HRESULT code); | |
| 33 pfc::string8 format_hresult(HRESULT code, const char * msgOverride); | |
| 34 | |
| 35 class exception_win32 : public std::exception { | |
| 36 public: | |
| 37 exception_win32(DWORD p_code) : std::exception(format_win32_error(p_code)), m_code(p_code) {} | |
| 38 DWORD get_code() const {return m_code;} | |
| 39 private: | |
| 40 DWORD m_code; | |
| 41 }; | |
| 42 | |
| 43 #ifdef PFC_WINDOWS_DESKTOP_APP | |
| 44 | |
| 45 void uAddWindowStyle(HWND p_wnd,LONG p_style); | |
| 46 void uRemoveWindowStyle(HWND p_wnd,LONG p_style); | |
| 47 void uAddWindowExStyle(HWND p_wnd,LONG p_style); | |
| 48 void uRemoveWindowExStyle(HWND p_wnd,LONG p_style); | |
| 49 unsigned MapDialogWidth(HWND p_dialog,unsigned p_value); | |
| 50 bool IsKeyPressed(unsigned vk); | |
| 51 | |
| 52 //! Returns current modifier keys pressed, using win32 MOD_* flags. | |
| 53 unsigned GetHotkeyModifierFlags(); | |
| 54 | |
| 55 class CClipboardOpenScope { | |
| 56 public: | |
| 57 CClipboardOpenScope() : m_open(false) {} | |
| 58 ~CClipboardOpenScope() {Close();} | |
| 59 bool Open(HWND p_owner); | |
| 60 void Close(); | |
| 61 private: | |
| 62 bool m_open; | |
| 63 | |
| 64 PFC_CLASS_NOT_COPYABLE_EX(CClipboardOpenScope) | |
| 65 }; | |
| 66 | |
| 67 class CGlobalLockScope { | |
| 68 public: | |
| 69 CGlobalLockScope(HGLOBAL p_handle); | |
| 70 ~CGlobalLockScope(); | |
| 71 void * GetPtr() const {return m_ptr;} | |
| 72 t_size GetSize() const {return GlobalSize(m_handle);} | |
| 73 private: | |
| 74 void * m_ptr; | |
| 75 HGLOBAL m_handle; | |
| 76 | |
| 77 PFC_CLASS_NOT_COPYABLE_EX(CGlobalLockScope) | |
| 78 }; | |
| 79 | |
| 80 template<typename TItem> class CGlobalLockScopeT { | |
| 81 public: | |
| 82 CGlobalLockScopeT(HGLOBAL handle) : m_scope(handle) {} | |
| 83 TItem * GetPtr() const {return reinterpret_cast<TItem*>(m_scope.GetPtr());} | |
| 84 t_size GetSize() const { | |
| 85 const t_size val = m_scope.GetSize(); | |
| 86 PFC_ASSERT( val % sizeof(TItem) == 0 ); | |
| 87 return val / sizeof(TItem); | |
| 88 } | |
| 89 private: | |
| 90 CGlobalLockScope m_scope; | |
| 91 }; | |
| 92 | |
| 93 //! Resigns active window status passing it to the parent window, if wnd or a child popup of is active. \n | |
| 94 //! Use this to mitigate Windows 10 1809 active window handling bugs - call prior to DestroyWindow() | |
| 95 void ResignActiveWindow(HWND wnd); | |
| 96 //! Is point inside a control? | |
| 97 bool IsPointInsideControl(const POINT& pt, HWND wnd); | |
| 98 //! Is <child> a control inside <parent> window? Also returns true if child==parent. | |
| 99 bool IsWindowChildOf(HWND child, HWND parent); | |
| 100 //! Is <child> window a child (popup or control) of <parent> window? Also returns true if child==parent. | |
| 101 bool IsPopupWindowChildOf(HWND child, HWND parent); | |
| 102 | |
| 103 class win32_menu { | |
| 104 public: | |
| 105 win32_menu(HMENU p_initval) : m_menu(p_initval) {} | |
| 106 win32_menu() : m_menu(NULL) {} | |
| 107 ~win32_menu() {release();} | |
| 108 void release(); | |
| 109 void set(HMENU p_menu) {release(); m_menu = p_menu;} | |
| 110 void create_popup(); | |
| 111 HMENU get() const {return m_menu;} | |
| 112 HMENU detach() {return pfc::replace_t(m_menu,(HMENU)NULL);} | |
| 113 | |
| 114 bool is_valid() const {return m_menu != NULL;} | |
| 115 private: | |
| 116 win32_menu(const win32_menu &) = delete; | |
| 117 void operator=(const win32_menu &) = delete; | |
| 118 | |
| 119 HMENU m_menu; | |
| 120 }; | |
| 121 | |
| 122 #endif | |
| 123 | |
| 124 class win32_event { | |
| 125 public: | |
| 126 win32_event() : m_handle(NULL) {} | |
| 127 ~win32_event() {release();} | |
| 128 | |
| 129 void create(bool p_manualreset,bool p_initialstate); | |
| 130 | |
| 131 void set(HANDLE p_handle) {release(); m_handle = p_handle;} | |
| 132 HANDLE get() const {return m_handle;} | |
| 133 HANDLE get_handle() const {return m_handle;} | |
| 134 HANDLE detach() {return pfc::replace_t(m_handle,(HANDLE)NULL);} | |
| 135 bool is_valid() const {return m_handle != NULL;} | |
| 136 | |
| 137 void release(); | |
| 138 | |
| 139 //! Returns true when signaled, false on timeout | |
| 140 bool wait_for(double p_timeout_seconds) {return g_wait_for(get(),p_timeout_seconds);} | |
| 141 void wait() { wait_for(-1); } | |
| 142 void wait_and_clear() { wait(); set_state(false); } | |
| 143 | |
| 144 static DWORD g_calculate_wait_time(double p_seconds); | |
| 145 | |
| 146 //! Returns true when signaled, false on timeout | |
| 147 static bool g_wait_for(HANDLE p_event,double p_timeout_seconds); | |
| 148 | |
| 149 void set_state(bool p_state); | |
| 150 bool is_set() { return wait_for(0); } | |
| 151 | |
| 152 // Two-wait event functions, return 0 on timeout, 1 on evt1 set, 2 on evt2 set | |
| 153 static int g_twoEventWait( win32_event & ev1, win32_event & ev2, double timeout ); | |
| 154 static int g_twoEventWait( HANDLE ev1, HANDLE ev2, double timeout ); | |
| 155 | |
| 156 // Multi-wait. Returns SIZE_MAX on timeout, 0 based event index if either event becomes set. | |
| 157 static size_t g_multiWait(const HANDLE* events, size_t count, double timeout); | |
| 158 static size_t g_multiWait( std::initializer_list<HANDLE> const & arg, double timeout ); | |
| 159 private: | |
| 160 win32_event(const win32_event&) = delete; | |
| 161 void operator=(const win32_event &) = delete; | |
| 162 | |
| 163 HANDLE m_handle; | |
| 164 }; | |
| 165 | |
| 166 namespace pfc { | |
| 167 typedef HANDLE eventHandle_t; | |
| 168 | |
| 169 static constexpr eventHandle_t eventInvalid = NULL; | |
| 170 | |
| 171 class event : public win32_event { | |
| 172 public: | |
| 173 event(bool initial = false) { create(true, initial); } | |
| 174 | |
| 175 HANDLE get_handle() const { return win32_event::get(); } | |
| 176 }; | |
| 177 } | |
| 178 | |
| 179 void uSleepSeconds(double p_time,bool p_alertable); | |
| 180 | |
| 181 #ifdef PFC_WINDOWS_DESKTOP_APP | |
| 182 | |
| 183 class win32_icon { | |
| 184 public: | |
| 185 win32_icon(HICON p_initval) : m_icon(p_initval) {} | |
| 186 win32_icon() : m_icon(NULL) {} | |
| 187 ~win32_icon() {release();} | |
| 188 | |
| 189 void release(); | |
| 190 | |
| 191 void set(HICON p_icon) {release(); m_icon = p_icon;} | |
| 192 HICON get() const {return m_icon;} | |
| 193 HICON detach() {return pfc::replace_t(m_icon,(HICON)NULL);} | |
| 194 | |
| 195 bool is_valid() const {return m_icon != NULL;} | |
| 196 | |
| 197 private: | |
| 198 win32_icon(const win32_icon&) = delete; | |
| 199 const win32_icon & operator=(const win32_icon &) = delete; | |
| 200 | |
| 201 HICON m_icon; | |
| 202 }; | |
| 203 | |
| 204 class win32_accelerator { | |
| 205 public: | |
| 206 win32_accelerator() : m_accel(NULL) {} | |
| 207 ~win32_accelerator() {release();} | |
| 208 HACCEL get() const {return m_accel;} | |
| 209 | |
| 210 void load(HINSTANCE p_inst,const TCHAR * p_id); | |
| 211 void release(); | |
| 212 private: | |
| 213 HACCEL m_accel; | |
| 214 PFC_CLASS_NOT_COPYABLE_EX(win32_accelerator); | |
| 215 }; | |
| 216 | |
| 217 class SelectObjectScope { | |
| 218 public: | |
| 219 SelectObjectScope(HDC p_dc,HGDIOBJ p_obj) throw() : m_dc(p_dc), m_obj(SelectObject(p_dc,p_obj)) {} | |
| 220 ~SelectObjectScope() throw() {SelectObject(m_dc,m_obj);} | |
| 221 private: | |
| 222 PFC_CLASS_NOT_COPYABLE_EX(SelectObjectScope) | |
| 223 HDC m_dc; | |
| 224 HGDIOBJ m_obj; | |
| 225 }; | |
| 226 | |
| 227 // WARNING: Windows is known to truncate the coordinates to float32 internally instead of retaining original int | |
| 228 // With large values, this OffsetWindowOrgEx behaves erratically | |
| 229 class OffsetWindowOrgScope { | |
| 230 public: | |
| 231 OffsetWindowOrgScope(HDC dc, const POINT & pt) throw() : m_dc(dc), m_pt(pt) { | |
| 232 OffsetWindowOrgEx(m_dc, m_pt.x, m_pt.y, NULL); | |
| 233 } | |
| 234 ~OffsetWindowOrgScope() throw() { | |
| 235 OffsetWindowOrgEx(m_dc, -m_pt.x, -m_pt.y, NULL); | |
| 236 } | |
| 237 | |
| 238 private: | |
| 239 const HDC m_dc; | |
| 240 const POINT m_pt; | |
| 241 }; | |
| 242 class DCStateScope { | |
| 243 public: | |
| 244 DCStateScope(HDC p_dc) throw() : m_dc(p_dc) { | |
| 245 m_state = SaveDC(m_dc); | |
| 246 } | |
| 247 ~DCStateScope() throw() { | |
| 248 RestoreDC(m_dc,m_state); | |
| 249 } | |
| 250 private: | |
| 251 const HDC m_dc; | |
| 252 int m_state; | |
| 253 }; | |
| 254 #endif // #ifdef PFC_WINDOWS_DESKTOP_APP | |
| 255 | |
| 256 class exception_com : public std::exception { | |
| 257 public: | |
| 258 exception_com(HRESULT p_code) : std::exception(format_hresult(p_code)), m_code(p_code) {} | |
| 259 exception_com(HRESULT p_code, const char * msg) : std::exception(format_hresult(p_code, msg)), m_code(p_code) {} | |
| 260 HRESULT get_code() const {return m_code;} | |
| 261 private: | |
| 262 HRESULT m_code; | |
| 263 }; | |
| 264 | |
| 265 #ifdef PFC_WINDOWS_DESKTOP_APP | |
| 266 | |
| 267 // Same format as _WIN32_WINNT macro. | |
| 268 WORD GetWindowsVersionCode() throw(); | |
| 269 | |
| 270 #endif | |
| 271 | |
| 272 //! Simple implementation of a COM reference counter. The initial reference count is zero, so it can be used with pfc::com_ptr_t<> with plain operator=/constructor rather than attach(). | |
| 273 template<typename TBase> class ImplementCOMRefCounter : public TBase { | |
| 274 public: | |
| 275 template<typename ... arg_t> ImplementCOMRefCounter(arg_t && ... arg) : TBase(std::forward<arg_t>(arg) ...) {} | |
| 276 | |
| 277 ULONG STDMETHODCALLTYPE AddRef() override { | |
| 278 return ++m_refcounter; | |
| 279 } | |
| 280 ULONG STDMETHODCALLTYPE Release() override { | |
| 281 long val = --m_refcounter; | |
| 282 if (val == 0) delete this; | |
| 283 return val; | |
| 284 } | |
| 285 protected: | |
| 286 virtual ~ImplementCOMRefCounter() {} | |
| 287 private: | |
| 288 pfc::refcounter m_refcounter; | |
| 289 }; | |
| 290 | |
| 291 | |
| 292 | |
| 293 template<typename TPtr> | |
| 294 class CoTaskMemObject { | |
| 295 public: | |
| 296 CoTaskMemObject() : m_ptr() {} | |
| 297 | |
| 298 ~CoTaskMemObject() {CoTaskMemFree(m_ptr);} | |
| 299 void Reset() {CoTaskMemFree(pfc::replace_null_t(m_ptr));} | |
| 300 TPtr * Receive() {Reset(); return &m_ptr;} | |
| 301 | |
| 302 TPtr m_ptr; | |
| 303 PFC_CLASS_NOT_COPYABLE(CoTaskMemObject, CoTaskMemObject<TPtr> ); | |
| 304 }; | |
| 305 | |
| 306 | |
| 307 namespace pfc { | |
| 308 bool isShiftKeyPressed(); | |
| 309 bool isCtrlKeyPressed(); | |
| 310 bool isAltKeyPressed(); | |
| 311 | |
| 312 class winHandle { | |
| 313 public: | |
| 314 winHandle(HANDLE h_ = INVALID_HANDLE_VALUE) : h(h_) {} | |
| 315 ~winHandle() { Close(); } | |
| 316 void Close() { | |
| 317 if (h != INVALID_HANDLE_VALUE && h != NULL ) { CloseHandle(h); h = INVALID_HANDLE_VALUE; } | |
| 318 } | |
| 319 | |
| 320 void Attach(HANDLE h_) { Close(); h = h_; } | |
| 321 HANDLE Detach() { HANDLE t = h; h = INVALID_HANDLE_VALUE; return t; } | |
| 322 | |
| 323 HANDLE Get() const { return h; } | |
| 324 operator HANDLE() const { return h; } | |
| 325 | |
| 326 HANDLE h; | |
| 327 private: | |
| 328 winHandle(const winHandle&) = delete; | |
| 329 void operator=(const winHandle&) = delete; | |
| 330 }; | |
| 331 | |
| 332 void winSleep( double seconds ); | |
| 333 void sleepSeconds(double seconds); | |
| 334 void yield(); | |
| 335 | |
| 336 #ifdef PFC_WINDOWS_DESKTOP_APP | |
| 337 void winSetThreadDescription(HANDLE hThread, const wchar_t * desc); | |
| 338 | |
| 339 pfc::string8 format_window(HWND wnd); | |
| 340 pfc::string8 format_windowStyle(DWORD); | |
| 341 #endif // PFC_WINDOWS_DESKTOP_APP | |
| 342 | |
| 343 int winNaturalSortCompare(const char* s1, const char* s2); | |
| 344 int winNaturalSortCompare(const wchar_t* s1, const wchar_t* s2); | |
| 345 int winNaturalSortCompareI(const char* s1, const char* s2); | |
| 346 int winNaturalSortCompareI(const wchar_t* s1, const wchar_t* s2); | |
| 347 | |
| 348 } |
