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

📄 mtlcom.h

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

#pragma once

#ifndef __MTLBASE_H__
	#error mtlcom.h requires mtlbase.h to be included first
#endif

#ifndef _SHLOBJ_H_
	#error mtlcom.h requires shlobj.h to be included first
#endif

////////////////////////////////////////////////////////////////////////////
// MTL Version 0.10
// Copyright (C) 2001 MB<mb2@geocities.co.jp>
// All rights unreserved.
//
// This file is a part of Mb Template Library.
// The code and information is *NOT* provided "as-is" without
// warranty of any kind, either expressed or implied.
//
// MtlCom.h: Last updated: February 12, 2001
////////////////////////////////////////////////////////////////////////////

#define HANDLE_MENU_MESSAGE_CONTEXTMENU(x) \
	if(uMsg == WM_INITMENUPOPUP || uMsg == WM_DRAWITEM || uMsg == WM_MEASUREITEM) \
	{ \
		if (x != NULL) { \
			bHandled = TRUE; \
			lResult = x->HandleMenuMsg(uMsg, wParam, lParam); \
		} \
		else { \
			bHandled = FALSE; \
		} \
		if(bHandled) \
			return TRUE; \
	}

namespace MTL
{

inline void MtlCheckError(SCODE sc)
{
	if (FAILED(sc)) {
		if (sc == E_OUTOFMEMORY)
			ATLTRACE2(atlTraceCOM, 0, "MtlCheckError Error : OOM\n");
		else
			ATLTRACE2(atlTraceCOM, 0, "MtlCheckError Error : MISC\n");
	}
}

// cf. "ATL Internals"
inline HRESULT WINAPI _This(void* pv, REFIID iid, void** ppvObject, DWORD) {
	ATLASSERT(iid == IID_NULL);
	*ppvObject = pv;
	return S_OK;
}

// Helper for creating default FORMATETC from cfFormat
LPFORMATETC _MtlFillFormatEtc(
	LPFORMATETC lpFormatEtc, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtcFill)
{
	ATLASSERT(lpFormatEtcFill != NULL);
	if (lpFormatEtc == NULL && cfFormat != 0)
	{
		lpFormatEtc = lpFormatEtcFill;
		lpFormatEtc->cfFormat = cfFormat;
		lpFormatEtc->ptd = NULL;
		lpFormatEtc->dwAspect = DVASPECT_CONTENT;
		lpFormatEtc->lindex = -1;
		lpFormatEtc->tymed = (DWORD) -1;
	}
	return lpFormatEtc;
}

bool MtlIsDataAvailable(IDataObject* pDataObject, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc = NULL)
{
	ATLASSERT(pDataObject != NULL);

	// fill in FORMATETC struct
	FORMATETC formatEtc;
	lpFormatEtc = _MtlFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);

	// attempt to get the data
	return pDataObject->QueryGetData(lpFormatEtc) == S_OK;
}

bool MtlGetDropFileName(IDataObject* pDataObject, CSimpleArray<CString>& arrFileNames)
{
	if (!MtlIsDataAvailable(pDataObject, CF_HDROP))
		return false;

	FORMATETC formatetc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
	STGMEDIUM stgmedium;
	HRESULT hr = pDataObject->GetData(&formatetc, &stgmedium);
	if (FAILED(hr) || stgmedium.hGlobal == NULL) {
		return false;
	}

	HDROP hDropInfo = (HDROP)stgmedium.hGlobal;

	UINT nFiles = ::DragQueryFile(hDropInfo, (UINT)-1, NULL, 0);
	for (UINT iFile = 0; iFile < nFiles; iFile++) {
		TCHAR szFileName[_MAX_PATH];
		::DragQueryFile(hDropInfo, iFile, szFileName, _MAX_PATH);
		arrFileNames.Add(CString(szFileName));
	}
	::DragFinish(hDropInfo);// required?
	
	::ReleaseStgMedium(&stgmedium);

	if (arrFileNames.GetSize() > 0)
		return true;
	else
		return false;
}

// Implementation
bool MtlGetHGlobalText(IDataObject* pDataObject, CString& strText, CLIPFORMAT cfFormat = CF_TEXT)
{
	bool bResult = false;

	if (!MtlIsDataAvailable(pDataObject, cfFormat))
		return false;

	FORMATETC formatetc = { cfFormat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
	STGMEDIUM stgmedium;
	HRESULT hr = pDataObject->GetData(&formatetc, &stgmedium);
	if (SUCCEEDED(hr)) {
		if (stgmedium.hGlobal != NULL) {
			HGLOBAL hText = stgmedium.hGlobal;
			strText = reinterpret_cast<LPSTR>(::GlobalLock(hText));
			::GlobalUnlock(hText);
			bResult = true;
		}
		::ReleaseStgMedium(&stgmedium);
	}

	return bResult;
}

// Thanks to www.nakka.com
// Even IE creates a shortcut file for every link, what the hell is OLE.
template <class _InputStringIter>
HDROP MtlCreateDropFile(_InputStringIter __first, _InputStringIter __last)
{
	if (__first == __last)
		return NULL;

	//filename\0...\0filename\0...\0filename\0\0
	int nLen = 0;

	_InputStringIter it;
	for (it = __first; it != __last; ++it) {
		nLen += ::lstrlen(*it);
		nLen += 1;	// for '\0' separator
	}
	nLen += 1;		// for the last '\0'

	HDROP hDrop = (HDROP)::GlobalAlloc(GHND, sizeof(DROPFILES) + nLen*sizeof(TCHAR));
	if (hDrop == NULL)
		return NULL;

	LPDROPFILES lpDropFiles;
	lpDropFiles = (LPDROPFILES)::GlobalLock(hDrop);
	lpDropFiles->pFiles = sizeof(DROPFILES);
	lpDropFiles->pt.x = 0;
	lpDropFiles->pt.y = 0;
	lpDropFiles->fNC = FALSE;

#ifdef _UNICODE
	lpDropFiles->fWide = TRUE;
#else
	lpDropFiles->fWide = FALSE;
#endif

	TCHAR* psz = (TCHAR*)(lpDropFiles + 1);
	for (it = __first; it != __last; ++it) {
		::lstrcpy(psz, (*it));
		psz += ::lstrlen(*it) + 1;// skip a '\0' separator
	}

	::GlobalUnlock(hDrop);
	return hDrop;
}

HDROP MtlCreateDropFile(CSimpleArray<CString>& arrFiles)
{
	if (arrFiles.GetSize() == 0)
		return NULL;

	//filename\0...\0filename\0...\0filename\0\0
	int nLen = 0;

	int i;
	for (i = 0; i < arrFiles.GetSize(); ++i) {
		nLen += arrFiles[i].GetLength();
		nLen += 1;	// for '\0' separator
	}
	nLen += 1;		// for the last '\0'

	HDROP hDrop = (HDROP)::GlobalAlloc(GHND, sizeof(DROPFILES) + nLen*sizeof(TCHAR));
	if (hDrop == NULL)
		return NULL;

	LPDROPFILES lpDropFiles;
	lpDropFiles = (LPDROPFILES)::GlobalLock(hDrop);
	lpDropFiles->pFiles = sizeof(DROPFILES);
	lpDropFiles->pt.x = 0;
	lpDropFiles->pt.y = 0;
	lpDropFiles->fNC = FALSE;

#ifdef _UNICODE
	lpDropFiles->fWide = TRUE;
#else
	lpDropFiles->fWide = FALSE;
#endif

	TCHAR* psz = (TCHAR*)(lpDropFiles + 1);
	for (i = 0; i < arrFiles.GetSize(); ++i) {
		::lstrcpy(psz, arrFiles[i]);
		psz += arrFiles[i].GetLength() + 1;// skip a '\0' separator
	}

	::GlobalUnlock(hDrop);
	return hDrop;
}

/////////////////////////////////////////////////////////////////////////////
// CSafeArray class
typedef const SAFEARRAY* LPCSAFEARRAY;
typedef const VARIANT* LPCVARIANT;
/////////////////////////////////////////////////////////////////////////////
// Helper for initializing CComSafeArray
static bool _MtlCompareSafeArrays(SAFEARRAY* parray1, SAFEARRAY* parray2)
{
	bool bCompare = false;

	// If one is NULL they must both be NULL to compare
	if (parray1 == NULL || parray2 == NULL)
	{
		return parray1 == parray2;
	}

	// Dimension must match and if 0, then arrays compare
	DWORD dwDim1 = ::SafeArrayGetDim(parray1);
	DWORD dwDim2 = ::SafeArrayGetDim(parray2);
	if (dwDim1 != dwDim2)
		return false;
	else if (dwDim1 == 0)
		return true;

	// Element size must match
	DWORD dwSize1 = ::SafeArrayGetElemsize(parray1);
	DWORD dwSize2 = ::SafeArrayGetElemsize(parray2);
	if (dwSize1 != dwSize2)
		return false;

	long* pLBound1 = NULL;
	long* pLBound2 = NULL;
	long* pUBound1 = NULL;
	long* pUBound2 = NULL;

	void* pData1 = NULL;
	void* pData2 = NULL;

	// Bounds must match
	ATLTRY(pLBound1 = new long[dwDim1]);
	ATLTRY(pLBound2 = new long[dwDim2]);
	ATLTRY(pUBound1 = new long[dwDim1]);
	ATLTRY(pUBound2 = new long[dwDim2]);

	size_t nTotalElements = 1;

	// Get and compare bounds
	for (DWORD dwIndex = 0; dwIndex < dwDim1; dwIndex++)
	{
		MtlCheckError(::SafeArrayGetLBound(
			parray1, dwIndex+1, &pLBound1[dwIndex]));
		MtlCheckError(::SafeArrayGetLBound(
			parray2, dwIndex+1, &pLBound2[dwIndex]));
		MtlCheckError(::SafeArrayGetUBound(
			parray1, dwIndex+1, &pUBound1[dwIndex]));
		MtlCheckError(::SafeArrayGetUBound(
			parray2, dwIndex+1, &pUBound2[dwIndex]));

		// Check the magnitude of each bound
		if (pUBound1[dwIndex] - pLBound1[dwIndex] !=
			pUBound2[dwIndex] - pLBound2[dwIndex])
		{
			delete[] pLBound1;
			delete[] pLBound2;
			delete[] pUBound1;
			delete[] pUBound2;

			return false;
		}

		// Increment the element count
		nTotalElements *= pUBound1[dwIndex] - pLBound1[dwIndex] + 1;
	}

	// Access the data
	MtlCheckError(::SafeArrayAccessData(parray1, &pData1));
	MtlCheckError(::SafeArrayAccessData(parray2, &pData2));

	// Calculate the number of bytes of data and compare
	size_t nSize = nTotalElements * dwSize1;
	int nOffset = memcmp(pData1, pData2, nSize);
	bCompare = (nOffset == 0);

	// Release the array locks
	MtlCheckError(::SafeArrayUnaccessData(parray1));
	MtlCheckError(::SafeArrayUnaccessData(parray2));

	// Clean up bounds arrays
	delete[] pLBound1;
	delete[] pLBound2;
	delete[] pUBound1;
	delete[] pUBound2;

	return bCompare;
}
/////////////////////////////////////////////////////////////////////////////
// CComSafeArray class
class CComSafeArray : public tagVARIANT
{
public:
// Data members
	// Cache info to make element access (operator []) faster
	DWORD m_dwElementSize;
	DWORD m_dwDims;

//Constructors
	CComSafeArray()
	{
		_SafeArrayInit(this);
		vt = VT_EMPTY;
	}

	~CComSafeArray()
	{
		Clear();
	}	

	CComSafeArray(const SAFEARRAY& saSrc, VARTYPE vtSrc)
	{
		_SafeArrayInit(this);
		vt = (VARTYPE)(vtSrc | VT_ARRAY);
		MtlCheckError(::SafeArrayCopy((LPSAFEARRAY)&saSrc, &parray));
		m_dwDims = GetDim();
		m_dwElementSize = GetElemSize();
	}

	CComSafeArray(LPCSAFEARRAY pSrc, VARTYPE vtSrc)
	{
		_SafeArrayInit(this);
		vt = (VARTYPE)(vtSrc | VT_ARRAY);
		MtlCheckError(::SafeArrayCopy((LPSAFEARRAY)pSrc, &parray));
		m_dwDims = GetDim();
		m_dwElementSize = GetElemSize();
	}

	CComSafeArray(const CComSafeArray& saSrc)
	{
		_SafeArrayInit(this);
		*this = saSrc;
		m_dwDims = GetDim();
		m_dwElementSize = GetElemSize();
	}

	CComSafeArray(const VARIANT& varSrc)
	{
		_SafeArrayInit(this);
		*this = varSrc;
		m_dwDims = GetDim();
		m_dwElementSize = GetElemSize();
	}

	CComSafeArray(LPCVARIANT pSrc)
	{
		_SafeArrayInit(this);
		*this = pSrc;
		m_dwDims = GetDim();
		m_dwElementSize = GetElemSize();
	}

	void _SafeArrayInit(CComSafeArray* psa)
	{
		::memset(psa, 0, sizeof(*psa));
	}

	void Clear()

⌨️ 快捷键说明

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