/** * @file XTPGdiObjects.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(__XTPGDIOBJECTCACHE_H__) # define __XTPGDIOBJECTCACHE_H__ /** @endcond */ # if _MSC_VER > 1000 # pragma once # endif // _MSC_VER > 1000 # include "Common/Base/Diagnostic/XTPDisableNoisyWarnings.h" /** @cond */ /** * Enable this in Debug mode and re-build ToolkitPro only for tracking unauthorized cached object * changes. * #define XTP_ENABLE_UNAUTHORIZED_CACHED_GDI_OBJECT_CHANGE_FAULT */ # ifndef XTP_DISABLE_DEPRECATE_GDI_MEMBER # define XTP_DEPRECATE_GDI_MEMBER_IN_FAVOR_OF(memberName, inFavorOf) \ _XTP_DEPRECATE("The member '" #memberName \ "' has been deprecated, using it may lead to undefined behavior. " \ "Use '" #inFavorOf \ "' instead. You can disable this message by defining " \ "XTP_DISABLE_DEPRECATE_GDI_MEMBER globally.") # else # define XTP_DEPRECATE_GDI_MEMBER_IN_FAVOR_OF(what) # endif # define XTP_SUBSTITUTE_GDI_MEMBER_WITH_CACHED_(oldClass, oldClassRef, oldClassCRef, \ oldMemberName, cachedMemberName, \ handleGetterName) \ XTP_DEPRECATE_GDI_MEMBER_IN_FAVOR_OF(oldMemberName, cachedMemberName) \ AFX_INLINE oldClassRef handleGetterName() \ { \ return *cachedMemberName.GetNativeGdiObject(); \ } \ XTP_DEPRECATE_GDI_MEMBER_IN_FAVOR_OF(oldMemberName, cachedMemberName) \ AFX_INLINE oldClassCRef handleGetterName() const \ { \ return *cachedMemberName.GetNativeGdiObject(); \ } \ __declspec(property(get = handleGetterName)) oldClassRef oldMemberName; # define XTP_SUBSTITUTE_GDI_MEMBER_WITH_CACHED(oldClass, oldMemberName, cachedMemberName, \ handleGetterName) \ XTP_SUBSTITUTE_GDI_MEMBER_WITH_CACHED_(oldClass, oldClass&, const oldClass&, \ oldMemberName, cachedMemberName, handleGetterName) template class CXTPGdiObjectPtrProxy; class CXTPCachedGdiObjectReferenceBase; template class CXTPCachedGdiObjectReference; class CXTPFont; class CXTPGdiObject; class CXTPGdiObjectCacheBase; template class CXTPGdiObjectPtrProxy { public: operator XtpObject*(); operator const XtpObject*() const; operator GdiObject*(); operator const GdiObject*() const; XtpObject& operator*(); const XtpObject& operator*() const; private: friend class CXTPFont; friend class CXTPBrush; friend class CXTPPen; friend class CXTPImageList; explicit CXTPGdiObjectPtrProxy(XtpObject* object); XtpObject* m_pObject; }; template AFX_INLINE CXTPGdiObjectPtrProxy::CXTPGdiObjectPtrProxy(XtpObject* pObject) : m_pObject(pObject) { } template AFX_INLINE CXTPGdiObjectPtrProxy::operator XtpObject*() { return m_pObject; } template AFX_INLINE CXTPGdiObjectPtrProxy::operator const XtpObject*() const { return m_pObject; } template AFX_INLINE CXTPGdiObjectPtrProxy::operator GdiObject*() { return m_pObject->GetNativeGdiObject(); } template AFX_INLINE CXTPGdiObjectPtrProxy::operator const GdiObject*() const { return m_pObject->GetNativeGdiObject(); } template AFX_INLINE XtpObject& CXTPGdiObjectPtrProxy::operator*() { return *m_pObject; } template AFX_INLINE const XtpObject& CXTPGdiObjectPtrProxy::operator*() const { return *m_pObject; } struct XTPGDIDESCRIPTOR; /** @endcond */ /** * @brief * Implements common functionality for all XTP GDI object. Mimics * CGdiObject's interface from MFC however cannot be cast to * CGdiObject type. * @details * XTP GDI objects use cached GDI handles so one native GDI handle can be * shared across several XTP GDI object instances. The lifetime of a handle * is controlled by XTP GDI reference counter, meaning a handle is deleted * only when the last XTP GDI object that references a particular handle is * destroyed or DeleteObject is called. * Note, because an encapsulated GDI handle is cached and shared, passing * m_hObject to DeleteObject from Windows SDK or convering an XTP GDI * object to CGdiObject& and making a call to CGdiObject::DeleteObject * will delete a cached handle and leave all XTP GDI object that reference * the delete handle in an undetermined state. This will also affect every * place in a program where the cached handles are used. So use the encapsulated * GDI handle or CGdiObject very carefully and for read-only purposes. * @see * CXTPFont, CXTPBrush, CXTPPen */ class _XTP_EXT_CLASS CXTPGdiObject : public CObject { DECLARE_DYNAMIC(CXTPGdiObject); protected: /** * @brief * Performs internal CXTPGdiObject construction logic. */ CXTPGdiObject(); public: /** * @brief * Handles CXTPGdiObject destruction. Makes a call to DeleteObject * if it has not been done prior to object destruction. */ virtual ~CXTPGdiObject() = 0; /** * @brief * Casts an object to an encapsulated GDI handle. * @details * The returned handle must not be passed to DeleteObject * and should be used for read-only purposes, i.e. GDI object * state should not be modified as it will affect every place * in a program where the cached hande is used. * @return * Encapsulated GDI handle or NULL. */ operator HGDIOBJ() const; /** * @brief * Returns m_hObject unless this is NULL, in which case NULL is returned. * @details * The returned handle must not be passed to DeleteObject * and should be used for read-only purposes, i.e. GDI object * state should not be modified as it will affect every place * in a program where the cached handle is used. * @return * Encapsulated GDI handle or NULL. */ HGDIOBJ GetSafeHandle() const; /** * @brief * Decrements reference counter for a cached GDI object or delete * the cached GDI object once the reference counter is equal to zero. * @return * TRUE if the reference counter is decremented without deleting * a cached GDI object or the GDI object is deleted successfully. */ BOOL DeleteObject(); # pragma push_macro("GetObject") # undef GetObject /** * @brief * Fills a buffer with data that defines a specified object. * @param nCount Specifies the number of bytes to copy into the lpObject buffer. * @param lpObject Points to a user supplied buffer that is to receive the information. * @return * The number of bytes retrieved; otherwise 0 if an error occurs. */ int GetObject(int nCount, LPVOID lpObject) const; # pragma pop_macro("GetObject") /** * @brief * Retrieves the type of the GDI object. * @return * The type of the object, if successful; otherwise 0. Refer to * the Platform SDK documentation for the list of possible values * returned. */ UINT GetObjectType() const; /** * @brief * Retrieves a handle to one of the predefined stock Windows GDI pens, * brushes, or fonts, and attaches the GDI object to the CGdiObject object. * @param nIndex A constant specifying the type of stock object desired. Refer to * the Platform SDK documentation for the list of possible values. * @return * Nonzero if the function is successful; otherwise 0. * @details * Stock objects don't get cached and its handle becomes associated * with one and only one instance of CXTPGdiObject or its derived class. */ BOOL CreateStockObject(int nIndex); /** * @brief * Determines if two GDI objects are logically equal. * @param obj A reference to the other CXTPGdiObject instance to compare to. * @return * TRUE if the encapsulated GDI objects are logically equal (handles * are the same) or FALSE otherwise. */ BOOL operator==(const CXTPGdiObject& obj) const; /** * @brief * Determines if two GDI objects are logically not equal. * @param obj A reference to the other CXTPGdiObject instance to compare to. * @return * TRUE if the encapsulated GDI objects are logically not equal (handles * are not the same) or FALSE otherwise. */ BOOL operator!=(const CXTPGdiObject& obj) const; /** * @brief * Converts an object to CGdiObject reference making it possible * to use CXTPGdiObject with MFC classes and methods that use CGdiObject * reference as an argument. * @return * An encapsulated CGdiObject reference. * @details * The returned object must not be deleted or modified as it will affect * every place in a program where the cached handle is used. */ operator CGdiObject&(); /** * @brief * Converts an object to CGdiObject constance reference making it possible * to use CXTPGdiObject with MFC classes and methods that use CGdiObject * reference as an argument. * @return * An encapsulated CGdiObject constant reference. */ operator const CGdiObject&() const; /** * @brief * A read-only encapsulated GDI handle value. * @details * The returned handle must not be passed to DeleteObject * and should be used for read-only purposes, i.e. GDI object * state should not be modified as it will affect every place * in a program where the cached handle is used. * @return * Encapsulated GDI handle or NULL. */ __declspec(property(get = GetSafeHandle)) HGDIOBJ m_hObject; /** * @brief * Sets handle ownership guaranteed status. Guaranteed * ownership implies full control over the cached encapsulated handle and thus * guarantees that the handle is properly detached from a device context * before being deleted. Non-guaranteed ownership can be set in scenarios * when a handle is being passed to any API thay may or may not detach it * from a device context. By default guaranteed ownership is implied. * This status is used only as a diagnostic hint and does not provide any * functional advantage. Changing this status affects all GDI object that * use the same cached handle. */ void SetHandleOwnershipNotGuaranteed(); /** * @brief * Determines handle ownership guaranteed status. Guaranteed * ownership implies full control over the cached encapsulated handle and thus * guarantees that the handle is properly detached from a device context * before being deleted. Non-guaranteed ownership can be set in scenarios * when a handle is being passed to any API thay may or may not detach it * from a device context. By default guaranteed ownership is implied. * This status is used only as a diagnostic hint and does not provide any * functional advantage. Changing this status affects all GDI object that * use the same cached handle. * @return * TRUE if handle ownership is guaranteed. */ BOOL IsHandleOwnershipGuaranteed() const; protected: /** @cond */ CGdiObject* GetGdiObject(); const CGdiObject* GetGdiObject() const; void SetDummyGdiObject(CGdiObject& gdiObject); void SetCachedObject(CXTPCachedGdiObjectReferenceBase* pCachedObject); virtual XTPGDIDESCRIPTOR& AccessDescriptorData() = 0; const XTPGDIDESCRIPTOR& AccessDescriptorData() const; void* GetDescriptor() const; /** @endcond */ private: CXTPCachedGdiObjectReferenceBase* m_pCachedObject; CGdiObject* m_pDummyGdiObject; BOOL m_bHandleOwnershipViolated; # ifdef _DEBUG HGDIOBJ m_hDummyGdiObject; void AssertDummyUnaltered() const; # endif }; /** @cond */ AFX_INLINE const CGdiObject* CXTPGdiObject::GetGdiObject() const { return const_cast(this)->GetGdiObject(); } AFX_INLINE CXTPGdiObject::operator CGdiObject&() { return *GetGdiObject(); } AFX_INLINE CXTPGdiObject::operator const CGdiObject&() const { return *GetGdiObject(); } AFX_INLINE const XTPGDIDESCRIPTOR& CXTPGdiObject::AccessDescriptorData() const { return const_cast(this)->AccessDescriptorData(); } /** @endcond */ /** * @brief * Provides a convenient object oriented interface for HFONT GDI object * and uses GDI handle caching. Mimics CFont's interface from MFC however * cannot be cast to CFont or CGdiObject types. * @details * XTP GDI objects use cached GDI handles so one native GDI handle can be * shared across several XTP GDI object instances. The lifetime of a handle * is controlled by XTP GDI reference counter, meaning a handle is deleted * only when the last XTP GDI object that references a particular handle is * destroyed or DeleteObject is called. * Note, because an encapsulated GDI handle is cached and shared, passing * m_hObject to DeleteObject from Windows SDK or convering an XTP GDI * object to CGdiObject& and making a call to CGdiObject::DeleteObject * will delete a cached handle and leave all XTP GDI object that reference * the delete handle in an undetermined state. This will also affect every * place in a program where the cached handles are used. So use the encapsulated * GDI handle or CGdiObject very carefully and for read-only purposes. * @see * CXTPGdiObject, CXTPBrush, CXTPPen */ class _XTP_EXT_CLASS CXTPFont : public CXTPGdiObject { DECLARE_DYNAMIC(CXTPFont); public: /** @cond */ typedef CXTPGdiObjectPtrProxy XTPFontPtrProxy; /** @endcond */ /** * @brief * Constructs empty CXTPFont object. */ CXTPFont(); /** * @brief * Handles CXTPFont object destruction. */ ~CXTPFont(); /** * @brief * Initializes a CFont object with the characteristics given in a * LOGFONTstructure. * @param lpLogFont Points to a LOGFONT structure that defines the * characteristics of the logical font. * @return * Nonzero if successful; otherwise 0. * @details * If the requested font has already been created from another * CXTPFont instance and not yet deleted the same font will be re-used * and its reference counter will be incremented. */ BOOL CreateFontIndirect(const LOGFONT* lpLogFont); /** * @brief * Initializes a CFont object with the specified characteristics. * @param nHeight Specifies the desired height(in logical units) of the font. * @param nWidth Specifies the average width(in logical units) of characters in the * font. * @param nEscapement Specifies the angle(in 0.1 degree units) between the * escapement vector and the x axis of the display surface. * @param nOrientation Specifies the angle(in 0.1 degree units) between the * baseline of a character and the x axis. * @param nWeight Specifies the font weight(in inked pixels per 1000). * @param bItalic Specifies whether the font is italic. * @param bUnderline Specifies whether the font is underlined. * @param cStrikeOut Specifies whether characters in the font are struck out. * @param nCharSet Specifies the font's character set. * @param nOutPrecision Specifies the desired output precision. * @param nClipPrecision Specifies the desired clipping precision. * @param nQuality Specifies the font's output quality. * @param nPitchAndFamily Specifies the pitch and family of the font. * @param lpszFacename A CString or pointer to a null terminated string that * specifies the typeface name of the font. * @return * Nonzero if successful; otherwise 0. * @details * If the requested font has already been created from another * CXTPFont instance and not yet deleted the same font will be re-used * and its reference counter will be incremented. */ BOOL CreateFont(int nHeight, int nWidth, int nEscapement, int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline, BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision, BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily, LPCTSTR lpszFacename); /** * @brief * This function provides a simple way to create a font of a specified * typeface and point size. * @param nPointSize Requested font height in tenths of a point. * @param lpszFaceName A CString or pointer to a null terminated string * that specifies the typeface name of the font. * @param pDC Pointer to the CDC object to be used to convert the height in * nPointSize to logical units. * @return * Nonzero if successful, otherwise 0. * @details * If the requested font has already been created from another * CXTPFont instance and not yet deleted the same font will be re-used * and its reference counter will be incremented. */ BOOL CreatePointFont(int nPointSize, LPCTSTR lpszFaceName, CDC* pDC = NULL); /** * @brief * This function is the same as CreateFontIndirect except that the lfHeight * member of the LOGFONT is interpreted in tenths of a point rather than device units. * @param lpLogFont Points to a LOGFONT structure that defines the * characteristics of the logical font. * @param pDC Pointer to the CDC object to be used to convert the height * in lfHeight to logical units. * @return * Nonzero if successful, otherwise 0. * @details * If the requested font has already been created from another * CXTPFont instance and not yet deleted the same font will be re-used * and its reference counter will be incremented. */ BOOL CreatePointFontIndirect(const LOGFONT* lpLogFont, CDC* pDC = NULL); /** * @brief * Call this function to retrieve a copy of the LOGFONT structure that * describes the encapsulated GDI object. * @param pLogFont Pointer to the LOGFONT structure to receive the font information. * @return * Nonzero if the function succeeds, otherwise 0. */ int GetLogFont(LOGFONT* pLogFont); /** * @brief * Obtains a pointer to the encapsulated GDI object as CFont type. * The returned object must not be deleted or modified as it will affect * every place in a program where the cached handle is used. * @return * A pointer to the encapsulated GDI object as CFont type. */ CFont* GetNativeGdiObject(); /** * @brief * Obtains a pointer to the encapsulated GDI object as CFont type. * The returned object must not be deleted or modified as it will affect * every place in a program where the cached handle is used. * @return * A pointer to the encapsulated GDI object as CFont type. */ const CFont* GetNativeGdiObject() const; /** * @brief * Casts an object to an encapsulated GDI handle. * @details * The returned handle must not be passed to DeleteObject * and should be used for read-only purposes, i.e. GDI object * state should not be modified as it will affect every place * in a program where the cached hande is used. * @return * Encapsulated GDI handle or NULL. */ operator HFONT() const; /** * @brief * Converts an object to CFont reference making it possible * to use CXTPFont with MFC classes and methods that use CFont or * CGdiObject reference as an argument. * @return * An encapsulated CFont reference. * @details * The returned object must not be deleted or modified as it will affect * every place in a program where the cached handle is used. */ operator CFont&(); /** * @brief * Converts an object to CFont reference making it possible * to use CXTPFont with MFC classes and methods that use CFont or * CGdiObject constant reference as an argument. * @return * An encapsulated CFont constance reference. */ operator const CFont&() const; /** @cond */ XTPFontPtrProxy operator&(); const XTPFontPtrProxy operator&() const; /** @endcond */ private: virtual XTPGDIDESCRIPTOR& AccessDescriptorData(); CFont m_dummyFont; HGDIOBJ m_hLogFontHandle; LOGFONT m_logFont; }; /** @cond */ AFX_INLINE CFont* CXTPFont::GetNativeGdiObject() { return static_cast(GetGdiObject()); } AFX_INLINE const CFont* CXTPFont::GetNativeGdiObject() const { return const_cast(this)->GetNativeGdiObject(); } AFX_INLINE CXTPFont::operator HFONT() const { return reinterpret_cast(GetSafeHandle()); } AFX_INLINE CXTPFont::operator CFont&() { return *GetNativeGdiObject(); } AFX_INLINE CXTPFont::operator const CFont&() const { return *GetNativeGdiObject(); } AFX_INLINE CXTPFont::XTPFontPtrProxy CXTPFont::operator&() { return XTPFontPtrProxy(this); } AFX_INLINE const CXTPFont::XTPFontPtrProxy CXTPFont::operator&() const { return XTPFontPtrProxy(const_cast(this)); } /** @endcond */ /** * @brief * Provides a convenient object oriented interface for HBRUSH GDI object * and uses GDI handle caching. Mimics CBrush's interface from MFC however * cannot be cast to CBrush or CGdiObject types. * @details * XTP GDI objects use cached GDI handles so one native GDI handle can be * shared across several XTP GDI object instances. The lifetime of a handle * is controlled by XTP GDI reference counter, meaning a handle is deleted * only when the last XTP GDI object that references a particular handle is * destroyed or DeleteObject is called. * Note, because an encapsulated GDI handle is cached and shared, passing * m_hObject to DeleteObject from Windows SDK or convering an XTP GDI * object to CGdiObject& and making a call to CGdiObject::DeleteObject * will delete a cached handle and leave all XTP GDI object that reference * the delete handle in an undetermined state. This will also affect every * place in a program where the cached handles are used. So use the encapsulated * GDI handle or CGdiObject very carefully and for read-only purposes. * @see * CXTPGdiObject, CXTPFont, CXTPPen */ class _XTP_EXT_CLASS CXTPBrush : public CXTPGdiObject { DECLARE_DYNAMIC(CXTPBrush); public: /** @cond */ typedef CXTPGdiObjectPtrProxy XTPBrushPtrProxy; /** @endcond */ /** * @brief * Constructs an empty CXTPBrush object. */ CXTPBrush(); /** * @brief * Initializes a brush with a specified solid color. * @param crColor A COLORREF structure that specifies the color of the brush. * @details * If the requested brush has already been created from another * CXTPBrush instance and not yet deleted the same brush will be re-used * and its reference counter will be incremented. */ CXTPBrush(COLORREF crColor); /** * @brief * Initializes a brush with the specified hatched pattern and color. * @param nIndex Specifies the hatch style of the brush. * @param crColor A COLORREF structure that specifies the color of the brush. * @details * If the requested brush has already been created from another * CXTPBrush instance and not yet deleted the same brush will be re-used * and its reference counter will be incremented. */ CXTPBrush(int nIndex, COLORREF crColor); /** * @brief * Initializes a brush with a pattern specified by a bitmap. * @param pBitmap Pattern bitmap pointer. * @details * If the requested brush has already been created from another * CXTPBrush instance and not yet deleted the same brush will be re-used * and its reference counter will be incremented. */ CXTPBrush(CBitmap* pBitmap); /** * @brief * Handles CXTPBrush object destruction. */ ~CXTPBrush(); /** * @brief * Initializes a brush with a specified solid color. * @param crColor A COLORREF structure that specifies the color of the brush. * @return * Nonzero if successful; otherwise 0. * @details * If the requested brush has already been created from another * CXTPBrush instance and not yet deleted the same brush will be re-used * and its reference counter will be incremented. */ BOOL CreateSolidBrush(COLORREF crColor); /** * @brief * Initializes a brush with the specified hatched pattern and color. * @param nIndex Specifies the hatch style of the brush. * @param crColor A COLORREF structure that specifies the color of the brush. * @return * Nonzero if successful; otherwise 0. * @details * If the requested brush has already been created from another * CXTPBrush instance and not yet deleted the same brush will be re-used * and its reference counter will be incremented. */ BOOL CreateHatchBrush(int nIndex, COLORREF crColor); /** * @brief * Initializes a brush with a style, color, and pattern specified in * a LOGBRUSH structure. * @param lpLogBrush Points to a LOGBRUSH structure that contains * information about the brush. * @return * Nonzero if successful; otherwise 0. * @details * If the requested brush has already been created from another * CXTPBrush instance and not yet deleted the same brush will be re-used * and its reference counter will be incremented. */ BOOL CreateBrushIndirect(const LOGBRUSH* lpLogBrush); /** * @brief * Initializes a brush with a pattern specified by a bitmap. * @param pBitmap Pattern bitmap pointer. * @return * Nonzero if successful; otherwise 0. * @details * If the requested brush has already been created from another * CXTPBrush instance and not yet deleted the same brush will be re-used * and its reference counter will be incremented. */ BOOL CreatePatternBrush(CBitmap* pBitmap); /** * @brief * Initializes a brush with the pattern specified by a device-independent bitmap (DIB). * @param hPackedDIB Identifies a global memory object containing a * packed device independent bitmap(DIB). * @param nUsage Specifies whether the bmiColors[] fields of the BITMAPINFO * data structure(a part of the "packed DIB") contain explicit * RGB values or indices into the currently realized logical palette. * @return * Nonzero if successful; otherwise 0. * @details * If the requested brush has already been created from another * CXTPBrush instance and not yet deleted the same brush will be re-used * and its reference counter will be incremented. */ BOOL CreateDIBPatternBrush(HGLOBAL hPackedDIB, UINT nUsage); /** * @brief * Initializes a brush with the pattern specified by a device-independent bitmap (DIB). * @param lpPackedDIB Points to a packed DIB consisting of a BITMAPINFO * structure immediately followed by an array of bytes * defining the pixels of the bitmap. * @param nUsage Specifies whether the bmiColors[] fields of the BITMAPINFO * data structure(a part of the "packed DIB") contain explicit * RGB values or indices into the currently realized logical palette. * @return * Nonzero if successful; otherwise 0. * @details * If the requested brush has already been created from another * CXTPBrush instance and not yet deleted the same brush will be re-used * and its reference counter will be incremented. */ BOOL CreateDIBPatternBrush(const void* lpPackedDIB, UINT nUsage); /** * @brief * Initializes a brush with a system color. * @param nIndex Specifies a color index. * @return * Nonzero if successful; otherwise 0. * @details * If the requested brush has already been created from another * CXTPBrush instance and not yet deleted the same brush will be re-used * and its reference counter will be incremented. */ BOOL CreateSysColorBrush(int nIndex); /** * @brief * Call this function to retrieve a copy of the LOGBRUSH structure that * describes the encapsulated GDI object. * @param pLogBrush Pointer to the LOGBRUSH structure to receive the brush information. * @return * Nonzero if the function succeeds, otherwise 0. */ int GetLogBrush(LOGBRUSH* pLogBrush); /** * @brief * Obtains a pointer to the encapsulated GDI object as CBrush type. * The returned object must not be deleted or modified as it will affect * every place in a program where the cached handle is used. * @return * A pointer to the encapsulated GDI object as CBrush type. */ CBrush* GetNativeGdiObject(); /** * @brief * Obtains a pointer to the encapsulated GDI object as CBrush type. * The returned object must not be deleted or modified as it will affect * every place in a program where the cached handle is used. * @return * A pointer to the encapsulated GDI object as CBrush type. */ const CBrush* GetNativeGdiObject() const; /** * @brief * Casts an object to an encapsulated GDI handle. * @details * The returned handle must not be passed to DeleteObject * and should be used for read-only purposes, i.e. GDI object * state should not be modified as it will affect every place * in a program where the cached hande is used. * @return * Encapsulated GDI handle or NULL. */ operator HBRUSH() const; /** * @brief * Converts an object to CBrush reference making it possible * to use CXTPBrush with MFC classes and methods that use CBrush or * CGdiObject reference as an argument. * @return * An encapsulated CBrush reference. * @details * The returned object must not be deleted or modified as it will affect * every place in a program where the cached handle is used. */ operator CBrush&(); /** * @brief * Converts an object to CBrush constant reference making it possible * to use CXTPBrush with MFC classes and methods that use CBrush or * CGdiObject constant reference as an argument. * @return * An encapsulated CBrush constant reference. * @details * The returned object must not be deleted or modified as it will affect * every place in a program where the cached handle is used. */ operator const CBrush&() const; /** @cond */ XTPBrushPtrProxy operator&(); const XTPBrushPtrProxy operator&() const; /** @endcond */ private: virtual XTPGDIDESCRIPTOR& AccessDescriptorData(); CBrush m_dummyBrush; HGDIOBJ m_hLogBrushHandle; LOGBRUSH m_logBrush; }; /** @cond */ AFX_INLINE CBrush* CXTPBrush::GetNativeGdiObject() { return static_cast(GetGdiObject()); } AFX_INLINE const CBrush* CXTPBrush::GetNativeGdiObject() const { return const_cast(this)->GetNativeGdiObject(); } AFX_INLINE CXTPBrush::operator HBRUSH() const { return reinterpret_cast(GetSafeHandle()); } AFX_INLINE CXTPBrush::operator CBrush&() { return *GetNativeGdiObject(); } AFX_INLINE CXTPBrush::operator const CBrush&() const { return *GetNativeGdiObject(); } AFX_INLINE CXTPBrush::XTPBrushPtrProxy CXTPBrush::operator&() { return XTPBrushPtrProxy(this); } AFX_INLINE const CXTPBrush::XTPBrushPtrProxy CXTPBrush::operator&() const { return XTPBrushPtrProxy(const_cast(this)); } /** @endcond */ /** * @brief * Provides a convenient object oriented interface for HPEN GDI object * and uses GDI handle caching. Mimics CPen's interface from MFC however * cannot be cast to CPen or CGdiObject types. * @details * XTP GDI objects use cached GDI handles so one native GDI handle can be * shared across several XTP GDI object instances. The lifetime of a handle * is controlled by XTP GDI reference counter, meaning a handle is deleted * only when the last XTP GDI object that references a particular handle is * destroyed or DeleteObject is called. * Note, because an encapsulated GDI handle is cached and shared, passing * m_hObject to DeleteObject from Windows SDK or convering an XTP GDI * object to CGdiObject& and making a call to CGdiObject::DeleteObject * will delete a cached handle and leave all XTP GDI object that reference * the delete handle in an undetermined state. This will also affect every * place in a program where the cached handles are used. So use the encapsulated * GDI handle or CGdiObject very carefully and for read-only purposes. * @see * CXTPGdiObject, CXTPFont, CXTPBrush */ class _XTP_EXT_CLASS CXTPPen : public CXTPGdiObject { /** @cond */ DECLARE_DYNAMIC(CXTPPen); /** @endcond */ public: /** @cond */ typedef CXTPGdiObjectPtrProxy XTPPenPtrProxy; /** @endcond */ /** * @brief * Constructs an empty CXTPPen object. */ CXTPPen(); /** * @brief * Constructs a CXTPPen object. * @param nPenStyle Specifies the pen style. * @param nWidth Specifies the width of the pen. * @param crColor Contains an RGB color for the pen. * @details * If the requested pen has already been created from another * CXTPPen instance and not yet deleted the same pen will be re-used * and its reference counter will be incremented. */ CXTPPen(int nPenStyle, int nWidth, COLORREF crColor); /** * @brief * Constructs a CXTPPen object. * @param nPenStyle Specifies the pen style. * @param nWidth Specifies the width of the pen. * @param pLogBrush A pointer to LOGBRUSH structure used differently * depending on pen style. * @param nStyleCount The number of optional style parameters. * @param lpStyle An optional pointer to the array of style parameters. * @details * If the requested pen has already been created from another * CXTPPen instance and not yet deleted the same pen will be re-used * and its reference counter will be incremented. */ CXTPPen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount = 0, const DWORD* lpStyle = NULL); /** * @brief * Handles CXTPPen object destruction. */ ~CXTPPen(); /** * @brief * Creates a pen with specified parameters. * @param nPenStyle Specifies the pen style. * @param nWidth Specifies the width of the pen. * @param crColor Contains an RGB color for the pen. * @return * TRUE if a pen is successfully created. * @details * If the requested pen has already been created from another * CXTPPen instance and not yet deleted the same pen will be re-used * and its reference counter will be incremented. */ BOOL CreatePen(int nPenStyle, int nWidth, COLORREF crColor); /** * @brief * Creates a pen with specified parameters. * @param nPenStyle Specifies the pen style. * @param nWidth Specifies the width of the pen. * @param pLogBrush A pointer to LOGBRUSH structure used differently * depending on pen style. * @param nStyleCount The number of optional style parameters. * @param lpStyle An optional pointer to the array of style parameters. * @return * TRUE if a pen is successfully created. * @details * If the requested pen has already been created from another * CXTPPen instance and not yet deleted the same pen will be re-used * and its reference counter will be incremented. */ BOOL CreatePen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount = 0, const DWORD* lpStyle = NULL); /** * @brief * Creates a pen with specified parameters. * @param lpLogPen A pointer to LOGPEN structu describing a pen * to be created. * @return * TRUE if a pen is successfully created. * @details * If the requested pen has already been created from another * CXTPPen instance and not yet deleted the same pen will be re-used * and its reference counter will be incremented. */ BOOL CreatePenIndirect(LPLOGPEN lpLogPen); /** * @brief * Call this function to retrieve a copy of the LOGPEN structure that * describes the encapsulated GDI object. * @param pLogPen Pointer to the LOGPEN structure to receive the pen information. * @return * Nonzero if the function succeeds, otherwise 0. */ int GetLogPen(LOGPEN* pLogPen); /** * @brief * Call this function to retrieve a copy of the EXTLOGPEN structure that * describes the encapsulated GDI object. * @param pLogPen Pointer to the EXTLOGPEN structure to receive the pen information. * @return * Nonzero if the function succeeds, otherwise 0. */ int GetExtLogPen(EXTLOGPEN* pLogPen); /** * @brief * Obtains a pointer to the encapsulated GDI object as CPen type. * The returned object must not be deleted or modified as it will affect * every place in a program where the cached handle is used. * @return * A pointer to the encapsulated GDI object as CPen type. */ CPen* GetNativeGdiObject(); /** * @brief * Obtains a pointer to the encapsulated GDI object as CPen type. * The returned object must not be deleted or modified as it will affect * every place in a program where the cached handle is used. * @return * A pointer to the encapsulated GDI object as CPen type. */ const CPen* GetNativeGdiObject() const; /** * @brief * Casts an object to an encapsulated GDI handle. * @details * The returned handle must not be passed to DeleteObject * and should be used for read-only purposes, i.e. GDI object * state should not be modified as it will affect every place * in a program where the cached hande is used. * @return * Encapsulated GDI handle or NULL. */ operator HPEN() const; /** * @brief * Converts an object to CPen reference making it possible * to use CXTPPen with MFC classes and methods that use CPen or * CGdiObject reference as an argument. * @return * An encapsulated CPen reference. * @details * The returned object must not be deleted or modified as it will affect * every place in a program where the cached handle is used. */ operator CPen&(); /** * @brief * Converts an object to CPen constant reference making it possible * to use CXTPPen with MFC classes and methods that use CPen or * CGdiObject constant reference as an argument. * @return * An encapsulated CPen constant reference. * @details * The returned object must not be deleted or modified as it will affect * every place in a program where the cached handle is used. */ operator const CPen&() const; /** @cond */ XTPPenPtrProxy operator&(); const XTPPenPtrProxy operator&() const; /** @endcond */ private: virtual XTPGDIDESCRIPTOR& AccessDescriptorData(); CPen m_dummyPen; HGDIOBJ m_hLogPenHandle; LOGPEN m_logPen; }; /** @cond */ AFX_INLINE CPen* CXTPPen::GetNativeGdiObject() { return static_cast(GetGdiObject()); } AFX_INLINE const CPen* CXTPPen::GetNativeGdiObject() const { return const_cast(this)->GetNativeGdiObject(); } AFX_INLINE CXTPPen::operator HPEN() const { return reinterpret_cast(GetSafeHandle()); } AFX_INLINE CXTPPen::operator CPen&() { return *GetNativeGdiObject(); } AFX_INLINE CXTPPen::operator const CPen&() const { return *GetNativeGdiObject(); } AFX_INLINE CXTPPen::XTPPenPtrProxy CXTPPen::operator&() { return XTPPenPtrProxy(this); } AFX_INLINE const CXTPPen::XTPPenPtrProxy CXTPPen::operator&() const { return XTPPenPtrProxy(const_cast(this)); } /** @endcond */ /** @cond */ class CXTPGdiObjectCacheBase : public CObject , public CXTPSynchronized { DECLARE_DYNAMIC(CXTPGdiObjectCacheBase); protected: CXTPGdiObjectCacheBase() { } virtual ~CXTPGdiObjectCacheBase() { } public: virtual void RemoveFromCache(const void* pDescriptor) = 0; }; struct XTPGDIDESCRIPTOR { XTPGDIDESCRIPTOR() : pReference(NULL) , nHandleOwnershipViolatorCount(0) { } CXTPCachedGdiObjectReferenceBase* pReference; LONG nHandleOwnershipViolatorCount; }; struct XTPPENINFO; class CXTPCachedPenReference; template<> UINT AFXAPI HashKey(XTPPENINFO* pPenInfo); template<> BOOL AFXAPI CompareElements(XTPPENINFO* const* pPenInfo1, XTPPENINFO* const* pPenInfo2); class CXTPPenCache : private CXTPGdiObjectCacheBase { DECLARE_DYNAMIC(CXTPPenCache); friend class CXTPSingleton; public: static XTPGDIDESCRIPTOR& AccessDescriptorData(void* pDescriptor); CXTPCachedPenReference* CreatePen(int nPenStyle, int nWidth, COLORREF crColor); CXTPCachedPenReference* CreatePen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount = 0, const DWORD* lpStyle = NULL); CXTPCachedPenReference* CreatePenIndirect(LPLOGPEN lpLogPen); private: CXTPPenCache(); ~CXTPPenCache(); virtual void RemoveFromCache(const void* pDescriptor); friend CXTPPenCache* AFX_CDECL XTPPenCache(); // LPVOID used instead of XTPCachedBrushReference* as a workaround for warning C4786. CMap m_penCache; }; struct XTPLOGBRUSHDESCRIPTOR : XTPGDIDESCRIPTOR { LOGBRUSH logBrush; }; template<> UINT AFXAPI HashKey(const LOGBRUSH& logBrush); template<> BOOL AFXAPI CompareElements(const LOGBRUSH* logBrush1, const LOGBRUSH* logBrush2); class CXTPBrushCache : private CXTPGdiObjectCacheBase { DECLARE_DYNAMIC(CXTPBrushCache); friend class CXTPSingleton; friend class CXTPCachedGdiObjectReference; public: typedef CXTPCachedGdiObjectReference XTPCachedBrushReference; static XTPGDIDESCRIPTOR& AccessDescriptorData(void* pDescriptor); XTPCachedBrushReference* CreateSolidBrush(COLORREF crColor); XTPCachedBrushReference* CreateHatchBrush(int nIndex, COLORREF crColor); XTPCachedBrushReference* CreateBrushIndirect(const LOGBRUSH* lpLogBrush); XTPCachedBrushReference* CreatePatternBrush(CBitmap* pBitmap); XTPCachedBrushReference* CreateDIBPatternBrush(HGLOBAL hPackedDIB, UINT nUsage); XTPCachedBrushReference* CreateDIBPatternBrush(const void* lpPackedDIB, UINT nUsage); XTPCachedBrushReference* CreateSysColorBrush(int nIndex); private: CXTPBrushCache(); ~CXTPBrushCache(); virtual void RemoveFromCache(const void* pDescriptor); friend CXTPBrushCache* AFX_CDECL XTPBrushCache(); // LPVOID used instead of XTPCachedBrushReference* as a workaround for warning C4786. CMap m_brushCache; }; struct XTPLOGFONTDESCRIPTOR : XTPGDIDESCRIPTOR { LOGFONT logFont; }; template<> UINT AFXAPI HashKey(const LOGFONT& logFont); template<> BOOL AFXAPI CompareElements(const LOGFONT* logFont1, const LOGFONT* logFont2); class CXTPFontCache : private CXTPGdiObjectCacheBase { DECLARE_DYNAMIC(CXTPFontCache); friend class CXTPSingleton; friend class CXTPCachedGdiObjectReference; public: typedef CXTPCachedGdiObjectReference XTPCachedFontReference; static XTPGDIDESCRIPTOR& AccessDescriptorData(void* pDescriptor); XTPCachedFontReference* CreateFontIndirect(const LOGFONT* lpLogFont); XTPCachedFontReference* CreateFont(int nHeight, int nWidth, int nEscapement, int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline, BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision, BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily, LPCTSTR lpszFaceName); XTPCachedFontReference* CreatePointFont(int nPointSize, LPCTSTR lpszFaceName, CDC* pDC = NULL); XTPCachedFontReference* CreatePointFontIndirect(const LOGFONT* lpLogFont, CDC* pDC = NULL); private: CXTPFontCache(); ~CXTPFontCache(); virtual void RemoveFromCache(const void* pDescriptor); friend CXTPFontCache* AFX_CDECL XTPFontCache(); // LPVOID used instead of XTPCachedFontReference* as a workaround for warning C4786. CMap m_fontCache; }; /** @endcond */ # include "Common/Base/Diagnostic/XTPEnableNoisyWarnings.h" /** @cond */ #endif /*__XTPGDIOBJECTCACHE_H__*/ /** @endcond */