DragSource Lib for BCB(DragDrop.cpp)

// ---------------------------------------------------------------------------
//  DragSource Lib.
//  Copyright (c) 2006, 2007 by Mao yongjun
//  All rights reserved
//  Add "WINOLEAPI OleInitialize (LPVOID pvReserved)" before use DragDropLib on each thread
//  Don't forget "WINOLEAPI OleUninitialize ()" on exit the thread
// ---------------------------------------------------------------------------

#pragma  hdrstop

#include 
" DragDrop.h "
#pragma  package(smart_init)

void *  THDROP_Files::Create_HDROP()  const
{
    
struct TMyDropFiles{
        DWORD pFiles;
        POINT pt;
        BOOL fNC;
        BOOL fWide;
        
char szFiles[1];
    }
;

    size_t MemSize
=0;
    
for(const_iterator i=begin();i!=end();i++)
    
{
        MemSize
+=i->length();
        MemSize
++;
    }


    
void* ptr=GlobalAlloc(GMEM_FIXED,sizeof(TMyDropFiles)+MemSize);
    ZeroMemory(ptr,
sizeof(TMyDropFiles)+MemSize);

    TMyDropFiles 
*FileNames=new (ptr)TMyDropFiles;
    FileNames
->pFiles=(unsigned)FileNames->szFiles - (unsigned)(&FileNames->pFiles);

    
char *p=FileNames->szFiles;
    
for(const_iterator i=begin();i!=end();i++)
    
{
        size_t len
=i->length();
        CopyMemory(p,i
->c_str(),len);
        p
+=len;
        
*(p++)=0;
    }

    
*p=0;

    
return ptr;
}

// ------------------------------TDropSource---------------------------------------------
HANDLE MemToHandle ( void   * pMem,  int  nSize)
{
    
void* ptr=GlobalAlloc(GMEM_FIXED, nSize);
    CopyMemory(ptr, pMem, nSize);
    
return ptr;
}


HRESULT __stdcall TDropSource::QueryInterface(REFIID iid, 
void   ** ppv)
{
    
if((iid==IID_IUnknown)||(iid==IID_IDropSource))
    
{
        
*ppv=this;
        AddRef();
    }

    
else
    
{
        
*ppv=NULL;
        
return E_NOINTERFACE;
    }

    
return S_OK;
}


HRESULT __stdcall TDropSource::QueryContinueDrag(BOOL fEscapePressed,DWORD grfKeyState)
{
    
return fEscapePressed?DRAGDROP_S_CANCEL:((grfKeyState&MK_LBUTTON)?S_OK:DRAGDROP_S_DROP);
}


HRESULT __stdcall TDropSource::GiveFeedback(DWORD dwEffect)
{
    
return DRAGDROP_S_USEDEFAULTCURSORS;
}

// -------------------------------TDataObject--------------------------------------------
HGLOBAL DupGlobalMem (HGLOBAL hMem)
{
    DWORD   len    
= GlobalSize (hMem);
    PVOID   source 
= GlobalLock (hMem);
    PVOID   dest   
= GlobalAlloc (GMEM_FIXED, len);
    memcpy (dest, source, len);
    GlobalUnlock (hMem);
    
return dest;
}


HRESULT CreateDataObject (FORMATETC 
* fmtetc, STGMEDIUM  * stgmeds, UINT count, IDataObject  ** ppDataObject)
{
    
if(ppDataObject == 0)
        
return E_INVALIDARG;

    
*ppDataObject = new TDataObject;
    ((TDataObject 
*)(*ppDataObject))->Add(fmtetc, stgmeds, count);
    
return (*ppDataObject) ? S_OK : E_OUTOFMEMORY;
}


HRESULT __stdcall TDataObject::QueryInterface(REFIID iid, 
void   ** ppv)
{
    
if((iid==IID_IUnknown)||(iid==IID_IDataObject))
    
{
        
*ppv=this;
        AddRef();
        
return S_OK;
    }

    
else
    
{
        
*ppv=NULL;
        
return E_NOINTERFACE;
    }

}


