/** * @file XTPSystemHelpers.h * * @copyright * (c) 1998-2025 Codejock Software, All Rights Reserved. * * This source file is the property of Codejock Software and must not be * redistributed by any means without the explicit written permission of * Codejock Software. * * The use of this source code is governed by the terms and conditions specified * in the Toolkit Pro license agreement. Codejock Software grants you, as a * single software developer, the limited right to use this software on one * computer only. * * Contact Information: * support@codejock.com * http://www.codejock.com * */ /** @cond */ #if !defined(__XTPSYSTEMHELPERS_H__) # define __XTPSYSTEMHELPERS_H__ /** @endcond */ # if _MSC_VER > 1000 # pragma once # endif // _MSC_VER > 1000 # include "Common/Base/Diagnostic/XTPDisableAdvancedWarnings.h" # include # include # include "Common/Base/Diagnostic/XTPEnableAdvancedWarnings.h" # include "Common/Base/Diagnostic/XTPDisableNoisyWarnings.h" /** @cond */ class CXTPDummySingletonDependency; /** @endcond */ template< class Singleton1 = CXTPDummySingletonDependency, class Singleton2 = CXTPDummySingletonDependency, class Singleton3 = CXTPDummySingletonDependency, class Singleton4 = CXTPDummySingletonDependency, class Singleton5 = CXTPDummySingletonDependency, class Singleton6 = CXTPDummySingletonDependency, class Singleton7 = CXTPDummySingletonDependency, class Singleton8 = CXTPDummySingletonDependency, class Singleton9 = CXTPDummySingletonDependency, class Singleton10 = CXTPDummySingletonDependency> class CXTPSingletonDependencies; template > class CXTPSingleton; class CXTPSystemVersion; /** * @brief * The XTPSystemVersion function is used for access to the * CXTPSystemVersion class. * @details * Call this function to access CXTPSystemVersion members. Since * this class is designed as a single instance object you can only * access its members through this method. You cannot directly * instantiate an object of type CXTPSystemVersion. * @return * A pointer to the one and only CXTPSystemVersion instance. * * Example: * The following example demonstrates the use of XTPSystemVersion. *
 * bool bIsWinNT = XTPSystemVersion()-\>IsWinNT4();
 * 
