⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 itemidlist.h

📁 一个使用wtl写的完整的多窗口浏览器
💻 H
📖 第 1 页 / 共 2 页
字号:
#pragma once

// too easy implementation
// no ref count, no other goodness, forgive me.
class CItemIDList;

// for debug
#ifdef _DEBUG
	const bool _Mtl_ItemIDList_traceOn = false;
	#define idlTRACE if (_Mtl_ItemIDList_traceOn) ATLTRACE
#else
	#define idlTRACE
#endif

class CItemIDList
{
public:

#ifdef _DEBUG
// for checking leaks
	static int d_m_nCount;
#define _INCREMENT_COUNT() ++CItemIDList::d_m_nCount; if (_Mtl_ItemIDList_traceOn) ATLTRACE(_T("CItemIDList(%d)\n"), CItemIDList::d_m_nCount)
#define _DECREMENT_COUNT() --CItemIDList::d_m_nCount; if (_Mtl_ItemIDList_traceOn) ATLTRACE(_T("CItemIDList(%d)\n"), CItemIDList::d_m_nCount)
#else
	#define _INCREMENT_COUNT()
	#define _DECREMENT_COUNT()
#endif

// Data members
	LPITEMIDLIST m_pidl;

// Constructors
	CItemIDList() : m_pidl(NULL)
	{
	}

	CItemIDList(const CItemIDList& idl)
	{
		m_pidl = _CopyItemIDList(idl);
	}

	CItemIDList(LPCITEMIDLIST pidl)
	{
		m_pidl = _CopyItemIDList(pidl);
	}

	CItemIDList(LPCTSTR lpszPath)// Note. this is late
	{
		m_pidl = NULL;

		ULONG chEaten;
		USES_CONVERSION;

		CComPtr<IShellFolder> spDesktopFolder;
		HRESULT hr = ::SHGetDesktopFolder(&spDesktopFolder);
		if (FAILED(hr))
			return;

		spDesktopFolder->ParseDisplayName(NULL, NULL, T2OLE((LPTSTR)lpszPath),
			&chEaten, &m_pidl, NULL);

		_INCREMENT_COUNT();
	}

// Destructor
	~CItemIDList()
	{
		_Release(m_pidl);
	}

	void Release()
	{
		_Release(m_pidl);
		m_pidl = NULL;
	}

	static void FreeIDList(LPITEMIDLIST pidl)
	{
		_Release(pidl);
	}

// Attributes
	bool IsNull()
	{
		return (m_pidl == NULL);
	}

	CString GetPath()
	{
		TCHAR szPath[MAX_PATH];
		if (::SHGetPathFromIDList(m_pidl, szPath))
			return szPath;
		else
			return CString();
	}

	void Attach(LPITEMIDLIST pidl)
	{
		ATLASSERT(m_pidl == NULL);
		m_pidl = pidl;
	}

	LPITEMIDLIST Detach()
	{
		LPITEMIDLIST idl = m_pidl;
		m_pidl = NULL;
		return idl;
	}

	operator LPITEMIDLIST() const
	{
		return m_pidl;
	}

//	operator LPCITEMIDLIST() const
//	{
//		return m_pidl;
//	}

	LPITEMIDLIST* operator&()
	{
		ATLASSERT(m_pidl == NULL);
		_INCREMENT_COUNT();
		return &m_pidl;
	}

	UINT GetSize()
	{
		return _GetSize(m_pidl);
	}

// Operations
/*	bool operator==(const CItemIDList& idl) const
	{
		return _CmpItemID(m_pidl, idl);
	}

	bool operator!=(const CItemIDList& idl) const
	{
		return !_CmpItemID(m_pidl, idl);
	}
*/
	void operator+=(const CItemIDList& idl)
	{
		LPITEMIDLIST pidlNew = _ConcatPidls(m_pidl, idl);
		Release();
		m_pidl = pidlNew;
	}

	void operator-=(const CItemIDList& idl)
	{
		LPITEMIDLIST pidlNew = _RelativePidls(m_pidl, idl);
		Release();
		m_pidl = pidlNew;
	}

