About OLE, Drag and Drop

nicotinism 2004-05-06 12:52:08
我想实现类似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次调用时将数据填好就行,可是在别的系统上却不对(不同的系
统次数不一样)。由于我的数据量有时会很大,不可能每次调用都提供实际数据。

请教:延迟提供数据的正确方法。谢谢!
...全文
75 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
nicotinism 2004-05-11
  • 打赏
  • 举报
回复
此问题已解决,感谢两位热心参与。
nicotinism 2004-05-10
  • 打赏
  • 举报
回复
to flyhigh(一不小心):
你的代码是DragDrop的立即模式,只适合于少量数据的传递。我的数据量会很大,因此需要延迟提供数据。
flyhigh 2004-05-10
  • 打赏
  • 举报
回复
用下面的代码:

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;
}
nicotinism 2004-05-10
  • 打赏
  • 举报
回复
nicotinism 2004-05-06
  • 打赏
  • 举报
回复
大侠,你的这段代码我省略了没贴(限于篇幅),实际上系统的每次调用不仅lpFormatEtc->cfFormat == CF_HDROP,其他的所有参数都相同。
aspnetwuxueyou 2004-05-06
  • 打赏
  • 举报
回复
// 只处理你想要的格式
if (lpFormatEtc->cfFormat == CF_HDROP )
{
// the pointer is null
if (! phGlobal)
GlobalAlloc()
else
{
*phGlobal = DealGetDropData()
return TRUE;
}

return FALSE;
}
nicotinism 2004-05-06
  • 打赏
  • 举报
回复
BOOL CMyOleDataSource::OnRenderGlobalData(LPFORMATETC lpFormatEtc, HGLOBAL* phGlobal)
{

if(!g_bDropGetData) return FALSE; // 左键释放标志


if(++g_nCount != 8) // ???????????????
{
return FALSE;
}

if(!*phGlobal)
{
if(*phGlobal = DealGetDropData())
{
return TRUE;
}
}
else //Never execute:
{
AfxMessageBox("*phGlobal != NULL");
}

return FALSE;
}
aspnetwuxueyou 2004-05-06
  • 打赏
  • 举报
回复
把你的OnRenderGlobalData paste出来,
我瞧瞧

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