#pragma once 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); } class format_win32_error { public: format_win32_error(DWORD p_code); const char * get_ptr() const {return m_buffer.get_ptr();} operator const char*() const {return m_buffer.get_ptr();} private: pfc::string8 m_buffer; }; class format_hresult { public: format_hresult(HRESULT p_code); format_hresult(HRESULT p_code, const char * msgOverride); const char * get_ptr() const {return m_buffer.get_ptr();} operator const char*() const {return m_buffer.get_ptr();} private: void stamp_hex(HRESULT p_code); pfc::string_formatter m_buffer; }; 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 class CGlobalLockScopeT { public: CGlobalLockScopeT(HGLOBAL handle) : m_scope(handle) {} TItem * GetPtr() const {return reinterpret_cast(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 a control inside window? Also returns true if child==parent. bool IsWindowChildOf(HWND child, HWND parent); //! Is window a child (popup or control) of 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);} 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 ); private: win32_event(const win32_event&) = delete; void operator=(const win32_event &) = delete; HANDLE m_handle; }; 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; }; 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 class ImplementCOMRefCounter : public TBase { public: template ImplementCOMRefCounter(arg_t && ... arg) : TBase(std::forward(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 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 ); }; 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); #if PFC_DEBUG #define PFC_SET_THREAD_DESCRIPTION(msg) ::pfc::winSetThreadDescription(GetCurrentThread(), L##msg); #define PFC_SET_THREAD_DESCRIPTION_SUPPORTED #endif // PFC_DEBUG #endif // PFC_WINDOWS_DESKTOP_APP }