HRESULT __stdcall TDataObject::QueryGetData(FORMATETC 
* pFormatEtc)
{
    
return (LookupFormatEtc(pFormatEtc) == -1? DV_E_FORMATETC : S_OK;
}


HRESULT __stdcall TDataObject::GetData (FORMATETC 
* pFormatEtc, STGMEDIUM  * pStgMedium)
{
    
int idx;
    
if((idx = LookupFormatEtc(pFormatEtc)) == -1)
        
return DV_E_FORMATETC;

    pStgMedium
->tymed           = _pFormatEtc[idx].tymed;
    pStgMedium
->pUnkForRelease  = 0;

    
switch(_pFormatEtc[idx].tymed)
    
{
    
case TYMED_HGLOBAL:
        pStgMedium
->hGlobal = DupGlobalMem(_pStgMedium[idx].hGlobal);
        
break;
    
case TYMED_GDI:
        pStgMedium
->hBitmap = CopyImage(_pStgMedium[idx].hBitmap,IMAGE_BITMAP,0,0,0);
        
break;
    
default:
        
return DV_E_FORMATETC;
    }

    
return S_OK;
}


int  TDataObject::LookupFormatEtc(FORMATETC  * pFormatEtc)
{
    
// 轮流检查格式看是否能找到匹配的格式
    for(size_t i = 0; i < _pFormatEtc.size(); i++)
    
{
        
if((_pFormatEtc[i].tymed & pFormatEtc->tymed)   &&
            _pFormatEtc[i].cfFormat 
== pFormatEtc->cfFormat &&
            _pFormatEtc[i].dwAspect 
== pFormatEtc->dwAspect)
        
{
            
return i;
        }

    }

    
return -1;
}


HRESULT __stdcall TDataObject::EnumFormatEtc (DWORD dwDirection, IEnumFORMATETC 
** ppEnumFormatEtc)
{
    
// OLE仅仅支持得到方向成员
    if(dwDirection == DATADIR_GET)
    
{
        
// 在WIN2K下,你可以调用API函数SHCreateStdEnumFmtEtc来完成,但为了支持//所有的window平台,我们需要实现IEnumFormatEtc。
        return CreateEnumFormatEtc(_pFormatEtc.size(), &_pFormatEtc[0], ppEnumFormatEtc);
    }

    
else
    
{
        
// the direction specified is not supported for drag+drop
        return E_NOTIMPL;
    }

}


void  TDataObject::Add(CLIPFORMAT ctFormat,DWORD tymed, void   * hStorage)
{
    FORMATETC fmtetc 
= {
        ctFormat,            
// we will be dropping some text
        0,
        DVASPECT_CONTENT,
        
-1,
        tymed       
// stored as a HGLOBAL
    }
;
    STGMEDIUM stgmed 
= {
        tymed,
        
{hStorage},
        
0
    }
;
    _pFormatEtc.push_back(fmtetc);
    _pStgMedium.push_back(stgmed);
}


void  TDataObject::Add(FORMATETC  * fmtetc, STGMEDIUM  * stgmeds, UINT count = 1 )
{
    
for(UINT i=0;i<count;i++)
    
{
        _pFormatEtc.push_back(fmtetc[i]);
        _pStgMedium.push_back(stgmeds[i]);
    }

}

void  TDataObject::Clear()
{
    _pFormatEtc.clear();
    _pStgMedium.clear();
}

void  TDataObject::ClearAndRelease()
{
    
for(size_t i=0;i<_pFormatEtc.size();i++)
        ReleaseStgMedium(
&_pStgMedium[i]);
    Clear();
}



// -------------------------------TEnumFormatEtc--------------------------------------------
HRESULT CreateEnumFormatEtc (UINT cfmt, FORMATETC  * afmt, IEnumFORMATETC  ** ppEnumFormatEtc)
{
    
if (cfmt == 0 || afmt == 0 || ppEnumFormatEtc == 0)
        
return E_INVALIDARG;
    
*ppEnumFormatEtc = new TEnumFormatEtc (afmt, cfmt);
    
if(*ppEnumFormatEtc)
    
{
        
return S_OK;
    }

    
else
    
{
        
return E_OUTOFMEMORY;
    }

}


void  DeepCopyFormatEtc(FORMATETC  * dest, FORMATETC  * source)
{
    
// copy the source FORMATETC into dest
    *dest = *source;
    
if(source->ptd)
    
{
        
// allocate memory for the DVTARGETDEVICE if necessary
        dest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE));
        
// copy the contents of the source DVTARGETDEVICE into dest->ptd
        *(dest->ptd) = *(source->ptd);
    }

}

