首页 > 代码库 > VC++自释放指针、自释放虚拟内存、自关闭句柄、局部作用域回调函数调用等辅助开发类

VC++自释放指针、自释放虚拟内存、自关闭句柄、局部作用域回调函数调用等辅助开发类


#pragma once

#ifndef NULL
#define NULL 0
#endif

namespace RangeHelper
{
	template <class T>
	class CAutoDeletePtr {
		//自动删除指针
	public:
		CAutoDeletePtr() : m_ptr(NULL) {

		}

		CAutoDeletePtr(T* ptr) {
			m_ptr = ptr;
		}

		~CAutoDeletePtr() {
			Free();
		}

		void Free() {
			if (!m_ptr) return;

			delete []m_ptr;
			m_ptr = NULL;
		}

		bool Allocate(size_t nElements) {
			Free();

			m_ptr = new T[nElements];
			if (!m_ptr) return false;

			return true;
		}

		void Attach(T* p) {
			ASSERT(p != NULL);

			m_ptr = p;
		}

		T* Detach() {
			T* p;

			p = m_p;
			m_p = NULL;

			return( p );
		}

		T operator[](int i) const
		{
			ASSERT((i>=0) && AfxIsValidAddress(m_ptr, sizeof(T)*i));
			return m_ptr[i];
		}

		T& operator[](int i)
		{
			ASSERT((i>=0) && AfxIsValidAddress(m_ptr, sizeof(T)*i));
			return m_ptr[i];
		}

		CAutoDeletePtr<T>& operator=(const T* ptr)
		{
			if ((m_ptr != NULL) && (m_ptr != ptr))
			{
				if (m_ptr != NULL)
				{
					delete []m_ptr;
					m_ptr = NULL;
				}
			}

			m_ptr = const_cast<T*>(ptr);

			return *this;
		}
		
		operator T*() const 
		{
			return m_ptr;
		}

	private:
		T *m_ptr;
	};

	template <class T>
	class CAutoReleaseVM
		//自释放虚拟内存
	{
	public:
		CAutoReleaseVM() :m_ptr(NULL), m_nCnt(0) {
			
		}

		CAutoReleaseVM(T* vmData, ULONG nCnt) {
			ASSERT(vmData);
			ASSERT(nCnt>0);
			m_ptr	= vmData;
			m_nCnt	= nCnt;
		}

		CAutoReleaseVM(ULONG nElementCnt, DWORD flAllocationType=MEM_COMMIT, DWORD flProtect=PAGE_READWRITE) : m_ptr(NULL) {
			AllocateVM(nElementCnt, flAllocationType, flProtect);
		}

		~CAutoReleaseVM()
		{
			FreeVM();
		}

		void FreeVM()
		{
			if (m_ptr) {
				VirtualFree(m_ptr, 0, MEM_RELEASE);
				m_nCnt	= 0;
				m_ptr	= NULL;
			}
		}

		BOOL AllocateVM(ULONG nElementCnt, DWORD flAllocationType=MEM_COMMIT, DWORD flProtect=PAGE_READWRITE)
		{
			FreeVM();
			m_ptr	= (T*)VirtualAlloc(NULL, nElementCnt*sizeof(T), flAllocationType, flProtect);
			m_nCnt	= nElementCnt;
			return (m_ptr!=NULL);
		}

		BOOL ReAllocateVM(ULONG nElementCnt, BOOL bCopyOld=TRUE, DWORD flAllocationType=MEM_COMMIT, DWORD flProtect=PAGE_READWRITE)
		{
			if (!bCopyOld)
				return AllocateVM(nElementCnt, flAllocationType, flProtect);

			T *tmp = (T*)VirtualAlloc(NULL, nElementCnt*sizeof(T), flAllocationType, flProtect);
			if (!tmp)
				return FALSE;

			memmove(tmp, m_ptr, min(nElementCnt, m_nCnt)*sizeof(T));
			m_ptr = tmp;
			m_nCnt= nElementCnt;
			return TRUE;
		}

		BOOL IsOK() {
			return (m_ptr!=NULL);
		}

		size_t GetDataBytes() {
			size_t nDataBytes = 0;
			if (IsOK()) {
				nDataBytes = GetTypeSize()*m_nCnt;
			}
			return nDataBytes;
		}

		size_t GetTypeSize() {
			return sizeof(T);
		}

		ULONG GetDataCount() {
			ULONG nDataCount = 0;
			if (IsOK()) {
				nDataCount = m_nCnt;
			}
			return nDataCount;
		}

		T operator[](size_t i) const
		{
			ASSERT((i>=0) && m_ptr && AfxIsValidAddress(m_ptr, sizeof(T)*i));
			return m_ptr[i];
		}

		T& operator[](size_t i)
		{
			ASSERT((i>=0) && m_ptr && AfxIsValidAddress(m_ptr, sizeof(T)*i));
			return m_ptr[i];
		}

		operator T*() const 
		{
			return m_ptr;
		}

	private:
		T*		m_ptr;
		size_t	m_nCnt;
	};

	class CAutoCloseHandle
		//自动关闭句柄类
	{
	public:		
		CAutoCloseHandle(HANDLE* handle=NULL) : m_handle(handle)
		{
		}		

		CAutoCloseHandle& operator=(HANDLE* rh)
		{
			if (m_handle) {
				CloseHandle(m_handle);
				m_handle = NULL;
			}
			m_handle = rh;

			return *this;
		}

		~CAutoCloseHandle()
		{
			CloseHandle(*m_handle);
		}

	private:
		HANDLE *m_handle;
	};

	template <class T>
	class CAutoDeleteArray : public CArray<T*, T*>
	{
	public:
		~CAutoDeleteArray() {
			RemoveAll();
		}

		void RemoveAt(INT_PTR nIndex, INT_PTR nCount = 1)
		{
			ASSERT(nCount>0);
			for (INT_PTR i=nIndex; i!=min(nIndex+nCount, GetCount()); ++i)
			{
				T *pItem = GetAt(i);
				delete pItem;
			}
			CArray::RemoveAt(nIndex, nCount);
		}

		void RemoveAll()
		{
			for (INT_PTR i=0; i!=GetCount(); ++i)
			{
				T *pItem = GetAt(i);
				delete pItem;
			}
			CArray::RemoveAll();
		}
	};
	
/*
	//CRangeFxnHelper使用示例
	class A
	{
	public:
		void func1(){
			cout << 1 << endl;
		}

		void func2(){
			cout << 2 << endl;
		}

		void test()	{
			CRangeFxnHelper<A> a(this, &A::func1, &A::func2);
		}
	};
*/
	template <class T>
	class CRangeFxnHelper
	//局部函数调用
	{
		typedef void(T::* MemFxnPtr)(void); //成员函数
	public:
		CRangeFxnHelper(T* pClassName,
			MemFxnPtr lpfxnEnter,
			MemFxnPtr lpfxnLeave = NULL) : m_pClassName(pClassName),
			m_lpfxnLeave(lpfxnLeave)
		{
			ASSERT(pClassName != NULL);
			ASSERT(lpfxnEnter != NULL);

			(m_pClassName->*lpfxnEnter)();
		}

		~CRangeFxnHelper()
		{
			if (m_lpfxnLeave != NULL)
				(m_pClassName->*m_lpfxnLeave)();
		}

	private:
		T *m_pClassName;
		MemFxnPtr m_lpfxnLeave;
	};

	template <class T>
	class CAutoRevertBOOL
	//自动反置布尔变量
	{
	public:
		CAutoRevertBOOL(T *pObjBool, T initVal) : m_pObjBool(pObjBool),
			m_InitVal(initVal)
		{
			ASSERT(pObjBool != NULL);

			*pObjBool = initVal;
		}

		~CAutoRevertBOOL()
		{
			*m_pObjBool = !m_InitVal;
		}

	private:
		T *m_pObjBool;
		T m_InitVal;
	};

	class CAutoDisableEnableChildCtls
	{
	public:
		CAutoDisableEnableChildCtls(HWND hwndParent, UINT nFirstExcludeChildCtrlID=-1, ...)
			: m_hwndParent(hwndParent), m_bDisabled(FALSE)
		{
			AddExcludeCtrlIDs(nFirstExcludeChildCtrlID);
		}

		~CAutoDisableEnableChildCtls()
		{
			if (m_bDisabled)
				SwitchStatus();
		}

		void SwitchStatus()
		{
			struct stEnumChild 
			{
				BOOL				*pChangeStatus		;//改变状态
				CArray<UINT, UINT>	*pArrayExcludeID	;//无须进行状态改变的列表
				CArray<HWND, HWND>	*pStatusChangedWND	;//已经改变的窗口
			};

			class CEnumChildHelper
			{
			public:
				static BOOL __stdcall EnumChildProc(HWND hwnd, LPARAM lParam)
				{
					stEnumChild *pParam		= (stEnumChild *)lParam;
					LONG lStyle				= GetWindowLong(hwnd, GWL_STYLE);
					BOOL bDisable			= *(pParam->pChangeStatus);
					CArray<UINT, UINT> &arr = *(pParam->pArrayExcludeID);
					CArray<HWND, HWND> &aChanged = *(pParam->pStatusChangedWND);

					for (int i=0; i!=arr.GetCount(); ++i)
					{						
						if (GetDlgCtrlID(hwnd) == arr[i]) return TRUE;
					}

					TCHAR szClsName[512] = {_T('\0')};
					GetClassName(hwnd, szClsName, 512);
					if (!_tcscmp(szClsName, _T("Internet Explorer_Server")))//不处理Web浏览器
						return TRUE;
					if (!_tcscmp(szClsName, _T("Static"))) //静态文本
						return TRUE;

					if (bDisable)
					{
						if ((lStyle&WS_DISABLED) != WS_DISABLED) {
							lStyle |= WS_DISABLED;
							aChanged.Add(hwnd);
						}
					} else {
						if ((lStyle&WS_DISABLED) == WS_DISABLED) {
							int i = 0;
							for (; i!=aChanged.GetCount(); ++i)
							{
								if (hwnd == aChanged[i])
									break;
							}
							if (i == aChanged.GetCount()) {
								//未在已处理过的控件列表中
								return TRUE;
							}
							aChanged.RemoveAt(i);

							lStyle &= ~WS_DISABLED;
						}
					}

					SetWindowLong(hwnd, GWL_STYLE, lStyle);
					::InvalidateRect(hwnd, NULL, TRUE);
					return TRUE;
				}
			};

			stEnumChild param;
			param.pChangeStatus		= &m_bDisabled;
			param.pArrayExcludeID	= &m_aExcludeIDs;
			param.pStatusChangedWND = &m_aStatusChangedChild;

			m_bDisabled = !m_bDisabled;

			EnumChildWindows(m_hwndParent, CEnumChildHelper::EnumChildProc, (LPARAM)¶m);			
		}

		void AddExcludeCtrlIDs(UINT nID, ...)
			//以-1结尾
		{
			va_list arglst;
			va_start(arglst, nID);

			while (nID != (UINT)-1)
			{
				//防止添加多次
				for (INT_PTR i=0; i!=m_aExcludeIDs.GetSize(); ++i)
				{
					if (nID == m_aExcludeIDs[i]) goto Next;
				}
				m_aExcludeIDs.Add(nID);
Next:
				nID = va_arg(arglst, UINT);				
			}
			va_end(arglst);
		}

	private:
		HWND				m_hwndParent;
		CArray<UINT, UINT>  m_aExcludeIDs;
		BOOL				m_bDisabled;
		CArray<HWND, HWND>	m_aStatusChangedChild;
	};

	class CAutoWndStatusSwitch
		//自动转换窗口使能与禁用状态
	{
	public:
		//ID 以-1结尾
		CAutoWndStatusSwitch(HWND hwndParent, UINT nID=-1, ...)
			: m_hwndParent(hwndParent), m_bSwitched(FALSE)
		{
			ASSERT(hwndParent != NULL);

			AddCtrls(nID);
		}
		~CAutoWndStatusSwitch()
		{
			if (m_bSwitched)
				SwitchStatus();
		}

		void AddCtrls(UINT nID, ...)
			//以-1结尾
		{
			va_list arglst;
			va_start(arglst, nID);

			while (nID != (UINT)-1)
			{
				//防止添加多次
				for (INT_PTR i=0; i!=m_aIDs.GetSize(); ++i)
				{
					if (nID == m_aIDs[i]) goto Next;
				}
				m_aIDs.Add(nID);
Next:
				nID = va_arg(arglst, UINT);				
			}
			va_end(arglst);
		}

		void SwitchStatus()
			//状态转换
		{
			m_bSwitched = !m_bSwitched;
			for (INT_PTR i=0; i!=m_aIDs.GetSize(); ++i)
			{
				HWND hCtrl = GetDlgItem(m_hwndParent, m_aIDs[i]);
				if (!IsWindow(hCtrl)) continue;

				LONG lStyle = GetWindowLong(hCtrl, GWL_STYLE);

				if ((lStyle&WS_DISABLED) == WS_DISABLED)
					lStyle &= ~WS_DISABLED;
				else
					lStyle |= WS_DISABLED;

				SetWindowLong(hCtrl, GWL_STYLE, lStyle);
				::InvalidateRect(hCtrl, NULL, TRUE);
			}
		}
	private:
		HWND				m_hwndParent;
		CArray<UINT, UINT>  m_aIDs;
		BOOL				m_bSwitched;
	};

	class CAutoHideShowWnd
		//自动隐藏窗口
	{
	public:
		CAutoHideShowWnd(HWND hWnd, BOOL bHide=TRUE):m_hWnd(hWnd)
		{
			ASSERT(IsWindow(hWnd));
			if (bHide) Hide();
		}

		~CAutoHideShowWnd()
		{
			Restore();
		}

		void Hide()
		{
			if (IsWindow(m_hWnd) &&
				(GetWindowLong(m_hWnd, GWL_STYLE) & WS_VISIBLE)) {
					ShowWindow(m_hWnd, SW_HIDE);
			}
		}

		void Restore()
		{
			if (IsWindow(m_hWnd) &&
				(GetWindowLong(m_hWnd, GWL_STYLE) & ~WS_VISIBLE)) {
					ShowWindow(m_hWnd, SW_SHOW);
			}
		}

	private:
		HWND m_hWnd;
	};
}

VC++自释放指针、自释放虚拟内存、自关闭句柄、局部作用域回调函数调用等辅助开发类