????? 在許多資料上都說CImage類是基于GDI+的,但是為什么是基于GDI+的呢?
?
???? 因為使用這個類時,并沒有加入#include <gdiplus.h> ,也沒有在程序開始和結束時分別寫GDI+啟動代碼GdiplusStartupInput和結束代碼GdiplusShutdown
使用這個類時,僅僅需要添加頭文件# include<altimage.h>就可以了,比GDI+得使用要簡單一些。
?
?????而CImage 對圖片的處理很類似GDI+ ,其內部是不是封裝了GDI+呢? 幸好,CImage類 是源碼公開的,我們可以研究其源碼,以便加深理解。
?
??? 首先,看看altimage.h頭文件
#ifndef?__ATLIMAGE_H__ ??#define?__ATLIMAGE_H__ ????#pragma?once ????#include?<atldef.h> ??#include?<atlbase.h> ??#include?<atlstr.h> ??#include?<atlsimpcoll.h> ??#include?<atltypes.h> ????#ifndef?_ATL_NO_PRAGMA_WARNINGS ??#pragma?warning?(push) ??#pragma?warning(disable?:?4820)?//?padding?added?after?member ??#endif?//!_ATL_NO_PRAGMA_WARNINGS ????#pragma?warning(?push,?3?) ??#pragma?push_macro("new") ??#undef?new ??#include?<gdiplus.h>???//?注意這里:添加了GDI+得頭文件 ??#pragma?pop_macro("new") ??#pragma?warning(?pop?) ????#include?<shlwapi.h> ????#ifndef?_ATL_NO_DEFAULT_LIBS ??#pragma?comment(lib,?"gdi32.lib") ??#pragma?comment(lib,?"shlwapi.lib") ??#pragma?comment(lib,?"gdiplus.lib") ??#if?WINVER?>=?0x0500 ??#pragma?comment(lib,?"msimg32.lib") ??#endif??//?WINVER?>=?0x0500 ??#endif??//?!_ATL_NO_DEFAULT_LIBS ????#pragma?pack(push,?_ATL_PACKING)?? #ifndef __ATLIMAGE_H__#define __ATLIMAGE_H__#pragma once#include <atldef.h>#include <atlbase.h>#include <atlstr.h>#include <atlsimpcoll.h>#include <atltypes.h>#ifndef _ATL_NO_PRAGMA_WARNINGS#pragma warning (push)#pragma warning(disable : 4820) // padding added after member#endif //!_ATL_NO_PRAGMA_WARNINGS#pragma warning( push, 3 )#pragma push_macro("new")#undef new#include <gdiplus.h> // 注意這里:添加了GDI+得頭文件#pragma pop_macro("new")#pragma warning( pop )#include <shlwapi.h>#ifndef _ATL_NO_DEFAULT_LIBS#pragma comment(lib, "gdi32.lib")#pragma comment(lib, "shlwapi.lib")#pragma comment(lib, "gdiplus.lib")#if WINVER >= 0x0500#pragma comment(lib, "msimg32.lib")#endif // WINVER >= 0x0500#endif // !_ATL_NO_DEFAULT_LIBS#pragma pack(push, _ATL_PACKING)
上面包含了GDI+得頭文件
?
再來看CImage的定義:
class?CImage??{??private:??????class?CDCCache??????{??????public:??????????CDCCache()?throw();??????????~CDCCache()?throw();????????????HDC?GetDC()?throw();??????????void?ReleaseDC(?HDC?)?throw();????????private:??????????HDC?m_ahDCs[CIMAGE_DC_CACHE_SIZE];??????};????????class?CInitGDIPlus??????{??????public:??????????CInitGDIPlus()?throw();??????????~CInitGDIPlus()?throw();????????????bool?Init()?throw();??????????void?ReleaseGDIPlus()?throw();??????????void?IncreaseCImageCount()?throw();??????????void?DecreaseCImageCount()?throw();????????private:??????????ULONG_PTR?m_dwToken;??????????CRITICAL_SECTION?m_sect;??????????LONG?m_nCImageObjects;??????};?? class CImage{private: class CDCCache { public: CDCCache() throw(); ~CDCCache() throw(); HDC GetDC() throw(); void ReleaseDC( HDC ) throw(); private: HDC m_ahDCs[CIMAGE_DC_CACHE_SIZE]; }; class CInitGDIPlus { public: CInitGDIPlus() throw(); ~CInitGDIPlus() throw(); bool Init() throw(); void ReleaseGDIPlus() throw(); void IncreaseCImageCount() throw(); void DecreaseCImageCount() throw(); private: ULONG_PTR m_dwToken; CRITICAL_SECTION m_sect; LONG m_nCImageObjects; };
?
static?CInitGDIPlus?s_initGDIPlus;?? static CInitGDIPlus s_initGDIPlus;
?
static?CDCCache?s_cache;?? static CDCCache s_cache;
它定義了兩個類成員變量: 其中CInitGDIPlus 是負責GDI+的啟動和釋放
?
我們再看一下,這個成員類的Init()方法:
?
inline?bool?CImage::CInitGDIPlus::Init()?throw()??{??????EnterCriticalSection(&m_sect);??????bool?fRet?=?true;??????if(?m_dwToken?==?0?)??????{??????????Gdiplus::GdiplusStartupInput?input;??????????Gdiplus::GdiplusStartupOutput?output;??????????Gdiplus::Status?status?=?Gdiplus::GdiplusStartup(?&m_dwToken,?&input,?&output?);???//啟動GDI+ ??????????if(?status?!=?Gdiplus::Ok?)??????????????fRet?=?false;??????}??????LeaveCriticalSection(&m_sect);??????return?fRet;??}?? inline bool CImage::CInitGDIPlus::Init() throw(){ EnterCriticalSection(&m_sect); bool fRet = true; if( m_dwToken == 0 ) { Gdiplus::GdiplusStartupInput input; Gdiplus::GdiplusStartupOutput output; Gdiplus::Status status = Gdiplus::GdiplusStartup( &m_dwToken, &input, &output ); //啟動GDI+ if( status != Gdiplus::Ok ) fRet = false; } LeaveCriticalSection(&m_sect); return fRet;}
也就是說 使用這個函數 啟動GDI+
?
再看下一個函數:
inline?void?CImage::CInitGDIPlus::ReleaseGDIPlus()?throw()??{??????EnterCriticalSection(&m_sect);??????if(?m_dwToken?!=?0?)??????{??????????Gdiplus::GdiplusShutdown(?m_dwToken?);??????}??????m_dwToken?=?0;??????LeaveCriticalSection(&m_sect);??}?? inline void CImage::CInitGDIPlus::ReleaseGDIPlus() throw(){ EnterCriticalSection(&m_sect); if( m_dwToken != 0 ) { Gdiplus::GdiplusShutdown( m_dwToken ); } m_dwToken = 0; LeaveCriticalSection(&m_sect);}
也就是說, 使用這一個函數,用來關閉GDI+
?
到此,我們便可知道,CImage類是基于GDI+的,但是我們還不知道CImage 對象是不是在初始化時就啟動了GDI+?如果不是,那什么時候才啟動GDI+呢?
為解決這個疑惑,我們查看CImage 構造函數
inline?CImage::CImage()?throw()?:??????m_hBitmap(?NULL?),??????m_pBits(?NULL?),??????m_hDC(?NULL?),??????m_nDCRefCount(?0?),??????m_hOldBitmap(?NULL?),??????m_nWidth(?0?),??????m_nHeight(?0?),??????m_nPitch(?0?),??????m_nBPP(?0?),??????m_iTransparentColor(?-1?),??????m_bHasAlphaChannel(?false?),??????m_bIsDIBSection(?false?)??{??????s_initGDIPlus.IncreaseCImageCount();??}?? inline CImage::CImage() throw() : m_hBitmap( NULL ), m_pBits( NULL ), m_hDC( NULL ), m_nDCRefCount( 0 ), m_hOldBitmap( NULL ), m_nWidth( 0 ), m_nHeight( 0 ), m_nPitch( 0 ), m_nBPP( 0 ), m_iTransparentColor( -1 ), m_bHasAlphaChannel( false ), m_bIsDIBSection( false ){ s_initGDIPlus.IncreaseCImageCount();}
?
inline?void?CImage::CInitGDIPlus::IncreaseCImageCount()?throw()??{??????EnterCriticalSection(&m_sect);??????m_nCImageObjects++;??????LeaveCriticalSection(&m_sect);??}?? inline void CImage::CInitGDIPlus::IncreaseCImageCount() throw(){ EnterCriticalSection(&m_sect); m_nCImageObjects++; LeaveCriticalSection(&m_sect);}
由此可見,構造函數并沒有啟動GDI+
也就是說定義? CImage image;? 這個image變量時,并沒有啟動GDI+
?
我們繼續查找:
inline?bool?CImage::InitGDIPlus()?throw()??{??????bool?bSuccess?=?s_initGDIPlus.Init();??????return(?bSuccess?);??}?? inline bool CImage::InitGDIPlus() throw(){ bool bSuccess = s_initGDIPlus.Init(); return( bSuccess );}
CImage使用InitGDIPlus() 來初始化GDI+
因此我們查找InitGDIPlus() 的所有引用 ,發現以下函數:
?
inline?HRESULT?CImage::GetImporterFilterString(?CSimpleString&?strImporters,???????CSimpleArray<?GUID?>&?aguidFileTypes,?LPCTSTR?pszAllFilesDescription?/*?=?NULL?*/,??????DWORD?dwExclude?/*?=?excludeDefaultLoad?*/,?TCHAR?chSeparator?/*?=?'|'?*/?)??{??????if(?!InitGDIPlus()?)??????{??????????return(?E_FAIL?);??????}????????UINT?nCodecs;??????UINT?nSize;??????Gdiplus::Status?status;??????Gdiplus::ImageCodecInfo*?pCodecs;????????status?=?Gdiplus::GetImageDecodersSize(?&nCodecs,?&nSize?);??????USES_ATL_SAFE_ALLOCA;??????pCodecs?=?static_cast<?Gdiplus::ImageCodecInfo*?>(?_ATL_SAFE_ALLOCA(nSize,?_ATL_SAFE_ALLOCA_DEF_THRESHOLD)?);????????if(?pCodecs?==?NULL?)??????????return?E_OUTOFMEMORY;????????status?=?Gdiplus::GetImageDecoders(?nCodecs,?nSize,?pCodecs?);??????BuildCodecFilterString(?pCodecs,?nCodecs,?strImporters,?aguidFileTypes,?pszAllFilesDescription,?dwExclude,?chSeparator?);????????return(?S_OK?);??}????inline?HRESULT?CImage::GetExporterFilterString(?CSimpleString&?strExporters,???????CSimpleArray<?GUID?>&?aguidFileTypes,?LPCTSTR?pszAllFilesDescription?/*?=?NULL?*/,??????DWORD?dwExclude?/*?=?excludeDefaultSave?*/,?TCHAR?chSeparator?/*?=?'|'?*/?)??{??????if(?!InitGDIPlus()?)??????{??????????return(?E_FAIL?);??????}????????UINT?nCodecs;??????UINT?nSize;??????Gdiplus::Status?status;??????Gdiplus::ImageCodecInfo*?pCodecs;????????status?=?Gdiplus::GetImageDecodersSize(?&nCodecs,?&nSize?);??????USES_ATL_SAFE_ALLOCA;??????pCodecs?=?static_cast<?Gdiplus::ImageCodecInfo*?>(?_ATL_SAFE_ALLOCA(nSize,?_ATL_SAFE_ALLOCA_DEF_THRESHOLD)?);????????if(?pCodecs?==?NULL?)??????????return?E_OUTOFMEMORY;????????status?=?Gdiplus::GetImageDecoders(?nCodecs,?nSize,?pCodecs?);??????BuildCodecFilterString(?pCodecs,?nCodecs,?strExporters,?aguidFileTypes,?pszAllFilesDescription,?dwExclude,?chSeparator?);????????return(?S_OK?);??}?? inline HRESULT CImage::GetImporterFilterString( CSimpleString& strImporters, CSimpleArray< GUID >& aguidFileTypes, LPCTSTR pszAllFilesDescription /* = NULL */, DWORD dwExclude /* = excludeDefaultLoad */, TCHAR chSeparator /* = '|' */ ){ if( !InitGDIPlus() ) { return( E_FAIL ); } UINT nCodecs; UINT nSize; Gdiplus::Status status; Gdiplus::ImageCodecInfo* pCodecs; status = Gdiplus::GetImageDecodersSize( &nCodecs, &nSize ); USES_ATL_SAFE_ALLOCA; pCodecs = static_cast< Gdiplus::ImageCodecInfo* >( _ATL_SAFE_ALLOCA(nSize, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) ); if( pCodecs == NULL ) return E_OUTOFMEMORY; status = Gdiplus::GetImageDecoders( nCodecs, nSize, pCodecs ); BuildCodecFilterString( pCodecs, nCodecs, strImporters, aguidFileTypes, pszAllFilesDescription, dwExclude, chSeparator ); return( S_OK );}inline HRESULT CImage::GetExporterFilterString( CSimpleString& strExporters, CSimpleArray< GUID >& aguidFileTypes, LPCTSTR pszAllFilesDescription /* = NULL */, DWORD dwExclude /* = excludeDefaultSave */, TCHAR chSeparator /* = '|' */ ){ if( !InitGDIPlus() ) { return( E_FAIL ); } UINT nCodecs; UINT nSize; Gdiplus::Status status; Gdiplus::ImageCodecInfo* pCodecs; status = Gdiplus::GetImageDecodersSize( &nCodecs, &nSize ); USES_ATL_SAFE_ALLOCA; pCodecs = static_cast< Gdiplus::ImageCodecInfo* >( _ATL_SAFE_ALLOCA(nSize, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) ); if( pCodecs == NULL ) return E_OUTOFMEMORY; status = Gdiplus::GetImageDecoders( nCodecs, nSize, pCodecs ); BuildCodecFilterString( pCodecs, nCodecs, strExporters, aguidFileTypes, pszAllFilesDescription, dwExclude, chSeparator ); return( S_OK );}
?
inline?HRESULT?CImage::Load(?IStream*?pStream?)?throw()??{??????if(?!InitGDIPlus()?)??????{??????????return(?E_FAIL?);??????}????????Gdiplus::Bitmap?bmSrc(?pStream?);??????if(?bmSrc.GetLastStatus()?!=?Gdiplus::Ok?)??????{??????????return(?E_FAIL?);??????}????????return(?CreateFromGdiplusBitmap(?bmSrc?)?);??}????inline?HRESULT?CImage::Load(?LPCTSTR?pszFileName?)?throw()??{??????if(?!InitGDIPlus()?)??????{??????????return(?E_FAIL?);??????}????????Gdiplus::Bitmap?bmSrc(?(CT2W)pszFileName?);??????if(?bmSrc.GetLastStatus()?!=?Gdiplus::Ok?)??????{??????????return(?E_FAIL?);??????}????????return(?CreateFromGdiplusBitmap(?bmSrc?)?);??}?? inline HRESULT CImage::Load( IStream* pStream ) throw(){ if( !InitGDIPlus() ) { return( E_FAIL ); } Gdiplus::Bitmap bmSrc( pStream ); if( bmSrc.GetLastStatus() != Gdiplus::Ok ) { return( E_FAIL ); } return( CreateFromGdiplusBitmap( bmSrc ) );}inline HRESULT CImage::Load( LPCTSTR pszFileName ) throw(){ if( !InitGDIPlus() ) { return( E_FAIL ); } Gdiplus::Bitmap bmSrc( (CT2W)pszFileName ); if( bmSrc.GetLastStatus() != Gdiplus::Ok ) { return( E_FAIL ); } return( CreateFromGdiplusBitmap( bmSrc ) );}
?
inline?HRESULT?CImage::Save(?IStream*?pStream,?REFGUID?guidFileType?)?const?throw()??{??????if(?!InitGDIPlus()?)??????{??????????return(?E_FAIL?);??????}????????UINT?nEncoders;??????UINT?nBytes;??????Gdiplus::Status?status;????????status?=?Gdiplus::GetImageEncodersSize(?&nEncoders,?&nBytes?);??????if(?status?!=?Gdiplus::Ok?)??????{??????????return(?E_FAIL?);??????}????????USES_ATL_SAFE_ALLOCA;??????Gdiplus::ImageCodecInfo*?pEncoders?=?static_cast<?Gdiplus::ImageCodecInfo*?>(?_ATL_SAFE_ALLOCA(nBytes,?_ATL_SAFE_ALLOCA_DEF_THRESHOLD)?);????????if(?pEncoders?==?NULL?)??????????return?E_OUTOFMEMORY;????????status?=?Gdiplus::GetImageEncoders(?nEncoders,?nBytes,?pEncoders?);??????if(?status?!=?Gdiplus::Ok?)??????{??????????return(?E_FAIL?);??????}????????CLSID?clsidEncoder?=?FindCodecForFileType(?guidFileType,?pEncoders,?nEncoders?);??????if(?clsidEncoder?==?CLSID_NULL?)??????{??????????return(?E_FAIL?);??????}????????if(?m_bHasAlphaChannel?)??????{??????????ATLASSUME(?m_nBPP?==?32?);??????????Gdiplus::Bitmap?bm(?m_nWidth,?m_nHeight,?m_nPitch,?PixelFormat32bppARGB,?static_cast<?BYTE*?>(?m_pBits?)?);??????????status?=?bm.Save(?pStream,?&clsidEncoder,?NULL?);??????????if(?status?!=?Gdiplus::Ok?)??????????{??????????????return(?E_FAIL?);??????????}??????}??????else??????{??????????Gdiplus::Bitmap?bm(?m_hBitmap,?NULL?);??????????status?=?bm.Save(?pStream,?&clsidEncoder,?NULL?);??????????if(?status?!=?Gdiplus::Ok?)??????????{??????????????return(?E_FAIL?);??????????}??????}????????return(?S_OK?);??}????inline?HRESULT?CImage::Save(?LPCTSTR?pszFileName,?REFGUID?guidFileType?)?const?throw()??{??????if(?!InitGDIPlus()?)??????{??????????return(?E_FAIL?);??????}????????UINT?nEncoders;??????UINT?nBytes;??????Gdiplus::Status?status;????????status?=?Gdiplus::GetImageEncodersSize(?&nEncoders,?&nBytes?);??????if(?status?!=?Gdiplus::Ok?)??????{??????????return(?E_FAIL?);??????}????????USES_CONVERSION_EX;??????Gdiplus::ImageCodecInfo*?pEncoders?=?static_cast<?Gdiplus::ImageCodecInfo*?>(?_ATL_SAFE_ALLOCA(nBytes,?_ATL_SAFE_ALLOCA_DEF_THRESHOLD)?);????????if(?pEncoders?==?NULL?)??????????return?E_OUTOFMEMORY;????????status?=?Gdiplus::GetImageEncoders(?nEncoders,?nBytes,?pEncoders?);??????if(?status?!=?Gdiplus::Ok?)??????{??????????return(?E_FAIL?);??????}????????CLSID?clsidEncoder?=?CLSID_NULL;??????if(?guidFileType?==?GUID_NULL?)??????{??????????//?Determine?clsid?from?extension ??????????clsidEncoder?=?FindCodecForExtension(?::PathFindExtension(?pszFileName?),?pEncoders,?nEncoders?);??????}??????else??????{??????????//?Determine?clsid?from?file?type ??????????clsidEncoder?=?FindCodecForFileType(?guidFileType,?pEncoders,?nEncoders?);??????}??????if(?clsidEncoder?==?CLSID_NULL?)??????{??????????return(?E_FAIL?);??????}????????LPCWSTR?pwszFileName?=?T2CW_EX(?pszFileName,?_ATL_SAFE_ALLOCA_DEF_THRESHOLD?);??#ifndef?_UNICODE ??????if(?pwszFileName?==?NULL?)??????????return?E_OUTOFMEMORY;??#endif?//?_UNICODE ??????if(?m_bHasAlphaChannel?)??????{??????????ATLASSUME(?m_nBPP?==?32?);??????????Gdiplus::Bitmap?bm(?m_nWidth,?m_nHeight,?m_nPitch,?PixelFormat32bppARGB,?static_cast<?BYTE*?>(?m_pBits?)?);??????????status?=?bm.Save(?pwszFileName,?&clsidEncoder,?NULL?);??????????if(?status?!=?Gdiplus::Ok?)??????????{??????????????return(?E_FAIL?);??????????}??????}??????else??????{??????????Gdiplus::Bitmap?bm(?m_hBitmap,?NULL?);??????????status?=?bm.Save(?pwszFileName,?&clsidEncoder,?NULL?);??????????if(?status?!=?Gdiplus::Ok?)??????????{??????????????return(?E_FAIL?);??????????}??????}????????return(?S_OK?);??}?? inline HRESULT CImage::Save( IStream* pStream, REFGUID guidFileType ) const throw(){ if( !InitGDIPlus() ) { return( E_FAIL ); } UINT nEncoders; UINT nBytes; Gdiplus::Status status; status = Gdiplus::GetImageEncodersSize( &nEncoders, &nBytes ); if( status != Gdiplus::Ok ) { return( E_FAIL ); } USES_ATL_SAFE_ALLOCA; Gdiplus::ImageCodecInfo* pEncoders = static_cast< Gdiplus::ImageCodecInfo* >( _ATL_SAFE_ALLOCA(nBytes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) ); if( pEncoders == NULL ) return E_OUTOFMEMORY; status = Gdiplus::GetImageEncoders( nEncoders, nBytes, pEncoders ); if( status != Gdiplus::Ok ) { return( E_FAIL ); } CLSID clsidEncoder = FindCodecForFileType( guidFileType, pEncoders, nEncoders ); if( clsidEncoder == CLSID_NULL ) { return( E_FAIL ); } if( m_bHasAlphaChannel ) { ATLASSUME( m_nBPP == 32 ); Gdiplus::Bitmap bm( m_nWidth, m_nHeight, m_nPitch, PixelFormat32bppARGB, static_cast< BYTE* >( m_pBits ) ); status = bm.Save( pStream, &clsidEncoder, NULL ); if( status != Gdiplus::Ok ) { return( E_FAIL ); } } else { Gdiplus::Bitmap bm( m_hBitmap, NULL ); status = bm.Save( pStream, &clsidEncoder, NULL ); if( status != Gdiplus::Ok ) { return( E_FAIL ); } } return( S_OK );}inline HRESULT CImage::Save( LPCTSTR pszFileName, REFGUID guidFileType ) const throw(){ if( !InitGDIPlus() ) { return( E_FAIL ); } UINT nEncoders; UINT nBytes; Gdiplus::Status status; status = Gdiplus::GetImageEncodersSize( &nEncoders, &nBytes ); if( status != Gdiplus::Ok ) { return( E_FAIL ); } USES_CONVERSION_EX; Gdiplus::ImageCodecInfo* pEncoders = static_cast< Gdiplus::ImageCodecInfo* >( _ATL_SAFE_ALLOCA(nBytes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) ); if( pEncoders == NULL ) return E_OUTOFMEMORY; status = Gdiplus::GetImageEncoders( nEncoders, nBytes, pEncoders ); if( status != Gdiplus::Ok ) { return( E_FAIL ); } CLSID clsidEncoder = CLSID_NULL; if( guidFileType == GUID_NULL ) { // Determine clsid from extension clsidEncoder = FindCodecForExtension( ::PathFindExtension( pszFileName ), pEncoders, nEncoders ); } else { // Determine clsid from file type clsidEncoder = FindCodecForFileType( guidFileType, pEncoders, nEncoders ); } if( clsidEncoder == CLSID_NULL ) { return( E_FAIL ); } LPCWSTR pwszFileName = T2CW_EX( pszFileName, _ATL_SAFE_ALLOCA_DEF_THRESHOLD );#ifndef _UNICODE if( pwszFileName == NULL ) return E_OUTOFMEMORY;#endif // _UNICODE if( m_bHasAlphaChannel ) { ATLASSUME( m_nBPP == 32 ); Gdiplus::Bitmap bm( m_nWidth, m_nHeight, m_nPitch, PixelFormat32bppARGB, static_cast< BYTE* >( m_pBits ) ); status = bm.Save( pwszFileName, &clsidEncoder, NULL ); if( status != Gdiplus::Ok ) { return( E_FAIL ); } } else { Gdiplus::Bitmap bm( m_hBitmap, NULL ); status = bm.Save( pwszFileName, &clsidEncoder, NULL ); if( status != Gdiplus::Ok ) { return( E_FAIL ); } } return( S_OK );}
?
有上面可知: CImage對象 在第一次Load() 或第一次Save() 時 啟動GDI+
?
下面我們看看 CImage析構時,是否能將GDI+關閉掉:
inline?CImage::~CImage()?throw()??{??????Destroy();??????s_initGDIPlus.DecreaseCImageCount();??}?? inline CImage::~CImage() throw(){ Destroy(); s_initGDIPlus.DecreaseCImageCount();}
?
inline?void?CImage::CInitGDIPlus::DecreaseCImageCount()?throw()??{??????EnterCriticalSection(&m_sect);??????if(?--m_nCImageObjects?==?0?)??????????ReleaseGDIPlus();??????LeaveCriticalSection(&m_sect);??}?? inline void CImage::CInitGDIPlus::DecreaseCImageCount() throw(){ EnterCriticalSection(&m_sect); if( --m_nCImageObjects == 0 ) ReleaseGDIPlus(); LeaveCriticalSection(&m_sect);}
?
inline?void?CImage::CInitGDIPlus::ReleaseGDIPlus()?throw()??{??????EnterCriticalSection(&m_sect);??????if(?m_dwToken?!=?0?)??????{??????????Gdiplus::GdiplusShutdown(?m_dwToken?);??????}??????m_dwToken?=?0;??????LeaveCriticalSection(&m_sect);??}?? inline void CImage::CInitGDIPlus::ReleaseGDIPlus() throw(){ EnterCriticalSection(&m_sect); if( m_dwToken != 0 ) { Gdiplus::GdiplusShutdown( m_dwToken ); } m_dwToken = 0; LeaveCriticalSection(&m_sect);}
也就是說,一個CImage對象退出時,并不直接關閉GDI+ ,而是僅僅將GDI+使用計數減一, 當其為0時,再關閉GDI+
而這是通過類靜態變量來實現計數的:
static?CInitGDIPlus?s_initGDIPlus;?? static CInitGDIPlus s_initGDIPlus;
?
由此,我們可作如下總結:
?
????? 當定義多個CImge 變量時, 當某個變量加載圖片或保存圖片時,啟動GDI+,之后, 當其他變量再加載圖片或保存時,增加GDI+計數變量
????? 當所有CImage變量都析構完畢時,才關閉GDI+,否則,只是減少GDI+計算變量值。
??? ? 所以說,CImage類是基于GDI+的。
原文地址:http://blog.csdn.net/shuilan0066/article/details/7086371?
我不喜歡做界面,所以就看過一次,因為我不會,所以有個印象。
CImage 是 GDI+ 里的東西?
?
轉載于:https://www.cnblogs.com/suanguade/p/4038055.html
總結
以上是生活随笔為你收集整理的CImage 是基于GDI+的,很老的一篇文章,我很久很久以前看到过的的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。