TEnumFormatEtc::TEnumFormatEtc(FORMATETC 
* pFormatEtc, ULONG nNumFormats)
    :_iRefCount(
1 ),_nIndex( 0 ),_nNumFormats(nNumFormats)
{
    _pFormatEtc  
= new FORMATETC[nNumFormats];
    
// make a new copy of each FORMATETC structure
    for(ULONG i = 0; i < nNumFormats; i++)
    
{
        DeepCopyFormatEtc (
&_pFormatEtc[i], &pFormatEtc[i]);
    }

}

TEnumFormatEtc::
~ TEnumFormatEtc()
{
    
// first free any DVTARGETDEVICE structures
    for(ULONG i = 0; i < _nNumFormats; i++)
    
{
        
if(_pFormatEtc[i].ptd)
            CoTaskMemFree(_pFormatEtc[i].ptd);
    }

    
// now free the main array
    delete[] _pFormatEtc;
}

HRESULT __stdcall TEnumFormatEtc::Next(ULONG celt, FORMATETC 
* pFormatEtc, ULONG  * pceltFetched)
{
    ULONG copied 
= 0;
    
// copy the FORMATETC structures into the caller's buffer
    while (_nIndex < _nNumFormats && copied < celt)
    
{
        DeepCopyFormatEtc (
&pFormatEtc [copied], &_pFormatEtc [_nIndex]);
        copied
++;
        _nIndex
++;
    }

    
// store result
    if(pceltFetched != 0
        
*pceltFetched = copied;
    
// did we copy all that was requested?
    return (copied == celt) ? S_OK : S_FALSE;
}


TDropResult DoDragDrop(FORMATETC 
* fmtetc, STGMEDIUM  * stgmeds,UINT count,DWORD dwOKEffect)
{
    IDropSource 
*pDropSource=new TDropSource;
    TDataObject 
*pDataObject=new TDataObject();
    pDataObject
->Add(fmtetc, stgmeds, count);
    DWORD dwEffect;
    DWORD dwResult 
= DoDragDrop(pDataObject, pDropSource, dwOKEffect, &dwEffect);

    pDropSource
->Release();
    pDataObject
->Release();

    TDropResult Result
={dwResult,dwEffect};
    
return Result;
}


TDropResult DoDragDrop(CLIPFORMAT ctFormat,DWORD tymed,
void   * hStorage,DWORD dwOKEffect)
{
    FORMATETC fmtetc 
= {
        ctFormat,
        
0,
        DVASPECT_CONTENT,
        
-1,
        tymed
    }
;
    STGMEDIUM stgmed 
= {
        tymed,
        
{hStorage},
        
0
    }
;
    TDropResult Result
= DoDragDrop(&fmtetc,&stgmed,1,dwOKEffect);
    ReleaseStgMedium(
&stgmed);
    
return Result;
}


TDropResult DoDragDrop(
char   * szText,DWORD dwOKEffect)
{
    
return DoDragDrop(
        CF_TEXT,
        TYMED_HGLOBAL,
        MemToHandle(szText, strlen(szText)
+1),               //Freed
        dwOKEffect
        );
}


TDropResult DoDragDropURL(
char   * URL,DWORD dwOKEffect)
{
    
return DoDragDrop(
        RegisterClipboardFormat(
"UniformResourceLocator"),
        TYMED_HGLOBAL,
        MemToHandle(URL, strlen(URL)
+1),               //Freed
        dwOKEffect
        );
}


TDropResult DoDragDrop(wchar_t 
* wszText,DWORD dwOKEffect)
{
    
return DoDragDrop(
        CF_UNICODETEXT,
        TYMED_HGLOBAL,
        MemToHandle (wszText, wcslen(wszText)
*2+2),         //Freed
        dwOKEffect
        );
}


TDropResult DoDragDrop(HBITMAP hBitmap,DWORD dwOKEffect)
{
    FORMATETC fmtetc 
= {
        CF_BITMAP,
        
0,
        DVASPECT_CONTENT,
        
-1,
        TYMED_GDI
    }
;
    STGMEDIUM stgmed 
= {
        TYMED_GDI,
        
{hBitmap},
        
0
    }
;
    TDropResult Result 
= DoDragDrop(&fmtetc,&stgmed,1,dwOKEffect);
    
return Result;
}


TDropResult DoDragDrop(
const  THDROP_Files  & files,
        DWORD dwOKEffect)
{
    
return DoDragDrop(
        CF_HDROP,
        TYMED_HGLOBAL,
        files.Create_HDROP(),
        dwOKEffect
        );
}


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值