描述:
我想实现类似WinRAR中将目录/文件拖拽出来的功能,实现方法如下:
(1) 继承了MFC的COleDropSource,并实现了其中的QueryContinueDrag(...)接口,
用来设置Drop标志(鼠标左键释放)。
(2) 继承了MFC的COleDataSource,并实现了其中的OnRenderGlobalData(...)接口,
用来延迟提供数据。
(3) 调用pcDataSource->DelayRenderData(CF_HDROP),设置数据格式。
(4) 调用pcDataSource->DoDragDrop(...),开始DragDrop。
(5) 在pcDropSource->QueryContinueDrag(...)返回DRAGDROP_S_DROP后,
在pcDataSource->OnRenderGlobalData(...)中提供实际数据。
我发现pcDataSource->OnRenderGlobalData(...)接口会被系统频繁调用,即使是在
我设置了Drop标志后,仍然会调用多次。而且好像并不是每次都需要将实际数据填
好,由于每次调用时传递的参数都一样,无法判断出哪一次才是真正要数据。在我的
系统上,我只要在第8次调用时将数据填好就行,可是在别的系统上却不对(不同的系
统次数不一样)。由于我的数据量有时会很大,不可能每次调用都提供实际数据。
请教:延迟提供数据的正确方法。谢谢!
解决方案1:
用下面的代码:
void onbegindrag(...)
{
HGLOBAL hGblFiles;
COleDataSource datasource;
hGblFiles=MakeHDragFilesData();
FORMATETC etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
datasource.CacheGlobalData( CF_FAVSOFTDRAGDATA, hGblFiles,&etc );
DROPEFFECT dropEff=datasource.DoDragDrop(DROPEFFECT_COPY ,NULL,NULL);
GlobalFree(hGblFiles);
}
HGLOBAL CSciView::MakeHDragFilesData()
{
HGLOBAL hGblFiles=NULL;
POSITION pos = m_filelstCtrl.GetFirstSelectedItemPosition();
CStringArray files;
int nFileListBufLen=0;
CString cdrompath=GetDocument()->m_CDROMPath;
while (pos)
{
int nItem = m_filelstCtrl.GetNextSelectedItem(pos);
CString filename=cdrompath+m_strPath+m_filelstCtrl.GetItemText(nItem,0);
files.Add(filename);
nFileListBufLen+=filename.GetLength()+1;
}
nFileListBufLen++;
hGblFiles= GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE, sizeof(DROPFILES)+nFileListBufLen);
BYTE *szData=(BYTE*)GlobalLock(hGblFiles);
DROPFILES *pDropFiles=(DROPFILES*)szData;
pDropFiles->pFiles =sizeof(DROPFILES);
pDropFiles->pt.x=0;
pDropFiles->pt.y=0;
pDropFiles->fNC =FALSE;
pDropFiles->fWide =FALSE;
int offset=sizeof(DROPFILES);
for(int i=0;i<files.GetSize();i++)
{
CString filename=files.GetAt(i);
memcpy(szData+offset,(LPCTSTR)filename,filename.GetLength());
offset+=filename.GetLength()+1;
}
GlobalUnlock(hGblFiles);
return hGblFiles;
}
把你的OnRenderGlobalData paste出来,
我瞧瞧