* @see * CXTPSystemVersion */ _XTP_EXT_CLASS CXTPSystemVersion* AFXAPI XTPSystemVersion(); /** * @brief * CXTPModuleHandle class is helper for LoadLibray/GetModuleHandle methods */ class _XTP_EXT_CLASS CXTPModuleHandle { public: /** * @brief * Module state enum. */ enum XTPModuleState { xtpModNone, /**< Indicates no module found. */ xtpModMapped, /**< Indicates the module handle was set using GetModuleHandle */ xtpModLoaded /**< Indicates the module handle was set using LoadLibrary. */ }; public: /** * @brief * Constructs a CXTPModuleHandle object. */ CXTPModuleHandle(); /** * @brief * Constructs a CXTPModuleHandle object. * @param lpszModuleName Pointer to a null-terminated string that names * the .DLL file. The name specified is the * filename of the module and is not related to the * name stored in the library module itself, as * specified by the LIBRARY keyword in the module- * definition (.DEF) file. * If the string specifies a path but the file does * not exist in the specified directory, the * function fails. When specifying a path, be sure * to use backslashes (\\), not forward slashes (/). */ CXTPModuleHandle(LPCTSTR lpszModuleName); /** * @brief * Destroys a CXTPModuleHandle object, handles cleanup and deallocation */ virtual ~CXTPModuleHandle(); /** * @brief * Call this method to LoadLibrary * @param lpszModuleName Pointer to a null-terminated string that names * the .DLL file. The name specified is the * filename of the module and is not related to the * name stored in the library module itself, as * specified by the LIBRARY keyword in the module- * definition (.DEF) file. * If the string specifies a path but the file does * not exist in the specified directory, the * function fails. When specifying a path, be sure * to use backslashes (\\), not forward slashes (/). * @return TRUE if successful, FALSE otherwise. */ BOOL Init(LPCTSTR lpszModuleName); /** * @brief * This member function is called to load the library specified * by 'lpszModule'. Once the library is loaded, you can * retrieve the instance handle by using the HINSTANCE operator. * @param lpszModuleName Pointer to a null-terminated string that names * the .DLL file. The name specified is the * filename of the module and is not related to the * name stored in the library module itself, as * specified by the LIBRARY keyword in the module- * definition (.DEF) file. * If the string specifies a path but the file does * not exist in the specified directory, the * function fails. When specifying a path, be sure * to use backslashes (\\), not forward slashes (/). * @return TRUE if successful, FALSE otherwise. */ BOOL LoadLibrary(LPCTSTR lpszModuleName); /** * @brief * The GetModuleHandle function retrieves a module handle for the specified module * if the file has been mapped into the address space of the calling process. * @param lpszModuleName Pointer to a null-terminated string that contains the name * of the module (either a .dll or .exe file). * @return TRUE if successful, FALSE otherwise. */ BOOL GetModuleHandle(LPCTSTR lpszModuleName); /** * @brief * The FreeLibrary function decrements the reference count of the loaded * dynamic-link library (DLL). * @return TRUE if successful, FALSE otherwise. */ BOOL FreeLibrary(); /** * @brief * The GetProcAddress function retrieves the address of the specified * exported dynamic-link library (DLL) function. * @param dwMinVer Specifies the minimum acceptable module version. * @param ppFnPtr Receives a retrieved function pointer upon successful execution. * @param lpProcName Specifies the procedure name. * @return TRUE if successful, FALSE otherwise. */ BOOL GetProcAddress(FARPROC* ppFnPtr, LPCSTR lpProcName, DWORD dwMinVer = NULL); /** * @brief * Use this member function to return the version number of the * module attached to this CLoadLibrary object. The high-order * word of the return value represents the major version number * and the low-order word of the returned value represents the * minor version number. * @return * A DWORD value if successful, otherwise 0L. */ DWORD GetVersion(); /** * @brief * This overloaded operator returns a handle to the module * indicating success. NULL indicates failure. * @return * A handle to the module if successful, otherwise returns NULL. */ operator HMODULE() const; /** * @brief * This method returns a handle to the module * indicating success. NULL indicates failure. * @return * A handle to the module if successful, otherwise returns NULL. */ HMODULE GetHandle() const; /** * @return * Returns Path to loaded library */ CString GetName() const; /** * @return * Returns module state */ XTPModuleState GetModuleState() const; private: BOOL GetVersionInfo(); BOOL EnsureModuleState(); BOOL IsModule(LPCTSTR lpName, int nLen = -1) const; struct XTP_DLLVERSIONINFO { DWORD cbSize; DWORD dwMajorVersion; /**< Major version */ DWORD dwMinorVersion; /**< Minor version */ DWORD dwBuildNumber; /**< Build number */ DWORD dwPlatformID; /**< DLLVER_PLATFORM_* */ }; CString m_strModuleName; /**< Module path */ HMODULE m_hModule; /**< A handle to the module indicates success. */ XTPModuleState m_eModuleState; /**< Module state */ XTP_DLLVERSIONINFO m_dvInfo; /**< Version information */ typedef HRESULT(WINAPI* PFNDLLVERSIONINFO)(XTP_DLLVERSIONINFO*); PFNDLLVERSIONINFO m_pfnDllGetVersion; }; /** @cond */ AFX_INLINE HMODULE CXTPModuleHandle::GetHandle() const { return m_hModule; } AFX_INLINE CXTPModuleHandle::operator HMODULE() const { return m_hModule; } AFX_INLINE CString CXTPModuleHandle::GetName() const { return m_strModuleName; } AFX_INLINE CXTPModuleHandle::XTPModuleState CXTPModuleHandle::GetModuleState() const { return m_eModuleState; } /** @endcond */ // Obsolete name //#define CXTLoadLibrary CXTPModuleHandle /** * @brief * CXTPSystemVersion is used to get the current * Windows OS version. CXTPSystemVersion is a single instance, or * "singleton" object, that is accessed with the Get() method. */ class _XTP_EXT_CLASS CXTPSystemVersion { friend class CXTPSingleton; private: /** * @brief * Constructs a CXTPSystemVersion object. */ CXTPSystemVersion(); public: /** * @brief * Compares a set of operating system version requirements to the * corresponding values for the currently running version of the system. * Uses different available methods of version information extraction. * @param dwConditionMask A variable to be passed as the condition mask, * can be either VER_EQUAL or VER_GREATER_EQUAL. * @param dwMajorVersion The major version number of the operating system. * @param dwMinorVersion The minor version number of the operating system. * @param dwPlatformId The operating system platform. * @return * If the currently running operating system satisfies the specified * requirements, the return value is true, otherwise returns false. */ bool VerifyWinVer(BYTE dwConditionMask, DWORD dwMajorVersion, DWORD dwMinorVersion, DWORD dwPlatformId) const; /** * @brief * Compares a set of operating system version requirements to the * corresponding values for the currently running version of the system. * Uses VerifyVersionInfo Windows API function if available. * @param dwConditionMask A variable to be passed as the condition mask, * can be either VER_EQUAL or VER_GREATER_EQUAL. * @param dwMajorVersion The major version number of the operating system. * @param dwMinorVersion The minor version number of the operating system. * @param dwPlatformId The operating system platform. * @return * If the currently running operating system satisfies the specified * requirements, the return value is S_OK, otherwise returns S_FALSE. * If VerifyVersionInfo is not available then the return value is E_NOTIMPL. */ LRESULT VerifyVersion(BYTE dwConditionMask, DWORD dwMajorVersion, DWORD dwMinorVersion, DWORD dwPlatformId) const; /** * @brief * Compares a set of operating system version requirements to the * corresponding values for the currently running version of the system. * Uses GetVersionEx Windows API function for version data extraction. * @param dwConditionMask A variable to be passed as the condition mask, * can be either VER_EQUAL or VER_GREATER_EQUAL. * @param dwMajorVersion The major version number of the operating system. * @param dwMinorVersion The minor version number of the operating system. * @param dwPlatformId The operating system platform. * @return * If the currently running operating system satisfies the specified * requirements, the return value is S_OK, otherwise returns S_FALSE. */ LRESULT GetVersion(BYTE dwConditionMask, DWORD dwMajorVersion, DWORD dwMinorVersion, DWORD dwPlatformId) const; /** * @brief * Retrieves OS version information. * @return * A pointer to the cached OS version information object or NULL if unable to get it. */ const OSVERSIONINFOEXW* GetOSVersionInfo() const; /** * @brief * Call this member function to check whether or not the * operating system is Windows 3.1. * @return * true if the OS is Windows 3.1, otherwise returns false. */ bool IsWin31() const; /** * @brief * Call this member function to check whether or not the * operating system is Windows 95. * @return * true if the OS is Windows 95, otherwise returns false. */ bool IsWin95() const; /** * @brief * Call this member function to check whether or not the * operating system is Windows 98. * @return * true if the OS is Windows 98, otherwise returns false. */ bool IsWin98() const; /** * @brief * Call this member function to check whether or not the * operating system is Windows ME. * @return * true if the OS is Windows ME, otherwise returns false. */ bool IsWinME() const; /** * @brief * Call this member function to check whether or not the * operating system is Windows NT 4. * @return * true if the OS is Windows NT 4, otherwise returns false. */ bool IsWinNT4() const; /** * @brief * Call this member function to check whether or not the * operating system is Windows 2000. * @return * true if the OS is Windows 2000, otherwise returns false. */ bool IsWin2K() const; /** * @brief * Call this member function to check whether or not the * operating system is Windows XP. * @return * true if the OS is Windows XP, otherwise returns false. */ bool IsWinXP() const; /** * @brief * Call this member function to check whether or not the * operating system is greater than or equal to Windows 3.1. * @return * true if the OS is greater than or equal to Windows 3.1, * otherwise returns false. */ bool IsWin31OrGreater() const; /** * @brief * Call this member function to check whether or not the * operating system is of the Windows 9x family, and if it is * Windows 95 or a later version. * @return * true if the OS is of the Windows 9x family, and is Windows 95 * or a later version, otherwise returns false. */ bool IsWin95OrGreater() const; /** * @brief * Call this member function to check whether or not the * operating system is of the Windows 9x family, and if it is * Windows 98 or a later version. * @return * true if the OS is of the Windows 9x family, and is Windows 98 * or a later version, otherwise returns false. */ bool IsWin98OrGreater() const; /** * @brief * Call this member function to check whether or not the * operating system is of the Windows 9x family, and if it is * Windows ME or a later version. * @return * true if the OS is of the Windows 9x family, and is Windows ME * or a later version, otherwise returns false. */ bool IsWinMEOrGreater() const; /** * @brief * Call this member function to check whether or not the * operating system is of the Windows 9x family * @return * true if the OS is of the Windows 9x family */ bool IsWin9x() const; /** * @brief * Call this member function to check whether or not the * operating system is of the Windows NT family, and if it is * Windows NT 4 or a later version. * @return * true if the OS is of the Windows NT family, and is Windows NT * 4 or a later version, otherwise returns false. */ bool IsWinNT4OrGreater() const; /** * @brief * Call this member function to check whether or not the * operating system is of the Windows NT family, and if it is * Windows 2000 or a later version. * @return * true if the OS is of the Windows NT family, and is Windows * 2000 or a later version, otherwise returns false. */ bool IsWin2KOrGreater() const; /** * @brief * Call this member function to check whether or not the * operating system is of the Windows NT family, and if it is * Windows XP or a later version. * @return * true if the OS is of the Windows NT family, and is Windows XP * or a later version, otherwise returns false. */ bool IsWinXPOrGreater() const; /** * @brief * Call this member function to check whether or not the * operating system is of the Windows NT family, and if it is * Windows Vista or a later version. * @return * true if the OS is of the Windows NT family, and is Windows Vista * or a later version, otherwise returns false. */ bool IsWinVistaOrGreater() const; /** * @brief * Call this member function to check whether or not the * operating system is of the Windows NT family, and if it is * Windows 7 or a later version. * @return * true if the OS is of the Windows NT family, and is Windows 7 * or a later version, otherwise returns false. */ bool IsWin7OrGreater() const; /** * @brief * Call this member function to check whether or not the * operating system is of the Windows NT family, and if it is * Windows 8 or a later version. * @return * true if the OS is of the Windows NT family, and is Windows 8 * or a later version, otherwise returns false. */ bool IsWin8OrGreater() const; /** * @brief * Call this member function to check whether or not the * operating system is of the Windows NT family, and if it is * Windows 8.1 or a later version. * @return * true if the OS is of the Windows NT family, and is Windows 8.1 * or a later version, otherwise returns false. */ bool IsWin81OrGreater() const; /** * @brief * Call this member function to check whether or not the * operating system is of the Windows NT family, and if it is * Windows 10 or a later version. * @return * true if the OS is of the Windows NT family, and is Windows 10 * or a later version, otherwise returns false. */ bool IsWin10OrGreater() const; /** * @brief * Call this member function to check whether or not the * operating system is of the Windows NT family, and if it is * Windows 11 or a later version. * @return * true if the OS is of the Windows NT family, and is Windows 11 * or a later version, otherwise returns false. */ bool IsWin11OrGreater() const; public: /** * @brief * Use this member function to return the version number of the * comctl32.dll. The high-order word of the return * value represents the major version number and the low-order * word of the returned value represents the minor version number. * @return * A DWORD value if successful, otherwise 0L. */ DWORD GetComCtlVersion() const; public: /** * @brief * Determines if right-to-left (RTL) formatting is supported by current OS * @return * TRUE if right-to-left (RTL) formatting is supported. */ BOOL IsLayoutRTLSupported() const; /** * @brief * Determines if ClearType text is supported by current OS * @return TRUE if ClearType text is supported. */ BOOL IsClearTypeTextQualitySupported() const; /** * @brief * Obtains the maximum length, in bytes, of a character in an OEM code page. * @return * The number of bytes per character. */ int GetMaxCharSize() const; private: CXTPModuleHandle m_modKernel32; CXTPModuleHandle m_modNtdll; BOOL(WINAPI* m_pfnVerifyVersionInfo)(LPOSVERSIONINFOEX, DWORD, DWORDLONG); ULONGLONG(WINAPI* m_pfnVerSetConditionMask)(ULONGLONG, DWORD, BYTE); LONG(WINAPI* m_pfnRtlGetVersion)(OSVERSIONINFOEXW*); friend _XTP_EXT_CLASS CXTPSystemVersion* AFXAPI XTPSystemVersion(); }; // deprecated # define XTOSVersionInfo XTPSystemVersion /** * @brief * MultiMonitor API wrapper class */ class _XTP_EXT_CLASS CXTPMultiMonitor { friend class CXTPSingleton; private: DECLARE_HANDLE(XTP_HMONITOR); private: struct XTP_MONITORINFO { DWORD cbSize; RECT rcMonitor; RECT rcWork; DWORD dwFlags; }; struct XTP_MONITORINFOEX : XTP_MONITORINFO { TCHAR szDevice[CCHDEVICENAME]; }; private: CXTPMultiMonitor(); public: /** * @brief * This function retrieves work area for the display monitor that * the mouse cursor is currently positioned over. * @return * If the mouse cursor is positioned over a display monitor, the * return value is a CRect object that specifies the work area * rectangle of the display monitor, expressed in virtual-screen * coordinates. Otherwise, returns the size of the work area on * the primary display monitor. */ CRect GetWorkArea(); /** * @brief * This function retrieves work area for the display monitor that * the mouse cursor is currently positioned over. * @param point Point of interest. * @return * If the mouse cursor is positioned over a display monitor, the * return value is a CRect object that specifies the work area * rectangle of the display monitor, expressed in virtual-screen * coordinates. Otherwise, returns the size of the work area on * the primary display monitor. */ CRect GetWorkArea(const POINT& point); /** * @brief * This function retrieves work area for the display monitor that * the mouse cursor is currently positioned over. * @param rect Reference to a CRect class that specifies the * coordinates of the rectangle of interest in virtual * screen coordinates. * @return * If the mouse cursor is positioned over a display monitor, the * return value is a CRect object that specifies the work area * rectangle of the display monitor, expressed in virtual-screen * coordinates. Otherwise, returns the size of the work area on * the primary display monitor. */ CRect GetWorkArea(LPCRECT rect); /** * @brief * This function retrieves work area for the display monitor that * the mouse cursor is currently positioned over. * @param pWnd Pointer to the window of interest. * @return * If the mouse cursor is positioned over a display monitor, the * return value is a CRect object that specifies the work area * rectangle of the display monitor, expressed in virtual-screen * coordinates. Otherwise, returns the size of the work area on * the primary display monitor. */ CRect GetWorkArea(const CWnd* pWnd); /** * @brief * This function retrieves work area for the display monitor that * the mouse cursor is currently positioned over. * @param hWnd Handle to the window of interest. * @return * If the mouse cursor is positioned over a display monitor, the * return value is a CRect object that specifies the work area * rectangle of the display monitor, expressed in virtual-screen * coordinates. Otherwise, returns the size of the work area on * the primary display monitor. */ CRect GetWorkArea(HWND hWnd); /** * @brief * This function retrieves work area for the display monitor that * the mouse cursor is currently positioned over. * @param pWnd Pointer to the window of interest. * @return * If the mouse cursor is positioned over a display monitor, the * return value is a CRect object that specifies the work area * rectangle of the display monitor, expressed in virtual-screen * coordinates. Otherwise, returns the size of the work area on * the primary display monitor. */ CRect GetScreenArea(const CWnd* pWnd); /** * @brief * This function retrieves work area for the display monitor that * the mouse cursor is currently positioned over. * @param hWnd Handle to the window of interest. * @return * If the mouse cursor is positioned over a display monitor, the * return value is a CRect object that specifies the work area * rectangle of the display monitor, expressed in virtual-screen * coordinates. Otherwise, returns the size of the work area on * the primary display monitor. */ CRect GetScreenArea(HWND hWnd); /** * @brief * This function retrieves work area for the display monitor that * the mouse cursor is currently positioned over. * @param point Point of interest. * @return * If the mouse cursor is positioned over a display monitor, the * return value is a CRect object that specifies the work area * rectangle of the display monitor, expressed in virtual-screen * coordinates. Otherwise, returns the size of the work area on * the primary display monitor. */ CRect GetScreenArea(const POINT& point); /** * @brief * This function retrieves work area for the display monitor that * the mouse cursor is currently positioned over. * @param rect Reference to a CRect class that specifies the * coordinates of the rectangle of interest in virtual * screen coordinates. * @return * If the mouse cursor is positioned over a display monitor, the * return value is a CRect object that specifies the work area * rectangle of the display monitor, expressed in virtual-screen * coordinates. Otherwise, returns the size of the work area on * the primary display monitor. */ CRect GetScreenArea(LPCRECT rect); /** * @brief * Obtains display settings for a monitor associated with the window * handle provided. * @param pWnd Window object pointer * @param lpDevMode Points to DEVMODE object instance with dmSize field * initialized to a valid structure size value. Upon * successful completion this object will contain valid * display settings. * @return * TRUE if display settings obtained successfully. */ BOOL GetDisplaySettings(const CWnd* pWnd, DEVMODE* lpDevMode); /** * @brief * Obtains display settings for a monitor associated with the window * handle provided. * @param hWnd Window handle * @param lpDevMode Points to DEVMODE object instance with dmSize field * initialized to a valid structure size value. Upon * successful completion this object will contain valid * display settings. * @return * TRUE if display settings obtained successfully. */ BOOL GetDisplaySettings(HWND hWnd, DEVMODE* lpDevMode); private: BOOL GetMonitorInfo(XTP_HMONITOR hMonitor, XTP_MONITORINFO* lpMonitorInfo); CRect GetWorkArea(XTP_HMONITOR hMonitor); CRect GetScreenArea(XTP_HMONITOR hMonitor); int(WINAPI* m_pfnGetSystemMetrics)(int); XTP_HMONITOR(WINAPI* m_pfnMonitorFromWindow)(HWND, DWORD); XTP_HMONITOR(WINAPI* m_pfnMonitorFromRect)(LPCRECT, DWORD); XTP_HMONITOR(WINAPI* m_pfnMonitorFromPoint)(POINT, DWORD); BOOL(WINAPI* m_pfnGetMonitorInfo)(XTP_HMONITOR, XTP_MONITORINFO*); BOOL(WINAPI* m_pfnEnumDisplaySettingsEx)(LPCTSTR, DWORD, DEVMODE*, DWORD); CXTPModuleHandle m_modUser32; friend _XTP_EXT_CLASS CXTPMultiMonitor* AFX_CDECL XTPMultiMonitor(); }; /** * @brief * Call this function to access CXTPMultiMonitor members. * Since this class is designed as a single instance object you can * only access its members through this method. You cannot * directly instantiate an object of type CXTPMultiMonitor. * * Example: *
CRect rcWork = XTPMultiMonitor()->GetWorkArea();
* @return A global multi monitor helper object pointer. */ _XTP_EXT_CLASS CXTPMultiMonitor* AFX_CDECL XTPMultiMonitor(); /** * @brief * Critical Section Wrapper */ class _XTP_EXT_CLASS CXTPCriticalSection { public: /** * @brief * Constructs a CXTPCriticalSection object */ CXTPCriticalSection(); /** * @brief * Destroys a CXTPCriticalSection object, handles cleanup and deallocation */ ~CXTPCriticalSection(); public: /** * @brief * The EnterCriticalSection function waits for ownership of the * specified critical section object */ void EnterCritical(); /** * @brief * The LeaveCriticalSection function releases ownership of the * specified critical section object */ void LeaveCritical(); /** * @brief * Returns CRITICAL_SECTION reference */ operator CRITICAL_SECTION&() { return m_csMutex; } private: CRITICAL_SECTION m_csMutex; }; /** * @brief * Critical Sections Lock/Unlock helper */ class _XTP_EXT_CLASS CXTPLockGuard { public: /** * @brief * Constructs a CXTPLockGuard object * @param key CRITICAL_SECTION used to lock thread */ CXTPLockGuard(CRITICAL_SECTION& key); /** * @brief * Destroys a CXTPCriticalSection object, handles cleanup and deallocation */ ~CXTPLockGuard(); public: /** * @brief This method call EnterCritical of key object */ void LockThread(); /** * @brief This method call LeaveCritical of key object */ void UnLockThread(); private: DISABLE_COPY_OPERATOR(CXTPLockGuard); private: CRITICAL_SECTION& m_key; }; /** @cond */ # ifndef CHILDID_SELF # define CHILDID_SELF 0 # endif # ifndef WM_GETOBJECT # define WM_GETOBJECT 0x003D # endif # ifndef EVENT_OBJECT_FOCUS # define EVENT_OBJECT_FOCUS 0x8005 # endif # ifndef OBJID_MENU # define OBJID_MENU 0xFFFFFFFD # endif # ifndef OBJID_CLIENT # define OBJID_CLIENT 0xFFFFFFFC # endif # ifndef OBJID_WINDOW # define OBJID_WINDOW 0x00000000 # endif class _XTP_EXT_CLASS CXTPAccessibleProxy; class _XTP_EXT_CLASS CXTPAccessible { friend class CXTPAccessibleProxy; public: CXTPAccessible(); virtual ~CXTPAccessible(); LRESULT LresultFromProxyObject(WPARAM wParam); IAccessible* CreateAccProxy(); public: virtual HRESULT GetAccessibleParent(IDispatch** ppdispParent); virtual HRESULT GetAccessibleChildCount(long* pcountChildren); virtual HRESULT GetAccessibleChild(VARIANT varChild, IDispatch** ppdispChild); virtual HRESULT GetAccessibleName(VARIANT varChild, BSTR* pszName); virtual HRESULT GetAccessibleValue(VARIANT varChild, BSTR* pszValue); virtual HRESULT GetAccessibleDescription(VARIANT varChild, BSTR* pszDescription); virtual HRESULT GetAccessibleRole(VARIANT varChild, VARIANT* pvarRole); virtual HRESULT GetAccessibleState(VARIANT varChild, VARIANT* pvarState); virtual HRESULT GetAccessibleHelp(VARIANT varChild, BSTR* pszHelp); virtual HRESULT GetAccessibleHelpTopic(BSTR* pszHelpFile, VARIANT varChild, long* pidTopic); virtual HRESULT GetAccessibleKeyboardShortcut(VARIANT varChild, BSTR* pszKeyboardShortcut); virtual HRESULT GetAccessibleFocus(VARIANT* pvarChild); virtual HRESULT GetAccessibleSelection(VARIANT* pvarChildren); virtual HRESULT GetAccessibleDefaultAction(VARIANT varChild, BSTR* pszDefaultAction); virtual HRESULT AccessibleSelect(long flagsSelect, VARIANT varChild); virtual HRESULT AccessibleLocation(long* pxLeft, long* pyTop, long* pcxWidth, long* pcyHeight, VARIANT varChild); virtual HRESULT AccessibleNavigate(long navDir, VARIANT varStart, VARIANT* pvarEndUpAt); virtual HRESULT AccessibleHitTest(long xLeft, long yTop, VARIANT* pvarChild); virtual HRESULT AccessibleDoDefaultAction(VARIANT varChild); // Obsolete virtual HRESULT PutAccessibleName(VARIANT varChild, BSTR szName); // Obsolete virtual HRESULT PutAccessibleValue(VARIANT varChild, BSTR szValue); virtual CCmdTarget* GetAccessible(); void AccessibleNotifyWinEvent(DWORD event, HWND hwnd, LONG idObject, LONG idChild); protected: HRESULT AccessibleObjectFromWindow(HWND hwnd, DWORD dwId, REFIID riid, void** ppvObject); LRESULT LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN punk); long GetChildIndex(VARIANT* varChild); public: # pragma warning(push) // C4616: #pragma warning : warning number '...' out of range, must be between '4001' and '4999' // C4619: #pragma warning : there is no warning number 'number' // C5204: '...': class has virtual functions, but its trivial destructor is not virtual; instances // of objects derived from this class may not be destructed correctly # pragma warning(disable : 4616 4619 5204) class _XTP_EXT_CLASS XAccessible; BEGIN_INTERFACE_PART(Accessible, IAccessible) STDMETHOD(GetTypeInfoCount)(UINT FAR* pctinfo); STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo); STDMETHOD(GetIDsOfNames) (REFIID riid, OLECHAR FAR* FAR* rgszNames, UINT cNames, LCID lcid, DISPID FAR* rgdispid); STDMETHOD(Invoke) (DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pdispparams, VARIANT FAR* pvarResult, EXCEPINFO FAR* pexcepinfo, UINT FAR* puArgErr); STDMETHOD(get_accParent)(IDispatch* FAR* ppdispParent); STDMETHOD(get_accChildCount)(long FAR* pChildCount); STDMETHOD(get_accChild)(VARIANT varChildIndex, IDispatch* FAR* ppdispChild); STDMETHOD(get_accName)(VARIANT varChild, BSTR* pszName); STDMETHOD(get_accValue)(VARIANT varChild, BSTR* pszValue); STDMETHOD(get_accDescription)(VARIANT varChild, BSTR FAR* pszDescription); STDMETHOD(get_accRole)(VARIANT varChild, VARIANT* pvarRole); STDMETHOD(get_accState)(VARIANT varChild, VARIANT* pvarState); STDMETHOD(get_accHelp)(VARIANT varChild, BSTR* pszHelp); STDMETHOD(get_accHelpTopic)(BSTR* pszHelpFile, VARIANT varChild, long* pidTopic); STDMETHOD(get_accKeyboardShortcut)(VARIANT varChild, BSTR* pszKeyboardShortcut); STDMETHOD(get_accFocus)(VARIANT FAR* pvarFocusChild); STDMETHOD(get_accSelection)(VARIANT FAR* pvarSelectedChildren); STDMETHOD(get_accDefaultAction)(VARIANT varChild, BSTR* pszDefaultAction); STDMETHOD(accSelect)(long flagsSelect, VARIANT varChild); STDMETHOD(accLocation) (long* pxLeft, long* pyTop, long* pcxWidth, long* pcyHeight, VARIANT varChild); STDMETHOD(accNavigate)(long navDir, VARIANT varStart, VARIANT* pvarEndUpAt); STDMETHOD(accHitTest)(long xLeft, long yTop, VARIANT* pvarChildAtPoint); STDMETHOD(accDoDefaultAction)(VARIANT varChild); STDMETHOD(put_accName)(VARIANT varChild, BSTR szName); STDMETHOD(put_accValue)(VARIANT varChild, BSTR pszValue); END_INTERFACE_PART(ExternalAccessible) # pragma warning(pop) private: typedef VOID(WINAPI* LPFNNOTIFYWINEVENT)(DWORD event, HWND hwnd, LONG idObject, LONG idChild); LPFNNOTIFYWINEVENT m_pNotifyWinEvent; LPFNLRESULTFROMOBJECT m_pLresultFromObject; LPFNACCESSIBLEOBJECTFROMWINDOW m_pAccessibleObjectFromWindow; HMODULE m_hUser32; HMODULE m_hOleAcc; struct SharedHandle { SharedHandle(CXTPAccessible* pAcc); void AddRef(); void Release(); CXTPAccessible* pAcc; ULONG cRefs; }; SharedHandle* m_pHandle; }; class _XTP_EXT_CLASS CXTPAccessibleProxy : public IAccessible { public: explicit CXTPAccessibleProxy(CXTPAccessible::SharedHandle* pAccHandle); virtual ~CXTPAccessibleProxy(); BOOL IsAlive() const; private: virtual HRESULT STDMETHODCALLTYPE QueryInterface( /* [in] */ REFIID riid, /* [iid_is][out] */ void** ppvObject); virtual ULONG STDMETHODCALLTYPE AddRef(void); virtual ULONG STDMETHODCALLTYPE Release(void); virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount( /* [out] */ UINT* pctinfo); virtual HRESULT STDMETHODCALLTYPE GetTypeInfo( /* [in] */ UINT iTInfo, /* [in] */ LCID lcid, /* [out] */ ITypeInfo** ppTInfo); virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames( /* [in] */ REFIID riid, /* [size_is][in] */ LPOLESTR* rgszNames, /* [range][in] */ UINT cNames, /* [in] */ LCID lcid, /* [size_is][out] */ DISPID* rgDispId); virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke( /* [annotation][in] */ DISPID dispIdMember, /* [annotation][in] */ REFIID riid, /* [annotation][in] */ LCID lcid, /* [annotation][in] */ WORD wFlags, /* [annotation][out][in] */ DISPPARAMS* pDispParams, /* [annotation][out] */ VARIANT* pVarResult, /* [annotation][out] */ EXCEPINFO* pExcepInfo, /* [annotation][out] */ UINT* puArgErr); virtual /* [id][propget][hidden] */ HRESULT STDMETHODCALLTYPE get_accParent( /* [retval][out] */ IDispatch** ppdispParent); virtual /* [id][propget][hidden] */ HRESULT STDMETHODCALLTYPE get_accChildCount( /* [retval][out] */ long* pcountChildren); virtual /* [id][propget][hidden] */ HRESULT STDMETHODCALLTYPE get_accChild( /* [in] */ VARIANT varChild, /* [retval][out] */ IDispatch** ppdispChild); virtual /* [id][propget][hidden] */ HRESULT STDMETHODCALLTYPE get_accName( /* [optional][in] */ VARIANT varChild, /* [retval][out] */ BSTR* pszName); virtual /* [id][propget][hidden] */ HRESULT STDMETHODCALLTYPE get_accValue( /* [optional][in] */ VARIANT varChild, /* [retval][out] */ BSTR* pszValue); virtual /* [id][propget][hidden] */ HRESULT STDMETHODCALLTYPE get_accDescription( /* [optional][in] */ VARIANT varChild, /* [retval][out] */ BSTR* pszDescription); virtual /* [id][propget][hidden] */ HRESULT STDMETHODCALLTYPE get_accRole( /* [optional][in] */ VARIANT varChild, /* [retval][out] */ VARIANT* pvarRole); virtual /* [id][propget][hidden] */ HRESULT STDMETHODCALLTYPE get_accState( /* [optional][in] */ VARIANT varChild, /* [retval][out] */ VARIANT* pvarState); virtual /* [id][propget][hidden] */ HRESULT STDMETHODCALLTYPE get_accHelp( /* [optional][in] */ VARIANT varChild, /* [retval][out] */ BSTR* pszHelp); virtual /* [id][propget][hidden] */ HRESULT STDMETHODCALLTYPE get_accHelpTopic( /* [out] */ BSTR* pszHelpFile, /* [optional][in] */ VARIANT varChild, /* [retval][out] */ long* pidTopic); virtual /* [id][propget][hidden] */ HRESULT STDMETHODCALLTYPE get_accKeyboardShortcut( /* [optional][in] */ VARIANT varChild, /* [retval][out] */ BSTR* pszKeyboardShortcut); virtual /* [id][propget][hidden] */ HRESULT STDMETHODCALLTYPE get_accFocus( /* [retval][out] */ VARIANT* pvarChild); virtual /* [id][propget][hidden] */ HRESULT STDMETHODCALLTYPE get_accSelection( /* [retval][out] */ VARIANT* pvarChildren); virtual /* [id][propget][hidden] */ HRESULT STDMETHODCALLTYPE get_accDefaultAction( /* [optional][in] */ VARIANT varChild, /* [retval][out] */ BSTR* pszDefaultAction); virtual /* [id][hidden] */ HRESULT STDMETHODCALLTYPE accSelect( /* [in] */ long flagsSelect, /* [optional][in] */ VARIANT varChild); virtual /* [id][hidden] */ HRESULT STDMETHODCALLTYPE accLocation( /* [out] */ long* pxLeft, /* [out] */ long* pyTop, /* [out] */ long* pcxWidth, /* [out] */ long* pcyHeight, /* [optional][in] */ VARIANT varChild); virtual /* [id][hidden] */ HRESULT STDMETHODCALLTYPE accNavigate( /* [in] */ long navDir, /* [optional][in] */ VARIANT varStart, /* [retval][out] */ VARIANT* pvarEndUpAt); virtual /* [id][hidden] */ HRESULT STDMETHODCALLTYPE accHitTest( /* [in] */ long xLeft, /* [in] */ long yTop, /* [retval][out] */ VARIANT* pvarChild); virtual /* [id][hidden] */ HRESULT STDMETHODCALLTYPE accDoDefaultAction( /* [optional][in] */ VARIANT varChild); virtual /* [id][propput][hidden] */ HRESULT STDMETHODCALLTYPE put_accName( /* [optional][in] */ VARIANT varChild, /* [in] */ BSTR szName); virtual /* [id][propput][hidden] */ HRESULT STDMETHODCALLTYPE put_accValue( /* [optional][in] */ VARIANT varChild, /* [in] */ BSTR szValue); private: CXTPAccessible::SharedHandle* m_pAccHandle; ULONG m_cRefs; }; /** @endcond */ /** * @brief * Enumeration used to play system sound. * * Example: *
XTPSoundManager()->PlaySystemSound(xtpSoundMenuCommand);
* @see * CXTPSoundManager, xtpSoundNone, xtpSoundMenuCommand, xtpSoundMenuPopup */ enum XTPSoundManagerState { xtpSoundNone, /**< No Sound (default) */ xtpSoundMenuCommand, /**< Menu command system sound */ xtpSoundMenuPopup, /**< Menu pop-up system sound */ }; /** * @brief * CXTPSoundManager is a standalone class. It used to play system sound. * @see * XTPSoundManagerState, XTPSoundManager */ class _XTP_EXT_CLASS CXTPSoundManager { friend class CXTPSingleton; friend _XTP_EXT_CLASS CXTPSoundManager* AFX_CDECL XTPSoundManager(); /** * @brief * Constructs a CXTPSoundManager object. */ CXTPSoundManager(); public: /** * @brief * Destroys a CXTPSoundManager object, handles cleanup and deallocation */ ~CXTPSoundManager(); /** * @brief * Call this method to play system sound * @param state System sound to play. Can be any of the values listed in * the remarks section. * @details * State parameter can be one of the following: * xtpSoundMenuCommand: Play menu command system sound. * xtpSoundMenuPopup: Play menu pop-up system sound. */ void PlaySystemSound(XTPSoundManagerState state); /** * @brief * Call this method to disable all system sounds for application * @param bEnable FALSE to disable system sounds. * @details * Call this method to force system settings and disable all sounds. */ void EnableSystemSounds(BOOL bEnable); /** * @brief * This method is called to stop all sounds and terminate sound thread. */ void StopThread(); public: /** @cond */ BOOL IsSoundThreadProc(LPVOID pProc) const; BOOL IsSoundThreadId(DWORD dwTid) const; /** @endcond */ private: void StartThread(); static DWORD WINAPI SoundThreadProc(LPVOID); XTPSoundManagerState FetchSoundState(BOOL& bQuit); public: BOOL m_bSoundAvailable; /**< FALSE to disable sound. you can use "m_bSoundAvailable = waveOutGetNumDevs()" */ private: BOOL m_bSystemSounds; HANDLE m_hThread; HANDLE m_hThreadStartEvent; DWORD m_dwThreadId; }; /** * @brief * Call this function to access CXTPSoundManager members. * Since this class is designed as a single instance object you can * only access version info through this method. You cannot * directly instantiate an object of type CXTPSoundManager. * * Example: *
XTPSoundManager()->PlaySystemSound(xtpSoundMenuCommand);
* @return A global sound manager object pointer. */ _XTP_EXT_CLASS CXTPSoundManager* AFX_CDECL XTPSoundManager(); /** * @brief * Zipped memory file */ class _XTP_EXT_CLASS CXTPZipMemFile : public CMemFile { struct ZIPBUFFERHEADER { DWORD dwType; DWORD dwSize; }; struct ZIPBUFFERINFO { ZIPBUFFERHEADER bh; BYTE bBuffer[1]; }; public: CXTPZipMemFile(); CXTPZipMemFile(BYTE* lpBuffer, UINT nBufferSize); ~CXTPZipMemFile(); public: void AttachCompressedBuffer(BYTE* lpBuffer, UINT nBufferSize, BOOL bAutoDelete = FALSE); void DetachCompressedBuffer(BYTE*& lpBuffer, DWORD& dwCount); BOOL OpenCompressedFile(LPCTSTR lpszFileName); }; _XTP_EXT_CLASS CWinThread* AFX_CDECL XTPGetThread(); /** * @brief * URI type identifier. */ enum XTPUriType { xtpUriFile, /**< Local file URI. */ xtpUriRes /**< Resource in a local file URI. */ }; /** * @brief * Parse URI information. */ struct XTP_URI { XTPUriType type; /**< URI type. */ union { TCHAR file[MAX_PATH + 1]; /**< Valid only for xtpUriFile. Local file full path. */ struct { TCHAR szFilePath[MAX_PATH + 1]; /**< Local file full path. */ LPCTSTR lpType; /**< Resource type. */ LPCTSTR lpName; /**< Resource name. */ struct { TCHAR szType[50]; TCHAR szName[50]; } reserved; /**< Reserved for internal needs. */ } res; /**< Valid only for xtpUriRes. */ }; }; /** * @brief * Default URI values. */ struct XTP_URI_DEFAULTS { struct { LPCTSTR lpType; /**< Default resource type. */ } res; }; /** * @brief * Parses URI, Sample valid file URIs: *
 * file://C:/Windows/data.txt - absolute file URI
 * C:/Windows/data.txt - absolute file URI
 * file://data.txt - relative to executable module file URI.
 * data.txt - relative to executable module file URI.
 * file://../../bin/data.txt - relative to executable module file URI.
 * data.txt - relative to executable module file URI.
 * 
* Resource URI format: *
 * res://[absolute or relative path|.][/(type name|type ID)/](name|\#ID)
 * 
* * If optional resource type is not specified and no default values passed, * the default value return by XTPGetDefaultResourceTypeFromPath will be used. * A special '.' symbol must be used as file name for referring to * current executable resource directory. * * Sample valid resource URIs: *
 * res://C:/Windows/System32/mydll.dll/24/1
 * res://C:/Windows/System32/mydll.dll/test.html
 * res://../../bin/mydll.dll/2/101
 * res://./2/101
 * res://./1000
 * res://./1000.html
 * res://#1000
 * res://1000.html
 * 
* @param lpszUri Pointer to a NULL-terminated URI. * @param pUri Pointer to XTP_URI structure that will be filled with valid * values on successful return. * @param pDefaults Optional pointer to default URI values. * @return * S_OK if successful, otherwise a standard error code that indicates * the problem that occured. */ _XTP_EXT_CLASS HRESULT AFX_CDECL XTPParseUri(LPCTSTR lpszUri, XTP_URI* pUri, const XTP_URI_DEFAULTS* pDefaults = NULL); /** * @brief * Creates a read-only stream on object identified by the specified URI. * @param pUri Pointer to an object URI structure. * @param ppStream Output pointer that receives stream pointer. * @return * S_OK if successful, or a standard COM error code. */ _XTP_EXT_CLASS HRESULT AFX_CDECL XTPCreateReadOnlyStreamOnUri(const XTP_URI* pUri, IStream** ppStream); /** * @brief * Creates a read-only stream on object identified by the specified URI. * @param lpszUri Object URI string. * @param ppStream Output pointer that receives stream pointer. * @param pDefaults Optional pointer to default URI values. * @return * S_OK if successful, or a standard COM error code. */ _XTP_EXT_CLASS HRESULT AFX_CDECL XTPCreateReadOnlyStreamOnUri( LPCTSTR lpszUri, IStream** ppStream, const XTP_URI_DEFAULTS* pDefaults = NULL); /** * @brief * Attempts to load a Unicode text from a binary buffer. If source text is not * in Unicode format, converts to Unicode depending on detected * text encoding. Supported encodings: ANSI, UTF-8, Unicode. * @param pRawData Pointer to raw text data to load. * @param cbRawData Size of raw text data in bytes. * @param lpUnicodeText Pointer to a buffer large enough to hold text * after being converted to Unicode. * @param pchUnicodeText On input, contains number of WCHARs available in * lpUnicodeText buffer including terminating 0. * On output, contains number of WCHARs placed to the * buffer excluding terminating 0. * @return * TRUE if the Unicode text is successully loaded from a binary buffer, FALSE otherwise. */ _XTP_EXT_CLASS BOOL AFX_CDECL XTPLoadUnicodeText(const void* pRawData, UINT cbRawData, LPWSTR lpUnicodeText, UINT* pchUnicodeText); /** * @brief * Attempts to load text from a binary buffer. Depending on the active charset the text will be * converted from the source encoding into the active charset. Supported encodings: ANSI, UTF-8, * Unicode. * @param pRawData Pointer to raw text data to load. * @param cbRawData Size of raw text data in bytes. * @param lpText Pointer to a buffer large enough to hold text after being converted to Unicode. * @param pchText On input, contains number of TCHARs available in * lpText buffer including terminating 0. * On output, contains number of TCHARs placed to the * buffer excluding terminating 0. * @return * TRUE if the text is successully loaded from a binary buffer, FALSE otherwise. */ _XTP_EXT_CLASS BOOL AFX_CDECL XTPLoadText(const void* pRawData, UINT cbRawData, LPTSTR lpText, UINT* pchText); /** * @brief * Attempts to load text from a binary buffer. Depending on the active charset the text will be * converted from the source encoding into the active charset. Supported encodings: ANSI, UTF-8, * Unicode. * @param pRawData Pointer to raw text data to load. * @param cbRawData Size of raw text data in bytes. * @param strText Upon successful execution contains loaded text data. * @return * TRUE if the text is successully loaded from a binary buffer, FALSE otherwise. */ _XTP_EXT_CLASS BOOL AFX_CDECL XTPLoadText(const void* pRawData, UINT cbRawData, CString& strText); /** * @brief * Attempts to load text from a specified file. Depending on the active charset the text will be * converted from the source encoding into the active charset. Supported encodings: ANSI, UTF-8, * Unicode. * @param pRawData Pointer to raw text data to load. * @param cbRawData Size of raw text data in bytes. * @param strText Upon successful execution contains loaded text data. * @return * TRUE if the text is successully loaded from a file, FALSE otherwise. */ _XTP_EXT_CLASS BOOL AFX_CDECL XTPLoadFileText(LPCTSTR lpPath, CString& strText); /** * @brief * Creates a read-only stream on a block of memory. * @param pData Pointer to the beginning of a memory block. * @param cbData Memory block size in bytes. * @param bClone If TRUE, the block will be cloned for exclusive stream use * and released when the returned stream is destructed. * @param ppStream Output pointer that receives stream pointer. * @return * S_OK if successful, or a standard COM error code. */ _XTP_EXT_CLASS HRESULT AFX_CDECL XTPCreateReadOnlyMemoryStream(const void* pData, UINT cbData, BOOL bClone, IStream** ppStream); /** * @brief * Creates a stream on the file specified. * @param lpPath File path. * @param grfMode A combination of STGM flags from Windows SDK. * @param ppStream Output pointer that receives stream pointer. * @return * S_OK if successful, or a standard COM error code. */ _XTP_EXT_CLASS HRESULT AFX_CDECL XTPCreateFileStream(LPCTSTR lpPath, DWORD grfMode, IStream** ppStream); /** * @brief * Creates a read-only stream on the file specified. * @param lpPath File path. * @param ppStream Output pointer that receives stream pointer. * @return * S_OK if successful, or a standard COM error code. */ _XTP_EXT_CLASS HRESULT AFX_CDECL XTPCreateReadOnlyFileStream(LPCTSTR lpPath, IStream** ppStream); /** * @brief * Creates a read-only stream on a resource. * @param hModule Module handle where to look for the resource specified. * @param lpResource Resource name pointer or identifier. * @param lpResourceType Resource type name pointer or identifier. * @param bClone If TRUE, the block will be cloned for exclusive stream use * and released when the returned stream is destructed. * @param ppStream Output pointer that receives stream pointer. * @return * S_OK if successful, or a standard COM error code. */ _XTP_EXT_CLASS HRESULT AFX_CDECL XTPCreateReadOnlyResourceStream(HMODULE hModule, LPCTSTR lpResource, LPCTSTR lpResourceType, BOOL bClone, IStream** ppStream); /** * @brief * Reads data from the specified stream starting at the specified position. * @param pStream Stream pointer to read data from * @param pData Upon successful completion contains a pointer to a memory buffer * filled with data read * @param cbData Upon successful completion contains the size of the data block read * @param cbSizeNeeded The maximum number to read from the stream. * @param nSeek Seek position * @param nOffset Offset from the specified seek position. * @details * The allocated returned buffer must be released by a caller using XTPReleaseReadStreamData * call. * @return * S_OK if successful, or a standard COM error code. * @see * XTPReleaseReadStreamData */ _XTP_EXT_CLASS HRESULT AFX_CDECL XTPReadStreamData(IStream* pStream, LPVOID& pData, SIZE_T& cbData, ULONG cbSizeNeeded = ULONG_MAX, STREAM_SEEK nSeek = STREAM_SEEK_CUR, LONG nOffset = 0); /** * @brief * Releases a memory buffer allocated by XTPReadStreamData. * @param pData Memory buffer pointer. * @return * @see * XTPReleaseReadStreamData */ _XTP_EXT_CLASS void AFX_CDECL XTPReleaseReadStreamData(LPVOID pData); /** * Defines an invalid TLS slot value specific to XTP TLS pool */ # define XTP_INVALID_TLS_SLOT (~DWORD_PTR(0)) /** * @brief * Allocates a new slot in XTP TLS pool and assigns an initial value if provided. * @param pValue An optional initial value of the newly allocated XTP TLS slot. * @return * A valid XTP TLS slot or XTP_INVALID_TLS_SLOT if unable to allocate a new XTP TLS slot. * @see * XTPTlsSetValue, XTPTlsGetValue, XTPTlsFree, CXTPThreadLocal */ _XTP_EXT_CLASS DWORD_PTR AFX_CDECL XTPTlsAllocate(PVOID pValue = NULL); /** * @brief * Sets a new value to the previously allocated XTP TLS slot. * @param dwSlot XTP TLS slot. * @param pValue New XTP TLS slot value. * @return * TRUE if the new XTP TLS slot value is assined or FALSE otherwise. * @see * XTPTlsAllocate, XTPTlsGetValue, XTPTlsFree, CXTPThreadLocal */ _XTP_EXT_CLASS BOOL AFX_CDECL XTPTlsSetValue(DWORD_PTR dwSlot, PVOID pValue); /** * @brief * Obtains an assigned XTP TLS slot value. * @param dwSlot XTP TLS slot. * @return * An assigned XTP TLS slot value or NULL in case of an error or if no value is assigned. * @see * XTPTlsAllocate, XTPTlsSetValue, XTPTlsFree, CXTPThreadLocal */ _XTP_EXT_CLASS PVOID AFX_CDECL XTPTlsGetValue(DWORD_PTR dwSlot); /** * @brief * Releases a previously assigned XTP TLS slot. * @param dwSlot XTP TLS slot. * @return * TRUE if the slot is release or FALSE otherwise. * @see * XTPTlsAllocate, XTPTlsSetValue, XTPTlsGetValue, CXTPThreadLocal */ _XTP_EXT_CLASS BOOL AFX_CDECL XTPTlsFree(DWORD_PTR dwSlot); /** @cond */ template struct XTPDefaultInitProcs { static T* AFX_CDECL Create() { return new T(); } static void AFX_CDECL Destroy(T* p) { _ASSERTE(NULL != p); delete p; } }; /** @endcond */ /** * @brief * Implements thread local variable adapter. By default it is assumed that * the type of the adaptee is default constructible and * can be destroyed using the delete operator, otherwise the custom * object creation and destruction callbacks must be provided. * Parameter: * T - Type of thread local variable. * @see * XTPTlsAllocate, XTPTlsSetValue, XTPTlsGetValue, XTPTlsFree */ template class CXTPThreadLocal { public: /** * A custom object instance allocation and initialization callback type. */ typedef T*(AFX_CDECL* CreateProc)(); /** * A custom object instance destruction and deallocation callback type. */ typedef void(AFX_CDECL* DestroyProc)(T*); /** @cond */ typedef XTPDefaultInitProcs DefaultProcs; /** @endcond */ /** * @brief * Construct adapter only, no thread local variable is constructed. * @param pfnCreate A custom object instance allocation and initialization callback pointer. If * not specified then the default implementation is used. * @param pfnDestroy A custom object instance destruction and deallocation callback pointer. If * not specified then the default implementation is used. */ CXTPThreadLocal(CreateProc pfnCreate = DefaultProcs::Create, DestroyProc pfnDestroy = DefaultProcs::Destroy); /** * @brief * Deallocates all thread local variables. */ ~CXTPThreadLocal(); /** * @brief * Checks if an adapter is valid and can create thread local variables. * @return * TRUE if the adapter is valid. */ BOOL IsValid() const; /** * @brief * Resets and destroys allocated object either for the current thread or all threads that * use the object. * @param bCurrentThread If TRUE then the current thread specific object will be reset, * otherwise all previously created objects for all threads will be reset. */ void Reset(BOOL bCurrentThread = FALSE); /** * @brief * Gives access to a variable accessible only to the caller's thread. * If accesses occur for the first time during a thread's * execution, then a new variable is allocated. * @return * A reference to a thread local variable. */ T& operator*(); /** * @brief * Gives access to a variable accessible only to the caller's thread. * If accesses occur for the first time during a thread's * execution, then a new variable is allocated. * @return * A reference to a thread local variable. */ const T& operator*() const; private: T* GetData(BOOL bAllocate = TRUE); DWORD_PTR m_dwSlot; CreateProc m_pfnCreate; DestroyProc m_pfnDestroy; CXTPCriticalSection m_access; CMap m_ptrMap; }; /** @cond */ template AFX_INLINE CXTPThreadLocal::CXTPThreadLocal(CreateProc pfnCreate /*= DefaultProcs::Create*/, DestroyProc pfnDestroy /*= DefaultProcs::Destroy*/) : m_dwSlot(XTPTlsAllocate()) , m_pfnCreate(pfnCreate) , m_pfnDestroy(pfnDestroy) { _ASSERTE(NULL != pfnCreate); _ASSERTE(NULL != pfnDestroy); } template AFX_INLINE CXTPThreadLocal::~CXTPThreadLocal() { Reset(); if (IsValid()) XTPTlsFree(m_dwSlot); } template AFX_INLINE BOOL CXTPThreadLocal::IsValid() const { return (XTP_INVALID_TLS_SLOT != m_dwSlot); } template AFX_INLINE void CXTPThreadLocal::Reset(BOOL bCurrentThread /*= FALSE*/) { if (bCurrentThread) { T* pData = reinterpret_cast(XTPTlsGetValue(m_dwSlot)); if (NULL != pData) { CXTPLockGuard lock(m_access); m_ptrMap.RemoveKey(pData); m_pfnDestroy(pData); XTPTlsSetValue(m_dwSlot, NULL); } } else { CXTPLockGuard lock(m_access); POSITION pos = m_ptrMap.GetStartPosition(); while (NULL != pos) { T* ptr = NULL; m_ptrMap.GetNextAssoc(pos, ptr, ptr); m_pfnDestroy(ptr); } } } template AFX_INLINE T* CXTPThreadLocal::GetData(BOOL bAllocate /*= TRUE*/) { if (!IsValid()) return NULL; T* pData = reinterpret_cast(XTPTlsGetValue(m_dwSlot)); if (NULL == pData && bAllocate) { pData = m_pfnCreate(); if (!XTPTlsSetValue(m_dwSlot, pData)) { m_pfnDestroy(pData); pData = NULL; } CXTPLockGuard lock(m_access); m_ptrMap[pData] = pData; } return pData; } template AFX_INLINE T& CXTPThreadLocal::operator*() { _ASSERTE(IsValid()); return *GetData(); } template AFX_INLINE const T& CXTPThreadLocal::operator*() const { return const_cast(this)->operator*(); } /** @endcond */ /** * @brief * The CXTPExcludedMemberPadding type is used for declaring padding * members for the members that were excluded by conditional compilation * in order to preserve the layout of the compiled classes. */ template class CXTPExcludedMemberPadding { BYTE _[sizeof(Type)]; }; /** * @brief * Defines known global window classes IDs. One ID represents a whole * family of the control including all its verions. Should not be confused * with a particular window class. */ enum XTPWindowClass { xtpWindowClassRichEdit /**< RichEdit window class family. */ }; /** * @brief * Defines rules of how window class version has to be selected. */ enum XTPWindowClassVersionSelectionVerb { xtpWindowClassVersionExact, /**< The window class version is matched exactly. */ xtpWindowClassVersionAtLeast, /**< At least the specified window class version should be available. The largest available is selected in result. */ xtpWindowClassVersionHighest /**< The largest available is selected. */ }; /** * @brief * Defines supported RichEdit versions. */ enum XTPRichEditWindowClassVersion { xtpRichEditWindowClassVersion10, /**< Specifies RichEdit control version 10 */ xtpRichEditWindowClassVersion20, /**< Specifies RichEdit control version 20 */ xtpRichEditWindowClassVersion30, /**< Specifies RichEdit control version 30 */ xtpRichEditWindowClassVersion31, /**< Specifies RichEdit control version 31 */ xtpRichEditWindowClassVersion40, /**< Specifies RichEdit control version 40 */ xtpRichEditWindowClassVersion41, /**< Specifies RichEdit control version 41 */ xtpRichEditWindowClassVersion50, /**< Specifies RichEdit control version 50 */ xtpRichEditWindowClassVersion60, /**< Specifies RichEdit control version 60 */ xtpRichEditWindowClassVersion70, /**< Specifies RichEdit control version 70 */ xtpRichEditWindowClassDefault = xtpRichEditWindowClassVersion20 /**< Specifies RichEdit control version 20 */ }; /** * @brief * Loads and verifies a window class module of a specified version * according to version selection rule. * @param nClass One of the predefined window class identifiers. * @param nVerb Determines how windows class version is selected. * @param pnVersion On input, must contain a valid window class specific * version identified. In case of success on return, * it contains the actual value of the window class * version selected. Ignored if nVerb == xtpWindowClassVersionHighest. * @param pWndClass Optional. If not NULL and succeeded, then it gets filled * with window class specific information. * @return * TRUE if the class specified has been loaded and verified. */ _XTP_EXT_CLASS BOOL AFX_CDECL XTPLoadWindowClass(XTPWindowClass nClass, XTPWindowClassVersionSelectionVerb nVerb, int* pnVersion, LPWNDCLASS pWndClass = NULL); /** * @brief * Loads and verifies a window class module of a specified version * according to version selection rule. * @param nClass One of the predefined window class identifiers. * @param nVerb Determines how windows class version is selected. * @param nVersion Same as pnVersion, but not changed on return. * @param pWndClass Optional. If not NULL and succeeded, then it gets filled * with window class specific information. * @return * TRUE if the class specified has been loaded and verified. */ AFX_INLINE BOOL AFX_CDECL XTPLoadWindowClass(XTPWindowClass nClass, XTPWindowClassVersionSelectionVerb nVerb, int nVersion, LPWNDCLASS pWndClass = NULL) { return XTPLoadWindowClass(nClass, nVerb, &nVersion, pWndClass); } /** * Defines a set of COM/OLE initialization methods. */ enum XTPComInit { /** * Used internally */ xtpComInitInvalid = -1, /** * If passed to CXTPWinApp constructor or to XTPInitialize then uses xtpComInitAfxOle, otherwise * uses the previously used method for CXTPWinApp constructor or to XTPInitialize. */ xtpComInitAppDefault, /** * Causes extended COM initialization to be used. Initializes the thread for apartment-threaded * object concurrency. Must not be combined with xtpComInitMTA. */ xtpComInitSTA = 0x1, /** * Causes extended COM initialization to be used. Initializes the thread for multithreaded * object concurrency. Must not be combined with xtpComInitSTA. */ xtpComInitMTA = 0x2, /** * Causes extended COM initialization to be used. Disables DDE for OLE1 support. Can be combined * with xtpComInitSTA, xtpComInitMTA, xtpComInitAfxOle and xtpComInitModuleAfxOle. */ xtpComInitDisableOle1DDE = 0x4, /** * Causes extended COM initialization to be used. Increase memory usage in an attempt to * increase performance. Can be combined with xtpComInitSTA, xtpComInitMTA, xtpComInitAfxOle and * xtpComInitModuleAfxOle. */ xtpComInitSpeedOverMemory = 0x8, /** * Causes OLE initialization to be used. Must not be combined with other flags. */ xtpComInitOle = 0x10, /** * Causes default AFX OLE initialization to be used for the main application thread, all other * threads will initialized COM using xtpComInitSTA. This is the default and preferred * initialization method determined by xtpComInitAppDefault. Can be combined with * xtpComInitDisableOle1DDE and xtpComInitSpeedOverMemory. */ xtpComInitAfxOle = 0x20, /** * Causes default AFX OLE initialization to be used during MFC extension DLL initialization. Use * of _AFXDLL macro is required. All threads started from the DLL will initialized COM using * xtpComInitSTA. This is the default and preferred initialization method determined by * xtpComInitAppDefault. Can be combined with xtpComInitDisableOle1DDE and * xtpComInitSpeedOverMemory. */ xtpComInitModuleAfxOle = 0x40, /** * No COM/OLE initialization will be performed. The user takes the whole responsibility of * managing COM/OLE initialization and accepts the risks of potential incompatibilities with the * framework. Must not be combined with other flags. */ xtpComInitUserDefined = 0x10000000, /** @cond */ xtpComInitForce = 0x80000000 /** @endcond */ }; /** * @brief * Initializes COM and increments and holds COM initialization reference * counter for the thread where constructed. */ class _XTP_EXT_CLASS CXTPComInitializer { public: /** * @brief * Initializes COM for the calling thread. * @param xtpComInit COM/OLE initialization method. * @see * XTPComInit */ CXTPComInitializer(int xtpComInit = xtpComInitAppDefault); /** * @brief * Decrements COM reference counter and uninitializes COM for * the calling thread if it holds the last COM reference. */ ~CXTPComInitializer(); /** * @brief * Obtains COM initialization status code. * @return * COM initialization status code. */ HRESULT GetInitializationStatus() const; /** * @brief * Obtains COM initialization flags. * @return * COM initialization flags. * @see * XTPComInit */ int GetInitFlags() const; private: CXTPComInitializer(const CXTPComInitializer&); CXTPComInitializer& operator=(const CXTPComInitializer&); int m_xtpComInit; HRESULT m_hr; }; /** @cond */ AFX_INLINE HRESULT CXTPComInitializer::GetInitializationStatus() const { return m_hr; } AFX_INLINE int CXTPComInitializer::GetInitFlags() const { return m_xtpComInit; } /** @endcond */ template class CXTPObservable; /** * @brief * Holds a list of observable objects to which an oberser is subscribed. * When a list is destructed, it unsubscribes the observer from all * subscribed observable objects. * @param Observable Type of the observable object. * @param Observer Type of the observer object. * @see * CXTPObservable */ template class CXTPSubscriptionList { friend class CXTPObservable; struct SubscriptionInfo { CXTPObservable* pObservable; BOOL bMarkedUnsubscribed; }; public: /** * @brief * Constructs a subscription list for the provided observer. * @param observer Observer reference. */ explicit CXTPSubscriptionList(Observer& observer); /** * @brief * Handles subscription list destruction. */ ~CXTPSubscriptionList(); /** * @brief * Obtains the number of registered subscriptions for the observer. * @return * The number of registered subscriptions for the observer. */ UINT GetSubscriptionCount() const; private: void OnSubscribed(CXTPObservable* pObservable); void OnUnsubscribed(CXTPObservable* pObservable); Observer& m_Observer; CList m_Subscriptions; BOOL m_bBeingDestructed; }; /** * @brief * Provides a basic implementation of the Observable design pattern. * @param Owner Type of the derived owner class. * @param Observer Type of an observer object. */ template class CXTPObservable { struct ObserverInfo { Observer* pObserver; BOOL bRemove; CXTPSubscriptionList* pSubcriptionList; }; protected: /** * @brief * Constructs an observable object. */ CXTPObservable(); /** * @brief * Handles observable object destruction. */ ~CXTPObservable(); public: /** * @brief * Subscribes a unique observer for events. * @param pObserver A pointer to an observer object to be subscribed to events. * @param pSubcriptionList An optional pointer to the subscriber list. If * provided, then the observable object pointer is * added to the subscription list. */ void Subscribe(Observer* pObserver, CXTPSubscriptionList* pSubcriptionList = NULL); /** * @brief * Unsubscribes an observer from events. * @param pObserver A pointer to the observer object to unsubscribe from events. * @details * If an observer has been previously subscribed with the provided subscription * list pointer, then the subscription list is notified about observer * unsubscription for removing the observable object from the list. * @see * CXTPObservable::Subscribe */ void Unsubscribe(Observer* pObserver); /** * @brief * Notifies all subscribed observers in the order of subscription * about an event determined by an observer's method to be called for * each subscribed observer. * @param method A pointer to the observer's method to be called for each * subscribed observer. */ void Notify(void (Observer::*method)(Owner*)) { _ASSERTE(NULL != method); OnBeforeNotify(); for (INT_PTR i = 0; i < m_Observers.GetSize(); ++i) { if (!m_Observers[i].bRemove) { (m_Observers[i].pObserver->*method)(static_cast(this)); } } OnAfterNotify(); } /** * @brief * Notifies all subscribed observers in the reversed order of * subscription about an event determined by an observer's method * to be called for each subscribed observer. * @param method A pointer to the observer's method to be called for each * subscribed observer. */ void NotifyReversed(void (Observer::*method)(Owner*)) { _ASSERTE(NULL != method); OnBeforeNotify(); for (INT_PTR i = m_Observers.GetSize() - 1; 0 <= i; --i) { if (!m_Observers[i].bRemove) { (m_Observers[i].pObserver->*method)(static_cast(this)); } } OnAfterNotify(); } /** * @brief * Notifies all subscribed observers in the order of subscription * about an event determined by an observer's method to be called for * each subscribed observer. * @param method A pointer to the observer's method to be called for each * subscribed observer. */ template void NotifyDynamic(void (T::*method)(O*)) { _ASSERTE(NULL != method); OnBeforeNotify(); CXTPTypeId specializedTypeId = CXTPTypeIdOf::Id(); for (INT_PTR i = 0; i < m_Observers.GetSize(); ++i) { if (!m_Observers[i].bRemove) { T* pCastedObserver = reinterpret_cast( static_cast*>(m_Observers[i].pObserver) ->TryCastTo(specializedTypeId)); if (NULL != pCastedObserver) { (pCastedObserver->*method)(static_cast(static_cast(this))); } } } OnAfterNotify(); } /** * @brief * Notifies all subscribed observers in the reversed order of subscription * about an event determined by an observer's method to be called for * each subscribed observer. * @param method A pointer to the observer's method to be called for each * subscribed observer. */ template void NotifyDynamicReversed(void (T::*method)(O*)) { _ASSERTE(NULL != method); OnBeforeNotify(); CXTPTypeId specializedTypeId = CXTPTypeIdOf::Id(); for (INT_PTR i = m_Observers.GetSize() - 1; 0 <= i; --i) { if (!m_Observers[i].bRemove) { T* pCastedObserver = reinterpret_cast( static_cast*>(m_Observers[i].pObserver) ->TryCastTo(specializedTypeId)); if (NULL != pCastedObserver) { (pCastedObserver->*method)(static_cast(static_cast(this))); } } } OnAfterNotify(); } /** * @brief * Notifies all subscribed observers in the order of subscription * about an event determined by an observer's method to be called * for each subscribed observer. * @param method A pointer to the observer's method to be called for each * subscribed observer. * @param arg1 The first argument to be passed to each call of the specified * method for each subscribed observer. */ template void Notify(void (Observer::*method)(Owner*, A1), A1 arg1) { _ASSERTE(NULL != method); OnBeforeNotify(); for (INT_PTR i = 0; i < m_Observers.GetSize(); ++i) { if (!m_Observers[i].bRemove) { (m_Observers[i].pObserver->*method)(static_cast(this), arg1); } } OnAfterNotify(); } /** * @brief * Notifies all subscribed observers in the reversed order of subscription * about an event determined by an observer's method to be called * for each subscribed observer. * @param method A pointer to the observer's method to be called for each * subscribed observer. * @param arg1 The first argument to be passed to each call of the specified * method for each subscribed observer. */ template void NotifyReversed(void (Observer::*method)(Owner*, A1), A1 arg1) { _ASSERTE(NULL != method); OnBeforeNotify(); for (INT_PTR i = m_Observers.GetSize() - 1; 0 <= i; --i) { if (!m_Observers[i].bRemove) { (m_Observers[i].pObserver->*method)(static_cast(this), arg1); } } OnAfterNotify(); } /** * @brief * Notifies all subscribed observers in the order of subscription * about an event determined by an observer's method to be called for * each subscribed observer. * @param method A pointer to the observer's method to be called for each * subscribed observer. * @param arg1 The first argument to be passed to each call of the specified * method for each subscribed observer. */ template void NotifyDynamic(void (T::*method)(O*, A1), A1 arg1) { _ASSERTE(NULL != method); OnBeforeNotify(); CXTPTypeId specializedTypeId = CXTPTypeIdOf::Id(); for (INT_PTR i = 0; i < m_Observers.GetSize(); ++i) { if (!m_Observers[i].bRemove) { T* pCastedObserver = reinterpret_cast( static_cast*>(m_Observers[i].pObserver) ->TryCastTo(specializedTypeId)); if (NULL != pCastedObserver) { (pCastedObserver->*method)(static_cast(static_cast(this)), arg1); } } } OnAfterNotify(); } /** * @brief * Notifies all subscribed observers in the reversed order of subscription * about an event determined by an observer's method to be called for * each subscribed observer. * @param method A pointer to the observer's method to be called for each * subscribed observer. * @param arg1 The first argument to be passed to each call of the specified * method for each subscribed observer. */ template void NotifyDynamicReversed(void (T::*method)(O*, A1), A1 arg1) { _ASSERTE(NULL != method); OnBeforeNotify(); CXTPTypeId specializedTypeId = CXTPTypeIdOf::Id(); for (INT_PTR i = m_Observers.GetSize() - 1; 0 <= i; --i) { if (!m_Observers[i].bRemove) { T* pCastedObserver = reinterpret_cast( static_cast*>(m_Observers[i].pObserver) ->TryCastTo(specializedTypeId)); if (NULL != pCastedObserver) { (pCastedObserver->*method)(static_cast(static_cast(this)), arg1); } } } OnAfterNotify(); } /** * @brief * Notifies all subscribed observers in the order of subscription * about an event determined by an observer's method to be called * for each subscribed observer. * @param method A pointer to the observer's method to be called for each * subscribed observer. * @param arg1 The first argument to be passed to each call of the specified * method for each subscribed observer. * @param arg2 The second argument to be passed to each call of the specified * method for each subscribed observer. */ template void Notify(void (Observer::*method)(Owner*, A1, A2), A1 arg1, A2 arg2) { _ASSERTE(NULL != method); OnBeforeNotify(); for (INT_PTR i = 0; i < m_Observers.GetSize(); ++i) { if (!m_Observers[i].bRemove) { (m_Observers[i].pObserver->*method)(static_cast(this), arg1, arg2); } } OnAfterNotify(); } /** * @brief * Notifies all subscribed observers in the reversed order of subscription * about an event determined by an observer's method to be called * for each subscribed observer. * @param method A pointer to the observer's method to be called for each * subscribed observer. * @param arg1 The first argument to be passed to each call of the specified * method for each subscribed observer. * @param arg2 The second argument to be passed to each call of the specified * method for each subscribed observer. */ template void NotifyReversed(void (Observer::*method)(Owner*, A1, A2), A1 arg1, A2 arg2) { _ASSERTE(NULL != method); OnBeforeNotify(); for (INT_PTR i = m_Observers.GetSize() - 1; 0 <= i; --i) { if (!m_Observers[i].bRemove) { (m_Observers[i].pObserver->*method)(static_cast(this), arg1, arg2); } } OnAfterNotify(); } /** * @brief * Notifies all subscribed observers in the order of subscription * about an event determined by an observer's method to be called * for each subscribed observer. * @param method A pointer to the observer's method to be called for each * subscribed observer. * @param arg1 The first argument to be passed to each call of the specified * method for each subscribed observer. * @param arg2 The second argument to be passed to each call of the specified * method for each subscribed observer. */ template void NotifyDynamic(void (T::*method)(O*, A1, A2), A1 arg1, A2 arg2) { _ASSERTE(NULL != method); OnBeforeNotify(); CXTPTypeId specializedTypeId = CXTPTypeIdOf::Id(); for (INT_PTR i = 0; i < m_Observers.GetSize(); ++i) { if (!m_Observers[i].bRemove) { T* pCastedObserver = reinterpret_cast( static_cast*>(m_Observers[i].pObserver) ->TryCastTo(specializedTypeId)); if (NULL != pCastedObserver) { (pCastedObserver->*method)(static_cast(static_cast(this)), arg1, arg2); } } } OnAfterNotify(); } /** * @brief * Notifies all subscribed observers in the reversed order of subscription * about an event determined by an observer's method to be called * for each subscribed observer. * @param method A pointer to the observer's method to be called for each * subscribed observer. * @param arg1 The first argument to be passed to each call of the specified * method for each subscribed observer. * @param arg2 The second argument to be passed to each call of the specified * method for each subscribed observer. */ template void NotifyDynamicReversed(void (T::*method)(O*, A1, A2), A1 arg1, A2 arg2) { _ASSERTE(NULL != method); OnBeforeNotify(); CXTPTypeId specializedTypeId = CXTPTypeIdOf::Id(); for (INT_PTR i = m_Observers.GetSize() - 1; 0 <= i; --i) { if (!m_Observers[i].bRemove) { T* pCastedObserver = reinterpret_cast( static_cast*>(m_Observers[i].pObserver) ->TryCastTo(specializedTypeId)); if (NULL != pCastedObserver) { (pCastedObserver->*method)(static_cast(static_cast(this)), arg1, arg2); } } } OnAfterNotify(); } /** * @brief * Notifies all subscribed observers in the order of subscription * about an event determined by an observer's method to be called * for each subscribed observer. * @param method A pointer to the observer's method to be called for each * subscribed observer. * @param arg1 The first argument to be passed to each call of the specified * method for each subscribed observer. * @param arg2 The second argument to be passed to each call of the specified * method for each subscribed observer. * @param arg3 The third argument to be passed to each call of the specified * method for each subscribed observer. */ template void Notify(void (Observer::*method)(Owner*, A1, A2, A3), A1 arg1, A2 arg2, A3 arg3) { _ASSERTE(NULL != method); OnBeforeNotify(); for (INT_PTR i = 0; i < m_Observers.GetSize(); ++i) { if (!m_Observers[i].bRemove) { (m_Observers[i].pObserver->*method)(static_cast(this), arg1, arg2, arg3); } } OnAfterNotify(); } /** * @brief * Notifies all subscribed observers in the reversed order of subscription * about an event determined by an observer's method to be called * for each subscribed observer. * @param method A pointer to the observer's method to be called for each * subscribed observer. * @param arg1 The first argument to be passed to each call of the specified * method for each subscribed observer. * @param arg2 The second argument to be passed to each call of the specified * method for each subscribed observer. * @param arg3 The third argument to be passed to each call of the specified * method for each subscribed observer. */ template void NotifyReversed(void (Observer::*method)(Owner*, A1, A2, A3), A1 arg1, A2 arg2, A3 arg3) { _ASSERTE(NULL != method); OnBeforeNotify(); for (INT_PTR i = m_Observers.GetSize() - 1; 0 <= i; --i) { if (!m_Observers[i].bRemove) { (m_Observers[i].pObserver->*method)(static_cast(this), arg1, arg2, arg3); } } OnAfterNotify(); } /** * @brief * Notifies all subscribed observers in the order of subscription * about an event determined by an observer's method to be called * for each subscribed observer. * @param method A pointer to the observer's method to be called for each * subscribed observer. * @param arg1 The first argument to be passed to each call of the specified * method for each subscribed observer. * @param arg2 The second argument to be passed to each call of the specified * method for each subscribed observer. * @param arg3 The third argument to be passed to each call of the specified * method for each subscribed observer. */ template void NotifyDynamic(void (T::*method)(O*, A1, A2, A3), A1 arg1, A2 arg2, A3 arg3) { _ASSERTE(NULL != method); OnBeforeNotify(); CXTPTypeId specializedTypeId = CXTPTypeIdOf::Id(); for (INT_PTR i = 0; i < m_Observers.GetSize(); ++i) { if (!m_Observers[i].bRemove) { T* pCastedObserver = reinterpret_cast( static_cast*>(m_Observers[i].pObserver) ->TryCastTo(specializedTypeId)); if (NULL != pCastedObserver) { (pCastedObserver->*method)(static_cast(static_cast(this)), arg1, arg2, arg3); } } } OnAfterNotify(); } /** * @brief * Notifies all subscribed observers in the reversed order of subscription * about an event determined by an observer's method to be called * for each subscribed observer. * @param method A pointer to the observer's method to be called for each * subscribed observer. * @param arg1 The first argument to be passed to each call of the specified * method for each subscribed observer. * @param arg2 The second argument to be passed to each call of the specified * method for each subscribed observer. * @param arg3 The third argument to be passed to each call of the specified * method for each subscribed observer. */ template void NotifyDynamicReversed(void (T::*method)(O*, A1, A2, A3), A1 arg1, A2 arg2, A3 arg3) { _ASSERTE(NULL != method); OnBeforeNotify(); CXTPTypeId specializedTypeId = CXTPTypeIdOf::Id(); for (INT_PTR i = m_Observers.GetSize() - 1; 0 <= i; --i) { if (!m_Observers[i].bRemove) { T* pCastedObserver = reinterpret_cast( static_cast*>(m_Observers[i].pObserver) ->TryCastTo(specializedTypeId)); if (NULL != pCastedObserver) { (pCastedObserver->*method)(static_cast(static_cast(this)), arg1, arg2, arg3); } } } OnAfterNotify(); } private: CArray m_Observers; LONG m_nNotificationDepth; INT_PTR FindObserver(Observer* pObserver) const; void OnBeforeNotify(); void OnAfterNotify(); void RemoveObserver(INT_PTR nIndex); }; template AFX_INLINE CXTPSubscriptionList::CXTPSubscriptionList(Observer& observer) : m_Observer(observer) , m_bBeingDestructed(FALSE) { } template AFX_INLINE CXTPSubscriptionList::~CXTPSubscriptionList() { m_bBeingDestructed = TRUE; POSITION pos = m_Subscriptions.GetHeadPosition(); while (NULL != pos) { SubscriptionInfo& subscription = m_Subscriptions.GetNext(pos); if (!subscription.bMarkedUnsubscribed) { subscription.pObservable->Unsubscribe(&m_Observer); } } _ASSERTE("Unable to unsubscribe from all subscriptions. The dangling observer pointer can lead " "to unspecified behavior." && 0 == GetSubscriptionCount()); } template AFX_INLINE UINT CXTPSubscriptionList::GetSubscriptionCount() const { UINT nCount = 0; POSITION pos = m_Subscriptions.GetHeadPosition(); while (NULL != pos) { const SubscriptionInfo& subscription = m_Subscriptions.GetNext(pos); if (!subscription.bMarkedUnsubscribed) { ++nCount; } } return nCount; } template AFX_INLINE void CXTPSubscriptionList::OnSubscribed( CXTPObservable* pObservable) { _ASSERTE(NULL != pObservable); SubscriptionInfo subscriptionInfo = { pObservable, FALSE }; m_Subscriptions.AddTail(subscriptionInfo); } template AFX_INLINE void CXTPSubscriptionList::OnUnsubscribed( CXTPObservable* pObservable) { POSITION pos = m_Subscriptions.GetHeadPosition(); while (NULL != pos) { POSITION oldPos = pos; SubscriptionInfo& subscription = m_Subscriptions.GetNext(pos); if (!subscription.bMarkedUnsubscribed && subscription.pObservable == pObservable) { if (!m_bBeingDestructed) { m_Subscriptions.RemoveAt(oldPos); } else { subscription.bMarkedUnsubscribed = TRUE; } } } } template AFX_INLINE CXTPObservable::CXTPObservable() : m_nNotificationDepth(0) { } template AFX_INLINE CXTPObservable::~CXTPObservable() { _ASSERTE("All observers must be unsubscribed before destruction" && 0 == m_Observers.GetSize()); } template AFX_INLINE void CXTPObservable::Subscribe( Observer* pObserver, CXTPSubscriptionList* pSubcriptionList /*= NULL*/) { _ASSERTE(NULL != pObserver); if (FindObserver(pObserver) == -1) { ObserverInfo observerInfo = { pObserver, FALSE, pSubcriptionList }; m_Observers.Add(observerInfo); if (NULL != pSubcriptionList) { pSubcriptionList->OnSubscribed(this); } } } template AFX_INLINE void CXTPObservable::Unsubscribe(Observer* pObserver) { INT_PTR nIndex = FindObserver(pObserver); if (0 <= nIndex) { if (0 == m_nNotificationDepth) { RemoveObserver(nIndex); } else { _ASSERTE(0 < m_nNotificationDepth); m_Observers[nIndex].bRemove = TRUE; } } } template AFX_INLINE INT_PTR CXTPObservable::FindObserver(Observer* pObserver) const { _ASSERTE(NULL != pObserver); INT_PTR nIndex = -1; for (INT_PTR i = 0; i < m_Observers.GetSize(); ++i) { if (m_Observers[i].pObserver == pObserver) { nIndex = i; break; } } return nIndex; } template AFX_INLINE void CXTPObservable::OnBeforeNotify() { ++m_nNotificationDepth; } template AFX_INLINE void CXTPObservable::OnAfterNotify() { if (0 == --m_nNotificationDepth) { CArray indices; INT_PTR i; for (i = 0; i < m_Observers.GetSize(); ++i) { if (m_Observers[i].bRemove) { indices.Add(i); } } for (i = indices.GetSize(); 0 < i; --i) { RemoveObserver(indices[i - 1]); } } _ASSERTE(0 <= m_nNotificationDepth); } template AFX_INLINE void CXTPObservable::RemoveObserver(INT_PTR nIndex) { _ASSERTE(nIndex < m_Observers.GetSize()); ObserverInfo& observerInfo = m_Observers.ElementAt(nIndex); if (NULL != observerInfo.pSubcriptionList) { observerInfo.pSubcriptionList->OnUnsubscribed(this); } m_Observers.RemoveAt(nIndex); } /** * @brief * Call this function to determine if the class specified by pClassThis * is derived from the class specified in the pBaseClass parameter. * Unlike CRuntimeClass::IsDerivedFrom, this function compares actual * class information which allows using it for comparison of the * classes declared in different physical modules. * @param pBaseClass Base class information pointer. * @param pClassThis Derived class information pointer. * @return * TRUE if the derived class has the same base class as its parent. * @see * XTP_DYNAMIC_DOWNCAST_REMOTE,XTPDynamicDownCastRemote,XTPIsKindOfRemote */ _XTP_EXT_CLASS BOOL AFX_CDECL XTPIsDerivedFromRemote(const CRuntimeClass* pBaseClass, const CRuntimeClass* pClassThis); /** * @brief * Tests this object's relationship to a given class. * Unlike CObject::IsKindOf, this function compares actual * class information which allows using it for comparison of the * classes declared in different physical modules. * @param pClass Class information pointer. * @param pObject Derived class object pointer. * @return * TRUE if the object corresponds to the class, otherwise FALSE. * @see * XTP_DYNAMIC_DOWNCAST_REMOTE,XTPDynamicDownCastRemote,XTPIsDerivedFromRemote */ _XTP_EXT_CLASS BOOL AFX_CDECL XTPIsKindOfRemote(const CRuntimeClass* pClass, const CObject* pObject); /** * @brief * Provides a handy way to cast a pointer to a pointer to a class object * while checking to see if the cast is legal. Unlike AfxDynamicDowncast, * this function compares actual class information which allows using it * for casting of the classes declared in different physical modules. * @param pClass Class information pointer. * @param pObject Derived class object pointer. * @return * If the object referenced by the pointer is a "kind of" the identified class, * then the function returns the appropriate pointer. If it is not a legal cast, * then the function returns NULL. * @see * XTP_DYNAMIC_DOWNCAST_REMOTE,XTPIsKindOfRemote,XTPIsDerivedFromRemote */ _XTP_EXT_CLASS CObject* AFX_CDECL XTPDynamicDownCastRemote(CRuntimeClass* pClass, CObject* pObject); /** * @brief * Provides a handy way to cast a pointer to a pointer to a class object * while checking to see if the cast is legal. Unlike DYNAMIC_DOWNCAST, * this macro compares actual class information which allows using it * for casting of the classes declared in different physical modules. * @param className Class name to which an object is to be casted. * @param pObject Derived class object pointer. * @return * If the object referenced by the pointer is a "kind of" the identified class, * then the macro returns the appropriate pointer. If it is not a legal cast, * then the macro returns NULL. * @see * XTPDynamicDownCastRemote,XTPIsKindOfRemote,XTPIsDerivedFromRemote */ # define XTP_DYNAMIC_DOWNCAST_REMOTE(className, pObject) \ static_cast(XTPDynamicDownCastRemote(RUNTIME_CLASS(className), pObject)) /** @cond */ # ifdef _XTP_ACTIVEX # define XTP_DYNAMIC_DOWNCAST_REMOTE_ XTP_DYNAMIC_DOWNCAST_REMOTE # else # define XTP_DYNAMIC_DOWNCAST_REMOTE_ DYNAMIC_DOWNCAST # endif /** @endcond */ /** * @brief * Perform a shallow comparison of two variants. Value objects and strings get compared in full, * while object references, arrays and vectors compared only by their reference values. * @param v1 The first variant object to compare. * @param v2 The second variant object to compare. * @return TRUE if provided variant objects are identical, FALSE otherwise. */ _XTP_EXT_CLASS BOOL AFX_CDECL XTPVariantEqual(const VARIANT& v1, const VARIANT& v2); /** * @brief * Attempts to parse a floating point value from the beginning of the provided string. * @param pStr String pointer to parse a floating point value from. * @param pEndPos An optional pointer to a value that receives the character position after the last * parsed character in the source string. * @return A parsed floating point value or XTP_NAN in case of an error. */ _XTP_EXT_CLASS double XTPParseDouble(LPCSTR pStr, int* pEndPos = NULL); /** * @copydoc XTPParseDouble(LPCSTR, SIZE_T*) */ _XTP_EXT_CLASS double XTPParseDouble(LPCWSTR pStr, int* pEndPos = NULL); /** * @brief * CXTPNonClientMetrics is a self-initializing NONCLIENTMETRICS derived * class. It contains the scalable metrics associated with the * non-client area of a non-minimized window. This class is used by * the SPI_GETNONCLIENTMETRICS and SPI_SETNONCLIENTMETRICS actions of * SystemParametersInfo. * * Example: * The following example demonstrates using CXTPNonClientMetrics. *
 * CXTPLogFont lfMenuFont;
 * CXTPNonClientMetrics ncm;
 *
 * lfMenuFont.lfCharSet = (BYTE)GetTextCharsetInfo (dc, NULL, 0);
 * lfMenuFont.lfHeight  = ncm.lfMenuFont.lfHeight;
 * lfMenuFont.lfWeight  = ncm.lfMenuFont.lfWeight;
 * lfMenuFont.lfItalic  = ncm.lfMenuFont.lfItalic;
 *
 * STRCPY_S(lfMenuFont.lfFaceName, LF_FACESIZE, ncm.lfMenuFont.lfFaceName);
 * 