	bool Find(LPCTSTR lpszText)
	{
		int nLen = ::lstrlen(lpszText);
		if (nLen == 0)
			return false;

		int nSrc = _GetSize(m_pidl);
		if (nSrc < nLen)
			return false;

		const BYTE* p = (BYTE*)m_pidl;

		for (int i = 0; i < nSrc - nLen; ++i) {
			if(::memcmp(p + i, lpszText, nLen * sizeof(TCHAR)) == 0) {
				return true;
			}
		}

		return false;
	}

// Operators
	CItemIDList& operator=(const CItemIDList& idlSrc)
	{
		Release();
		m_pidl = _CopyItemIDList(idlSrc);
		return *this;
	}
	
	CItemIDList& operator=(LPCTSTR lpszPath)
	{
		Release();

		CComPtr<IShellFolder> spDesktopFolder;
		HRESULT hr = ::SHGetDesktopFolder(&spDesktopFolder);
		if (FAILED(hr))
			return *this;

		ULONG chEaten;
		USES_CONVERSION;
		hr = spDesktopFolder->ParseDisplayName(NULL, NULL, T2OLE((LPTSTR)lpszPath),
			&chEaten, &m_pidl, NULL);
		
		_INCREMENT_COUNT();
		return *this;
	}

	CItemIDList operator+(const CItemIDList& idlSrc) const
	{
		CItemIDList idl;
		idl.m_pidl = _ConcatPidls(m_pidl, idlSrc);
		return idl;
	}

	CItemIDList operator-(const CItemIDList& idlSrc) const
	{
		CItemIDList idl;
		idl.m_pidl = _RelativePidls(m_pidl, idlSrc);
		return idl;
	}

// Helpers
	static LPITEMIDLIST _Create(UINT cbSize)
	{
		LPITEMIDLIST pidl = (LPITEMIDLIST)::CoTaskMemAlloc(cbSize);
		if (pidl == NULL)
			return NULL;

		_INCREMENT_COUNT();

		if (pidl)
			::memset(pidl, 0, cbSize);		// zero-init for external task	 alloc

		return pidl;
	}

	static void _Release(LPITEMIDLIST pidl)
	{
#ifdef _DEBUG
		if (pidl != NULL) {
			_DECREMENT_COUNT();
		}
#endif

		::CoTaskMemFree(pidl);
	}

	static UINT _GetSize(LPCITEMIDLIST pidl)
	{// include null terminator
		UINT cbTotal = 0;
		if (pidl) {
			cbTotal += sizeof(pidl->mkid.cb);		// Null terminator
			while (pidl->mkid.cb) {
				cbTotal += pidl->mkid.cb;
				pidl = _Next(pidl);
			}
		}

		return cbTotal;
	}

	static LPITEMIDLIST _Next(LPCITEMIDLIST pidl)
	{
		ATLASSERT(pidl != NULL);

		LPSTR lpMem=(LPSTR)pidl;
		lpMem += pidl->mkid.cb;
		return (LPITEMIDLIST)lpMem;
	}

