对于文件在窗口之间拖放的补充

来源:互联网 发布:Ubuntu 办公软件 编辑:程序博客网 时间:2024/05/22 17:42

之前使用网上下载的CDataSource、CDataObject—等等类实现了 对文件拖放的目的。

然而,此类原码竟是VC++代码。并且拖放时,鼠标下文件图标的显示也并不能实现。因此,自己从收集到的资料BCB的原码。

拖放的原码网上比较多,且简单。因此在此说明一下对于显示图标的步骤:

首先,对于CDataObject类的SetData方法,不能把非TYMED_HGLOBAL数据排除在外。

HRESULT __stdcall cdataobject::SetData (FORMATETC *pFormatEtc, STGMEDIUM *pMedium,  BOOL fRelease)
{
        HRESULT res=FindFormatEtc(pFormatEtc,pMedium,true);
        if (m_pStgMedium[res].tymed)
        {
                ReleaseStgMedium ( &m_pStgMedium[res] );
                ZeroMemory (&m_pStgMedium[res], sizeof(STGMEDIUM) );
        }     
        m_pStgMedium[res]=*pMedium;
        m_pFormatEtc[res].tymed=m_pStgMedium[res].tymed;
        if(m_pStgMedium[res].tymed==TYMED_HGLOBAL)
        {
        m_pStgMedium[res].hGlobal=DupMem(pMedium->hGlobal);//必须分配足够的内存空间和拷贝数据。
        }
        if(GetCanonicalIUnknown(m_pStgMedium[res].pUnkForRelease)==
             GetCanonicalIUnknown(static_cast<IDataObject*>(this)))
        {
            m_pStgMedium[res].pUnkForRelease->Release();
            m_pStgMedium[res].pUnkForRelease = NULL;
            return S_OK;
        }
        return  S_OK;
}

其次 ,在BragBegin中写入图形

IDataObject *pDataObject;
                IDropSource *pDropSource;
                DWORD   dwEffect;
                DWORD   dwResult;
               
                //
                //      STGMEDIUM  TYMED_HGLOBAL
                //
                FORMATETC fmtetc = { CF_HDROP|CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
                STGMEDIUM stgmed = { TYMED_HGLOBAL, { 0 }, 0 };
                HGLOBAL hMem = GlobalAlloc(GHND|GMEM_SHARE,(DWORD) (sizeof(DROPFILES)+_MAX_PATH+1));
                LPDROPFILES pDropFiles= (LPDROPFILES)GlobalLock(hMem);
                pDropFiles->pFiles = sizeof(DROPFILES);
            pDropFiles->fWide=FALSE;
                lstrcpy((LPSTR)((LPSTR)(pDropFiles)+sizeof(DROPFILES)),TEXT(filename));
                ((LPSTR)pDropFiles)[sizeof(DROPFILES)+strlen(filename)]=0;
                GlobalUnlock(hMem);
                stgmed.hGlobal=hMem;
                 
                CreateDropSource(&pDropSource);
                CreateDataObject(&fmtetc,&stgmed,1,&pDataObject);

                IDragSourceHelper  *pDragSrcHlp=NULL;
                CoCreateInstance(CLSID_DragDropHelper, NULL,CLSCTX_ALL
                       , IID_IDragSourceHelper, (LPVOID *)&pDragSrcHlp);
                if(pDragSrcHlp)
                {
                        SHDRAGIMAGE image={{50,50},{25,25},NULL,0xffffffff};
                        BYTE bits[50][50][4];
                        for(int n=0;n<50;n++)for(int m=0;m<50;m++)
                        {
                                bits[m][n][0]=m;
                                bits[m][n][1]=255-m*2;
                                bits[m][n][2]=255;
                                bits[m][n][3]=255;
                        }
                        image.hbmpDragImage = CreateBitmap(50, 50, 1, 32, bits);
                        pDragSrcHlp->InitializeFromBitmap(&image,pDataObject);
                }
                else    pDragSrcHlp = 0;
                DoDragDrop(pDataObject,pDropSource,DROPEFFECT_COPY|DROPEFFECT_MOVE,&dwEffect);
               
                pDragSrcHlp->Release();
                pDataObject->Release();
                pDropSource->Release();
                return true;
使用到MS的IDragSourceHelper类使写程序更方便,不过该类的具体操作还是不了解。

关键的一步就是pDragSrcHlp->InitializeFromBitmap,使数据写入STGMEDIUM结构中。

再次,在CDataObject的GetData方法里,需要对某些数据执行累加函数。
如:

case TYMED_ISTREAM:
                pMedium->pstm->AddRef();
                break;
        case TYMED_ISTORAGE:
                pMedium->pstg->AddRef();
                break;

特别注意的一点是: 在拖文件时, 将文件名写入内存,在多文件的情况下,需要以两个字节结尾,即 '00'.否则有乱码

如果各位有些好的思路和想法,可以给我流言:EMAIL :programuser@citiz.net   QQ:694796939

 

 

原创粉丝点击