*/ class _XTP_EXT_CLASS CXTPNonClientMetrics : public NONCLIENTMETRICS { public: /** * @brief * Constructs a CXTPNonClientMetrics object. */ CXTPNonClientMetrics(); }; /** * @brief * A wrapper around the Toolhelp32 API. The API is loaded dynamically * and IsInitialized can be used for checking if the API is supported. * Refer to Platform SDK documentation on Toolhelp32 API details. */ class _XTP_EXT_CLASS CXTPToolhelpApi { friend class CXTPSingleton; public: /** * @return * Obtains the only global class instance. */ static CXTPToolhelpApi& AFX_CDECL Instance(); /** * @brief * The method should be used for checking if the Toolhelp32 API * is supported and can be used. * @return * TRUE if the Toolhelp32 API is supported and can be used. */ BOOL IsInitialized() const; /** * @brief * Takes a snapshot of the specified processes, as well as the heaps, * modules, and threads used by these processes. * @param dwFlags The portions of the system to be included in the snapshot. * @param th32ProcessID The process identifier of the process to be included * in the snapshot. * @return * If the function succeeds, it returns an open handle to the specified * snapshot. Otherwise, the result value is INVALID_HANDLE_VALUE. */ HANDLE CreateSnapshot(DWORD dwFlags, DWORD th32ProcessID); /** * @brief * Retrieves information about the first thread of any process * encountered in a system snapshot. * @param hSnapshot A handle to the snapshot returned from a previous call * to the CreateToolhelp32Snapshot function. * @param lpte A pointer to a THREADENTRY32 structure. * @return * TRUE if the first entry of the thread list has been copied * to the buffer, otherwise FALSE. * @see * GetNextThread */ BOOL GetFirstThread(HANDLE hSnapshot, LPTHREADENTRY32 lpte); /** * @brief * Retrieves information about the next thread of any process encountered * in the system memory snapshot. * @param hSnapshot A handle to the snapshot returned from a previous call * to the CreateToolhelp32Snapshot function. * @param lpte A pointer to a THREADENTRY32 structure. * @return * TRUE if the next entry of the thread list has been copied * to the buffer, otherwise FALSE. * @see * GetFirstThread */ BOOL GetNextThread(HANDLE hSnapshot, LPTHREADENTRY32 lpte); /** * @brief * Retrieves information about the first module associated with a process. * @param hSnapshot A handle to the snapshot returned from a previous call * to the CreateToolhelp32Snapshot function. * @param lpme A pointer to a MODULEENTRY32 structure. * @return * TRUE if the first entry of the module list has been copied * to the buffer, otherwise FALSE. * @see * GetNextModule */ BOOL GetFirstModule(HANDLE hSnapshot, LPMODULEENTRY32 lpme); /** * @brief * Retrieves information about the next module associated with a process * or thread. * @param hSnapshot A handle to the snapshot returned from a previous call * to the CreateToolhelp32Snapshot function. * @param lpme A pointer to a MODULEENTRY32 structure. * @return * TRUE if the next entry of the module list has been copied * to the buffer, otherwise FALSE. * @see * GetFirstModule */ BOOL GetNextModule(HANDLE hSnapshot, LPMODULEENTRY32 lpme); private: typedef HANDLE(WINAPI* PFNCREATETOOLHELP32SNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID); typedef BOOL(WINAPI* PFNTHREAD32FIRSTNEXT)(HANDLE hSnapshot, LPTHREADENTRY32 lpte); typedef BOOL(WINAPI* PFNMODULE32FIRSTNEXT)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); CXTPToolhelpApi(); ~CXTPToolhelpApi(); BOOL m_bInitialized; PFNCREATETOOLHELP32SNAPSHOT m_pfnCreateToolhelp32Snapshot; PFNTHREAD32FIRSTNEXT m_pfnThread32First; PFNTHREAD32FIRSTNEXT m_pfnThread32Next; PFNMODULE32FIRSTNEXT m_pfnModule32First; PFNMODULE32FIRSTNEXT m_pfnModule32Next; }; AFX_INLINE BOOL CXTPToolhelpApi::IsInitialized() const { return m_bInitialized; } /** * @brief * A helper class for handling a global atom primitive. */ class _XTP_EXT_CLASS CXTPGlobalAtom { public: /** * @brief * Creates a global atom object using the provided name. If an atom * with such a name already exists, then its reference counter * will be incremented. * @param lpAtomName An atom name string. */ explicit CXTPGlobalAtom(LPCTSTR lpAtomName); /** * @brief * Handles global atom destruction. Atom reference counter gets decremented * and will be destroyed if it reaches zero. */ ~CXTPGlobalAtom(); /** * @brief * Obtains atom value. * @return * Atom value. */ ATOM GetAtom() const; /** * @brief * Obtains atom value as a string pointer. * @return * Atom value as a string pointer. The value must not be used for string * operations except where permitted by SDK documentation. */ LPCTSTR GetAtomString() const; /** * @brief * Obtains atom name. * @return * Atom name string. */ const CString& GetName() const; private: ATOM m_atom; CString m_strName; }; /** @cond */ AFX_INLINE ATOM CXTPGlobalAtom::GetAtom() const { return m_atom; } AFX_INLINE LPCTSTR CXTPGlobalAtom::GetAtomString() const { return MAKEINTATOM(m_atom); } AFX_INLINE const CString& CXTPGlobalAtom::GetName() const { return m_strName; } /** @endcond */ # include "Common/Base/Diagnostic/XTPEnableNoisyWarnings.h" /** @cond */ #endif // !defined(__XTPSYSTEMHELPERS_H__) /** @endcond */