	static LPITEMIDLIST _ConcatPidls(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
	{
		UINT cb1;
		if (pidl1)	//May be NULL
		   cb1 = _GetSize(pidl1) - sizeof(pidl1->mkid.cb);
		else
		   cb1 = 0;

		UINT cb2 = _GetSize(pidl2);	

		LPITEMIDLIST pidlNew = _Create(cb1 + cb2);
		if (pidlNew) {
			if (pidl1)
				::memcpy(pidlNew, pidl1, cb1);
			::memcpy(((LPSTR)pidlNew) + cb1, pidl2, cb2);
			ATLASSERT(_GetSize(pidlNew) == cb1 + cb2);
		}

		return pidlNew;
	}

	static LPITEMIDLIST _RelativePidls(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
	{
		ATLASSERT(pidl1 != NULL);

		UINT cb1 = _GetSize(pidl1);

		UINT cb2;
		if (pidl2)	//May be NULL
		   cb2 = _GetSize(pidl2) - sizeof(pidl2->mkid.cb);
		else
		   cb2 = 0;

		if (cb1 <= cb2)
			return NULL;
		
		LPITEMIDLIST pidlNew = _Create(cb1 - cb2);
		if (pidlNew) {
			if (pidl1)
				::memcpy(pidlNew, ((LPSTR)pidl1) + cb2, cb1 - cb2);

			ATLASSERT(_GetSize(pidlNew) == cb1 - cb2);
		}

		return pidlNew;
	}


	static LPITEMIDLIST _CopyItemIDList(LPCITEMIDLIST lpi)
	{
		if (lpi == NULL)
			return NULL;

		UINT cb = _GetSize(lpi);
		LPITEMIDLIST lpiTemp = (LPITEMIDLIST)::CoTaskMemAlloc(cb);
		if (lpiTemp == NULL)
			return NULL;
		
		_INCREMENT_COUNT();

		::memcpy(lpiTemp, lpi, cb);

		return lpiTemp;
	}

/*	static LPITEMIDLIST _CopyItemID(LPCITEMIDLIST lpi)
	{
		if (lpi == NULL)
			return NULL;

		LPITEMIDLIST lpiTemp = (LPITEMIDLIST)::CoTaskMemAlloc( lpi->mkid.cb + sizeof(lpi->mkid.cb) );
		if (lpiTemp == NULL)
			return NULL;

		_INCREMENT_COUNT();

		::memcpy(lpiTemp, lpi, lpi->mkid.cb + sizeof(lpi->mkid.cb));

		return lpiTemp;
	}
*/
	static bool _CmpItemID(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
	{
		if (pidl1 == NULL && pidl2 != NULL)
			return false;

		if (pidl1 != NULL && pidl2 == NULL)
			return false;

		UINT cb1 = _GetSize(pidl2);
		UINT cb2 = _GetSize(pidl1);
		
		if (cb1 != cb2)
			return false;

		return ::memcmp(pidl1, pidl2, cb1) == 0;
	}

	static void _Dump(LPCITEMIDLIST pidlSrc)
	{
		if  (pidlSrc == NULL)
			return;

		LPITEMIDLIST pidl = (LPITEMIDLIST)pidlSrc;
		while (pidl->mkid.cb) {
			idlTRACE(_T(" "));
			for (int i = sizeof(pidl->mkid.cb); i < pidl->mkid.cb; ++i)
				idlTRACE(_T("%c"), *((LPBYTE)pidl + i));
			pidl = _Next(pidl);
		}

		idlTRACE(_T("\n"));
	}
};

#ifdef _DEBUG
	__declspec(selectany) int CItemIDList::d_m_nCount = 0;
#endif

// Compare helpers
inline bool operator==(const CItemIDList& s1, const CItemIDList& s2)
{
	return CItemIDList::_CmpItemID(s1, s2);

}
inline bool operator==(const CItemIDList& s1, LPCITEMIDLIST s2)
{
	return CItemIDList::_CmpItemID(s1, s2);
}

inline bool operator==(LPCITEMIDLIST s1, const CItemIDList& s2)
{
	return CItemIDList::_CmpItemID(s1, s2);
}

inline bool operator!=(const CItemIDList& s1, const CItemIDList& s2)
{
	return !CItemIDList::_CmpItemID(s1, s2);
}

inline bool operator!=(const CItemIDList& s1, LPCITEMIDLIST s2)
{
	return !CItemIDList::_CmpItemID(s1, s2);
}

inline bool operator!=(LPCITEMIDLIST s1, const CItemIDList& s2)
{
	return !CItemIDList::_CmpItemID(s1, s2);
}

/*
template <class _Function>
_Function MtlForEachFile(IShellFolder* pFolder, _Function __f, bool bIncludeHidden = false)
{
	DWORD grfFlags = bIncludeHidden ? SHCONTF_NONFOLDERS|SHCONTF_INCLUDEHIDDEN : SHCONTF_NONFOLDERS;

	CComPtr<IEnumIDList> spEnum;
	HRESULT hr = pFolder->EnumObjects(NULL, grfFlags, &spEnum);
	if (FAILED(hr))
		return __f;

	LPITEMIDLIST pidl;
	ULONG celtFetched;
	while (spEnum->Next(1, &pidl, &celtFetched) == S_OK) {
		ATLASSERT(pidl != NULL);
		CItemIDList idl; idl.Attach(pidl);
		__f(pFolder, idl);
	}

	return __f;
}

template <typename _Function>
_Function MtlForEachFolder(IShellFolder* pFolder, _Function __f, bool bIncludeHidden = false)
{
	DWORD grfFlags = bIncludeHidden ? SHCONTF_FOLDERS|SHCONTF_INCLUDEHIDDEN : SHCONTF_FOLDERS;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -