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

📄 atldataobj.h

📁 remote debug and compile tools
💻 H
字号:
#if !defined(AFX_ATLDATAOBJ_H__20040706_4F49_248D_7C5E_0080AD509054__INCLUDED_)
#define AFX_ATLDATAOBJ_H__20040706_4F49_248D_7C5E_0080AD509054__INCLUDED_

#pragma once

/////////////////////////////////////////////////////////////////////////////
// IDataObject and OLE clipboard wrappers
//
// Written by Bjarke Viksoe (bjarke@viksoe.dk)
// Copyright (c) 2004 Bjarke Viksoe.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed by any means PROVIDING it is 
// not sold for profit without the authors written consent, and 
// providing that this notice and the authors name is included. 
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage to you or your
// computer whatsoever. It's free, so don't hassle me about it.
//
// Beware of bugs.
//

/////////////////////////////////////////////////////////////////////////
// Misc clipboard functions

#ifdef __ATLCONV_H__

inline BOOL AtlSetClipboardText(HWND hWnd, LPCTSTR pstrText)
{
   USES_CONVERSION;
   HGLOBAL hGlobal = GlobalAlloc(GMEM_FIXED, ::lstrlen(pstrText) + 1);
   if( hGlobal == NULL ) return FALSE;
   CopyMemory(hGlobal, T2CA(pstrText), ::lstrlen(pstrText) + 1);
   if( !::OpenClipboard(hWnd) ) return FALSE;
   ::EmptyClipboard();
   ::SetClipboardData(CF_TEXT, hGlobal);
   ::CloseClipboard();
   return TRUE;
}

#endif // __ATLCONV_H__


/////////////////////////////////////////////////////////////////////////
// CRawDropSource

class CRawDropSource : public IDropSource
{
public:
   // IUnknown

   STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObject)
   {
      if( riid == __uuidof(IDropSource) || riid == IID_IUnknown ) {
         *ppvObject = this;
         return S_OK;
      }
      return E_NOINTERFACE;
   }
   ULONG STDMETHODCALLTYPE AddRef()
   {
      return 1;
   }
   ULONG STDMETHODCALLTYPE Release()
   {
      return 1;
   }

   // IDropSource

   STDMETHOD(QueryContinueDrag)(BOOL bEsc, DWORD dwKeyState)
   {
      if( bEsc ) return ResultFromScode(DRAGDROP_S_CANCEL);
      if( (dwKeyState & MK_LBUTTON) == 0 ) return ResultFromScode(DRAGDROP_S_DROP);
      return S_OK;
   }
   STDMETHOD(GiveFeedback)(DWORD)
   {
      return ResultFromScode(DRAGDROP_S_USEDEFAULTCURSORS);
   }
};


//////////////////////////////////////////////////////////////////////////////
// IRawDropTarget

template< class T >
class ATL_NO_VTABLE IRawDropTarget : public IDropTarget
{
public:
   IRawDropTarget() : m_hwndTarget(NULL), m_fAcceptFmt(false), nFormats(0)
   { 
   }

   HRESULT RegisterDropTarget(HWND hWnd)
   {
      m_hwndTarget = hWnd;
      ::RegisterDragDrop(m_hwndTarget, this);
      return S_OK;
   }
   void RevokeDropTarget()
   {
      ::RevokeDragDrop(m_hwndTarget);
   }
   void AddDropFormat(FORMATETC fe)
   {
      if( nFormats >= sizeof(m_Formats) / sizeof(FORMATETC) ) return;
      m_Formats[nFormats++] = fe;
   }
   FORMATETC GetDropFormat(int iIndex) const
   {
      FORMATETC fe = { 0 };
      if( iIndex < 0 || iIndex >= nFormats) return fe;
      return m_Formats[iIndex];
   }

   // Attributes

   HWND m_hwndTarget;
   bool m_fAcceptFmt;
   FORMATETC m_Formats[8];
   int nFormats;

   // IUnknown

   STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObject)
   {
      if( riid == __uuidof(IDropTarget) || riid == IID_IUnknown ) {
         *ppvObject = this;
         return S_OK;
      }
      return E_NOINTERFACE;
   }
   ULONG STDMETHODCALLTYPE AddRef()
   {
      return 1;
   }
   ULONG STDMETHODCALLTYPE Release()
   {
      return 1;
   }

   // IDropTarget

   STDMETHOD(DragEnter)(LPDATAOBJECT pDataObj, 
                        DWORD dwKeyState, 
                        POINTL, 
                        LPDWORD pdwEffect)
   {
      // Does the drag source provide our CF types?
      m_fAcceptFmt = false;
      for( int i = 0; !m_fAcceptFmt && i < nFormats; i++ ) {
         FORMATETC fe = m_Formats[i];
         m_fAcceptFmt = (S_OK == pDataObj->QueryGetData(&fe));
      }
      *pdwEffect = _QueryDrop(dwKeyState, *pdwEffect);
      return S_OK;
   }
   STDMETHOD(DragOver)(DWORD dwKeyState, POINTL /*pt*/, LPDWORD pdwEffect)
   {
      *pdwEffect = _QueryDrop(dwKeyState, *pdwEffect);
      return S_OK;
   } 
   STDMETHOD(DragLeave)(VOID)
   {
      m_fAcceptFmt = false;
      return S_OK;
   }
   STDMETHOD(Drop)(LPDATAOBJECT pDataObj,
                   DWORD dwKeyState,
                   POINTL /*pt*/,
                   LPDWORD pdwEffect)
   {
      // Determine drop effect...
      DWORD dwDropEffect = _QueryDrop(dwKeyState, *pdwEffect);
      *pdwEffect = DROPEFFECT_NONE; // Default to failed/cancelled
      // Did we accept this drop effect?
      if( dwDropEffect == DROPEFFECT_NONE ) return S_OK;
      // Do the drop...
      T* pT = static_cast<T*>(this);
      BOOL bRes = pT->DoDrop(pDataObj);
      *pdwEffect = bRes ? dwDropEffect : DROPEFFECT_NONE;
      return bRes ? S_OK : E_FAIL;
   }

   // Implementation

   DWORD _QueryDrop(DWORD dwKeyState, DWORD dwEffect) const
   {
      if( !m_fAcceptFmt ) return DROPEFFECT_NONE;
      // Test key-state
      DWORD dwMask = _GetDropEffectFromKeyState(dwKeyState);
      if( (dwEffect & dwMask) != 0 ) return dwEffect & dwMask;
      // Map common alternatives
      if( (dwEffect & DROPEFFECT_COPY) != 0 ) return DROPEFFECT_COPY;
      // Drop-effect is determined by keys or default
      return dwMask;
   }
   DWORD _GetDropEffectFromKeyState(DWORD dwKeyState) const
   {
      // We don't support DROPEFFECT_LINK or DROPEFFECT_MOVE operations
      DWORD dwDropEffect = DROPEFFECT_COPY;
      if( (dwKeyState & MK_CONTROL) != 0 ) dwDropEffect = DROPEFFECT_COPY;
      return dwDropEffect;
   }
};


#ifdef __ATLCOM_H__

//////////////////////////////////////////////////////////////////////////////
// CEnumFORMATETC

class ATL_NO_VTABLE CEnumFORMATETC : 
   public CComObjectRootEx<CComSingleThreadModel>,
   public IEnumFORMATETC
{
public:
   CSimpleValArray<FORMATETC> m_aFmtEtc;
   ULONG m_iCur;

   BEGIN_COM_MAP(CEnumFORMATETC)
      COM_INTERFACE_ENTRY(IEnumFORMATETC)
   END_COM_MAP()

public:
   CEnumFORMATETC() : m_iCur(0)
   {
   }

   void Add(FORMATETC& fmtc)
   {
      m_aFmtEtc.Add(fmtc);
   }

   // IEnumFORMATETC

   STDMETHOD(Next)(ULONG celt, LPFORMATETC lpFormatEtc, ULONG* pceltFetched)
   {
      if( pceltFetched != NULL) *pceltFetched = 0;
      if( lpFormatEtc == NULL ) return E_INVALIDARG;
      if( celt <= 0 || m_iCur >= (ULONG) m_aFmtEtc.GetSize() ) return S_FALSE;
      if( pceltFetched == NULL && celt != 1 ) return S_FALSE;
      ULONG nCount = 0;
      while( m_iCur < (ULONG) m_aFmtEtc.GetSize() && celt > 0 ) {
         *lpFormatEtc++ = m_aFmtEtc[m_iCur++];
         --celt;
         ++nCount;
      }
      if( pceltFetched != NULL ) *pceltFetched = nCount;
      return celt == 0 ? S_OK : S_FALSE;
   }
   STDMETHOD(Skip)(ULONG celt)
   {
      if( m_iCur + celt >= (ULONG) m_aFmtEtc.GetSize() ) return S_FALSE;
      m_iCur += celt;
      return S_OK;
   }
   STDMETHOD(Reset)(void)
   {
      m_iCur = 0;
      return S_OK;
   }
   STDMETHOD(Clone)(IEnumFORMATETC FAR * FAR*)
   {
      ATLTRACENOTIMPL(_T("CEnumFORMATETC::Clone"));
   }
};


//////////////////////////////////////////////////////////////////////////////
// CSimpleDataObj

