Mercurial > foo_out_sdl
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foosdk/sdk/pfc/win-objects.h Mon Jan 05 02:15:46 2026 -0500 @@ -0,0 +1,348 @@ +#pragma once + +#include "ref_counter.h" + +namespace pfc { + BOOL winFormatSystemErrorMessage(pfc::string_base & p_out,DWORD p_code); + + // Prefix filesystem paths with \\?\ and \\?\UNC where appropriate. + void winPrefixPath(pfc::string_base & out, const char * p_path); + // Reverse winPrefixPath + void winUnPrefixPath(pfc::string_base & out, const char * p_path); + + string8 winPrefixPath( const char * in ); + string8 winUnPrefixPath( const char * in ); + + class LastErrorRevertScope { + public: + LastErrorRevertScope() : m_val(GetLastError()) {} + ~LastErrorRevertScope() { SetLastError(m_val); } + + private: + const DWORD m_val; + }; + + string8 getWindowText(HWND wnd); + void setWindowText(HWND wnd, const char * txt); + string8 getWindowClassName( HWND wnd ); + HWND findOwningPopup(HWND wnd); +} + +pfc::string8 format_win32_error(DWORD code); +pfc::string8 format_hresult(HRESULT code); +pfc::string8 format_hresult(HRESULT code, const char * msgOverride); + +class exception_win32 : public std::exception { +public: + exception_win32(DWORD p_code) : std::exception(format_win32_error(p_code)), m_code(p_code) {} + DWORD get_code() const {return m_code;} +private: + DWORD m_code; +}; + +#ifdef PFC_WINDOWS_DESKTOP_APP + +void uAddWindowStyle(HWND p_wnd,LONG p_style); +void uRemoveWindowStyle(HWND p_wnd,LONG p_style); +void uAddWindowExStyle(HWND p_wnd,LONG p_style); +void uRemoveWindowExStyle(HWND p_wnd,LONG p_style); +unsigned MapDialogWidth(HWND p_dialog,unsigned p_value); +bool IsKeyPressed(unsigned vk); + +//! Returns current modifier keys pressed, using win32 MOD_* flags. +unsigned GetHotkeyModifierFlags(); + +class CClipboardOpenScope { +public: + CClipboardOpenScope() : m_open(false) {} + ~CClipboardOpenScope() {Close();} + bool Open(HWND p_owner); + void Close(); +private: + bool m_open; + + PFC_CLASS_NOT_COPYABLE_EX(CClipboardOpenScope) +}; + +class CGlobalLockScope { +public: + CGlobalLockScope(HGLOBAL p_handle); + ~CGlobalLockScope(); + void * GetPtr() const {return m_ptr;} + t_size GetSize() const {return GlobalSize(m_handle);} +private: + void * m_ptr; + HGLOBAL m_handle; + + PFC_CLASS_NOT_COPYABLE_EX(CGlobalLockScope) +}; + +template<typename TItem> class CGlobalLockScopeT { +public: + CGlobalLockScopeT(HGLOBAL handle) : m_scope(handle) {} + TItem * GetPtr() const {return reinterpret_cast<TItem*>(m_scope.GetPtr());} + t_size GetSize() const { + const t_size val = m_scope.GetSize(); + PFC_ASSERT( val % sizeof(TItem) == 0 ); + return val / sizeof(TItem); + } +private: + CGlobalLockScope m_scope; +}; + +//! Resigns active window status passing it to the parent window, if wnd or a child popup of is active. \n +//! Use this to mitigate Windows 10 1809 active window handling bugs - call prior to DestroyWindow() +void ResignActiveWindow(HWND wnd); +//! Is point inside a control? +bool IsPointInsideControl(const POINT& pt, HWND wnd); +//! Is <child> a control inside <parent> window? Also returns true if child==parent. +bool IsWindowChildOf(HWND child, HWND parent); +//! Is <child> window a child (popup or control) of <parent> window? Also returns true if child==parent. +bool IsPopupWindowChildOf(HWND child, HWND parent); + +class win32_menu { +public: + win32_menu(HMENU p_initval) : m_menu(p_initval) {} + win32_menu() : m_menu(NULL) {} + ~win32_menu() {release();} + void release(); + void set(HMENU p_menu) {release(); m_menu = p_menu;} + void create_popup(); + HMENU get() const {return m_menu;} + HMENU detach() {return pfc::replace_t(m_menu,(HMENU)NULL);} + + bool is_valid() const {return m_menu != NULL;} +private: + win32_menu(const win32_menu &) = delete; + void operator=(const win32_menu &) = delete; + + HMENU m_menu; +}; + +#endif + +class win32_event { +public: + win32_event() : m_handle(NULL) {} + ~win32_event() {release();} + + void create(bool p_manualreset,bool p_initialstate); + + void set(HANDLE p_handle) {release(); m_handle = p_handle;} + HANDLE get() const {return m_handle;} + HANDLE get_handle() const {return m_handle;} + HANDLE detach() {return pfc::replace_t(m_handle,(HANDLE)NULL);} + bool is_valid() const {return m_handle != NULL;} + + void release(); + + //! Returns true when signaled, false on timeout + bool wait_for(double p_timeout_seconds) {return g_wait_for(get(),p_timeout_seconds);} + void wait() { wait_for(-1); } + void wait_and_clear() { wait(); set_state(false); } + + static DWORD g_calculate_wait_time(double p_seconds); + + //! Returns true when signaled, false on timeout + static bool g_wait_for(HANDLE p_event,double p_timeout_seconds); + + void set_state(bool p_state); + bool is_set() { return wait_for(0); } + + // Two-wait event functions, return 0 on timeout, 1 on evt1 set, 2 on evt2 set + static int g_twoEventWait( win32_event & ev1, win32_event & ev2, double timeout ); + static int g_twoEventWait( HANDLE ev1, HANDLE ev2, double timeout ); + + // Multi-wait. Returns SIZE_MAX on timeout, 0 based event index if either event becomes set. + static size_t g_multiWait(const HANDLE* events, size_t count, double timeout); + static size_t g_multiWait( std::initializer_list<HANDLE> const & arg, double timeout ); +private: + win32_event(const win32_event&) = delete; + void operator=(const win32_event &) = delete; + + HANDLE m_handle; +}; + +namespace pfc { + typedef HANDLE eventHandle_t; + + static constexpr eventHandle_t eventInvalid = NULL; + + class event : public win32_event { + public: + event(bool initial = false) { create(true, initial); } + + HANDLE get_handle() const { return win32_event::get(); } + }; +} + +void uSleepSeconds(double p_time,bool p_alertable); + +#ifdef PFC_WINDOWS_DESKTOP_APP + +class win32_icon { +public: + win32_icon(HICON p_initval) : m_icon(p_initval) {} + win32_icon() : m_icon(NULL) {} + ~win32_icon() {release();} + + void release(); + + void set(HICON p_icon) {release(); m_icon = p_icon;} + HICON get() const {return m_icon;} + HICON detach() {return pfc::replace_t(m_icon,(HICON)NULL);} + + bool is_valid() const {return m_icon != NULL;} + +private: + win32_icon(const win32_icon&) = delete; + const win32_icon & operator=(const win32_icon &) = delete; + + HICON m_icon; +}; + +class win32_accelerator { +public: + win32_accelerator() : m_accel(NULL) {} + ~win32_accelerator() {release();} + HACCEL get() const {return m_accel;} + + void load(HINSTANCE p_inst,const TCHAR * p_id); + void release(); +private: + HACCEL m_accel; + PFC_CLASS_NOT_COPYABLE_EX(win32_accelerator); +}; + +class SelectObjectScope { +public: + SelectObjectScope(HDC p_dc,HGDIOBJ p_obj) throw() : m_dc(p_dc), m_obj(SelectObject(p_dc,p_obj)) {} + ~SelectObjectScope() throw() {SelectObject(m_dc,m_obj);} +private: + PFC_CLASS_NOT_COPYABLE_EX(SelectObjectScope) + HDC m_dc; + HGDIOBJ m_obj; +}; + +// WARNING: Windows is known to truncate the coordinates to float32 internally instead of retaining original int +// With large values, this OffsetWindowOrgEx behaves erratically +class OffsetWindowOrgScope { +public: + OffsetWindowOrgScope(HDC dc, const POINT & pt) throw() : m_dc(dc), m_pt(pt) { + OffsetWindowOrgEx(m_dc, m_pt.x, m_pt.y, NULL); + } + ~OffsetWindowOrgScope() throw() { + OffsetWindowOrgEx(m_dc, -m_pt.x, -m_pt.y, NULL); + } + +private: + const HDC m_dc; + const POINT m_pt; +}; +class DCStateScope { +public: + DCStateScope(HDC p_dc) throw() : m_dc(p_dc) { + m_state = SaveDC(m_dc); + } + ~DCStateScope() throw() { + RestoreDC(m_dc,m_state); + } +private: + const HDC m_dc; + int m_state; +}; +#endif // #ifdef PFC_WINDOWS_DESKTOP_APP + +class exception_com : public std::exception { +public: + exception_com(HRESULT p_code) : std::exception(format_hresult(p_code)), m_code(p_code) {} + exception_com(HRESULT p_code, const char * msg) : std::exception(format_hresult(p_code, msg)), m_code(p_code) {} + HRESULT get_code() const {return m_code;} +private: + HRESULT m_code; +}; + +#ifdef PFC_WINDOWS_DESKTOP_APP + +// Same format as _WIN32_WINNT macro. +WORD GetWindowsVersionCode() throw(); + +#endif + +//! 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(). +template<typename TBase> class ImplementCOMRefCounter : public TBase { +public: + template<typename ... arg_t> ImplementCOMRefCounter(arg_t && ... arg) : TBase(std::forward<arg_t>(arg) ...) {} + + ULONG STDMETHODCALLTYPE AddRef() override { + return ++m_refcounter; + } + ULONG STDMETHODCALLTYPE Release() override { + long val = --m_refcounter; + if (val == 0) delete this; + return val; + } +protected: + virtual ~ImplementCOMRefCounter() {} +private: + pfc::refcounter m_refcounter; +}; + + + +template<typename TPtr> +class CoTaskMemObject { +public: + CoTaskMemObject() : m_ptr() {} + + ~CoTaskMemObject() {CoTaskMemFree(m_ptr);} + void Reset() {CoTaskMemFree(pfc::replace_null_t(m_ptr));} + TPtr * Receive() {Reset(); return &m_ptr;} + + TPtr m_ptr; + PFC_CLASS_NOT_COPYABLE(CoTaskMemObject, CoTaskMemObject<TPtr> ); +}; + + +namespace pfc { + bool isShiftKeyPressed(); + bool isCtrlKeyPressed(); + bool isAltKeyPressed(); + + class winHandle { + public: + winHandle(HANDLE h_ = INVALID_HANDLE_VALUE) : h(h_) {} + ~winHandle() { Close(); } + void Close() { + if (h != INVALID_HANDLE_VALUE && h != NULL ) { CloseHandle(h); h = INVALID_HANDLE_VALUE; } + } + + void Attach(HANDLE h_) { Close(); h = h_; } + HANDLE Detach() { HANDLE t = h; h = INVALID_HANDLE_VALUE; return t; } + + HANDLE Get() const { return h; } + operator HANDLE() const { return h; } + + HANDLE h; + private: + winHandle(const winHandle&) = delete; + void operator=(const winHandle&) = delete; + }; + + void winSleep( double seconds ); + void sleepSeconds(double seconds); + void yield(); + +#ifdef PFC_WINDOWS_DESKTOP_APP + void winSetThreadDescription(HANDLE hThread, const wchar_t * desc); + + pfc::string8 format_window(HWND wnd); + pfc::string8 format_windowStyle(DWORD); +#endif // PFC_WINDOWS_DESKTOP_APP + + int winNaturalSortCompare(const char* s1, const char* s2); + int winNaturalSortCompare(const wchar_t* s1, const wchar_t* s2); + int winNaturalSortCompareI(const char* s1, const char* s2); + int winNaturalSortCompareI(const wchar_t* s1, const wchar_t* s2); + +}