template< class T >
class ATL_NO_VTABLE ISimpleDataObjImpl : public IDataObject
{
public:
   typedef struct DATAOBJ
   {
      FORMATETC FmtEtc;
      STGMEDIUM StgMed;
      BOOL bRelease;
   };
   CSimpleValArray<DATAOBJ> m_aObjects;

   ~ISimpleDataObjImpl()
   {
      for( int i = 0; i < m_aObjects.GetSize(); i++ ) ::ReleaseStgMedium(&m_aObjects[i].StgMed);
   }

   STDMETHOD(GetData)(FORMATETC* pformatetcIn, STGMEDIUM* pmedium)
   {
      ATLTRACE2(atlTraceControls,2,_T("ISimpleDataObjImpl::GetData\n"));
      T* pT = (T*) this;
      return pT->IDataObject_GetData(pformatetcIn, pmedium);
   }
   STDMETHOD(GetDataHere)(FORMATETC* /*pformatetc*/, STGMEDIUM* /*pmedium*/)
   {
      ATLTRACENOTIMPL(_T("ISimpleDataObjImpl::GetDataHere"));
   }
   STDMETHOD(QueryGetData)(FORMATETC* pformatetc)
   {
      ATLASSERT(pformatetc);
      int iIndex = _Find(pformatetc);
      if( iIndex < 0 ) return DV_E_FORMATETC;
      // BUG: Only supports one media pr format!
      if( m_aObjects[iIndex].FmtEtc.lindex != -1 ) return DV_E_LINDEX;
      if( m_aObjects[iIndex].FmtEtc.tymed != pformatetc->tymed ) return DV_E_TYMED;
      return S_OK;
   }
   STDMETHOD(GetCanonicalFormatEtc)(FORMATETC* pformatectIn, FORMATETC* /* pformatetcOut */)
   {
      pformatectIn->ptd = NULL;
      ATLTRACENOTIMPL(_T("ISimpleDataObjImpl::GetCanonicalFormatEtc"));
   }
   STDMETHOD(SetData)(FORMATETC* pformatetc, STGMEDIUM* pmedium, BOOL fRelease)
   {
      ATLASSERT(pformatetc);
      ATLASSERT(pmedium);
      if( pformatetc == NULL ) return E_POINTER;
      if( pmedium == NULL ) return E_POINTER;
      DATAOBJ obj;
      obj.FmtEtc = *pformatetc;
      obj.StgMed = *pmedium;
      obj.bRelease = fRelease;
      if( !fRelease ) _CopyStgMedium(&obj.StgMed, pmedium, pformatetc);
      int iIndex = _Find(pformatetc);
      if( iIndex < 0 ) m_aObjects.Add(obj); else m_aObjects.SetAtIndex(iIndex, obj);
      return S_OK;
   }
   STDMETHOD(EnumFormatEtc)(DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc)
   {
      ATLASSERT(ppenumFormatEtc);
      if( ppenumFormatEtc == NULL ) return E_POINTER;
      *ppenumFormatEtc = NULL;
      if( dwDirection != DATADIR_GET ) return E_NOTIMPL;
      CComObject<CEnumFORMATETC>* pEnum = NULL;
      if( FAILED( CComObject<CEnumFORMATETC>::CreateInstance(&pEnum) ) ) return E_FAIL;
      for( int i = 0; i < m_aObjects.GetSize(); i++ ) pEnum->Add(m_aObjects[i].FmtEtc);
      return pEnum->QueryInterface(ppenumFormatEtc);
   }
   STDMETHOD(DAdvise)(FORMATETC* /*pformatetc*/, DWORD /*advf*/, IAdviseSink* /*pAdvSink*/, DWORD* /*pdwConnection*/)
   {
      ATLTRACENOTIMPL(_T("ISimpleDataObjImpl::DAdvise"));
   }
   STDMETHOD(DUnadvise)(DWORD dwConnection)
   {
      ATLTRACENOTIMPL(_T("ISimpleDataObjImpl::DUnadvise"));
   }
   STDMETHOD(EnumDAdvise)(IEnumSTATDATA** /*ppenumAdvise*/)
   {
      ATLTRACENOTIMPL(_T("ISimpleDataObjImpl::EnumDAdvise"));
   }

   // Helper functions

   int _Find(FORMATETC* pformatetc) const
   {
      for( int i = 0; i < m_aObjects.GetSize(); i++ ) {
         if( m_aObjects[i].FmtEtc.cfFormat == pformatetc->cfFormat ) return i;
      }
      return -1;
   }
   HRESULT _CopyStgMedium(STGMEDIUM* pMedDest, STGMEDIUM* pMedSrc, FORMATETC* pFmtSrc)
   {
      switch( pMedSrc->tymed ) {
      case TYMED_GDI:
      case TYMED_FILE:
      case TYMED_ENHMF:
      case TYMED_MFPICT:
      case TYMED_HGLOBAL:
         pMedDest->hGlobal = (HGLOBAL) ::OleDuplicateData(pMedSrc->hGlobal, pFmtSrc->cfFormat, NULL);
         break;
      case TYMED_ISTREAM:
         {
            pMedDest->pstm = NULL;
            if( FAILED( ::CreateStreamOnHGlobal(NULL, TRUE, &pMedDest->pstm) ) ) return E_OUTOFMEMORY;
            ULARGE_INTEGER alot = { 0, INT_MAX };
            if( FAILED( pMedSrc->pstm->CopyTo(pMedDest->pstm, alot, NULL, NULL) ) ) return E_FAIL;
         }
         break;
      case TYMED_ISTORAGE:
         {
            pMedDest->pstg = NULL;
            if( FAILED( ::StgCreateDocfile(NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE | STGM_CREATE, 0, &pMedDest->pstg) ) ) return E_OUTOFMEMORY;
            if( FAILED( pMedSrc->pstg->CopyTo(0, NULL, NULL, pMedDest->pstg) ) ) return E_FAIL;
         }
         break;
      default:
         ATLASSERT(false);
         return DV_E_TYMED;
      }
      pMedDest->tymed = pMedSrc->tymed;
      pMedDest->pUnkForRelease = pMedSrc->pUnkForRelease;
      return S_OK;
   }
};

class ATL_NO_VTABLE CSimpleDataObj : 
   public CComObjectRootEx<CComSingleThreadModel>,
   public ISimpleDataObjImpl<CSimpleDataObj>
{
public:
   BEGIN_COM_MAP(CSimpleDataObj)
      COM_INTERFACE_ENTRY(IDataObject)
   END_COM_MAP()

   HRESULT IDataObject_GetData(FORMATETC* pformatetc, STGMEDIUM* pmedium)
   {
      ATLASSERT(pmedium);
      ATLASSERT(pformatetc);
      int iIndex = _Find(pformatetc);
      if( iIndex < 0 ) return DV_E_FORMATETC;
      if( pformatetc->lindex != -1 ) return DV_E_LINDEX;
      if( (m_aObjects[iIndex].FmtEtc.tymed & pformatetc->tymed) == 0 ) return DV_E_LINDEX;
      return _CopyStgMedium(pmedium, &m_aObjects[iIndex].StgMed, &m_aObjects[iIndex].FmtEtc);
   }

   // Operations

   HRESULT SetGlobalData(CLIPFORMAT cf, LPCVOID pData, DWORD dwSize)
   {
      FORMATETC fmtetc = { cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
      STGMEDIUM stgmed = { TYMED_HGLOBAL, { 0 }, 0 };
      stgmed.hGlobal = ::GlobalAlloc(GMEM_FIXED, (SIZE_T) dwSize);
      if( stgmed.hGlobal == NULL ) return E_OUTOFMEMORY;
      memcpy(stgmed.hGlobal, pData, (size_t) dwSize);
      return SetData(&fmtetc, &stgmed, TRUE);
   }
   HRESULT SetTextData(LPCSTR pstrData)
   {
      return SetGlobalData(CF_TEXT, pstrData, ::lstrlenA(pstrData) + 1);
   }
   HRESULT SetUnicodeTextData(LPCWSTR pstrData)
   {
      return SetGlobalData(CF_UNICODETEXT, pstrData, (::lstrlenW(pstrData) + 1) * sizeof(WCHAR));
   }
   HRESULT SetHDropData(LPCSTR pstrFilename)
   {
      FORMATETC fmtetc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
      STGMEDIUM stgmed = { TYMED_HGLOBAL, { 0 }, 0 };
      DWORD dwSize = sizeof(DROPFILES) + ::lstrlenA(pstrFilename) + 2;
      stgmed.hGlobal = ::GlobalAlloc(GMEM_SHARE | GHND | GMEM_ZEROINIT, dwSize);
      if( stgmed.hGlobal == NULL ) return E_OUTOFMEMORY;
      DROPFILES* pDest = (DROPFILES*) GlobalLock(stgmed.hGlobal);
      pDest->pFiles = sizeof(DROPFILES);
      pDest->fWide = FALSE;
      ::lstrcpyA( ((LPSTR) pDest) + sizeof(DROPFILES), pstrFilename );
      GlobalUnlock(stgmed.hGlobal);
      return SetData(&fmtetc, &stgmed, TRUE);
   }
};

#endif // __ATLCOM_H__


#endif // !defined(AFX_ATLDATAOBJ_H__20040706_4F49_248D_7C5E_0080AD509054__INCLUDED_)

⌨️ 快捷键说明

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