有关文件拖放的延迟方式(DelayRenderData)的问题,哪位兄弟有经验,多多指教!!!!!!!!!! 我要从我的列表控件中把所显示的文件拖放到比如桌面上,但当我的拖放函数如begindrag()中操作时间较长时就无法完成拖动,我用的是即使方式,函数是CacheGlobalData(),查了一下资料好象要用延迟方式DelayRenderData(),但具体怎么做小弟还是无从下手,哪位兄弟有这方面的经验不吝赐教,小弟万分感激!!!!!!! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 CacheGlobalData不行么?我觉得可以啊。我以前都是这么做的。不过,你要拖放到桌面上,那么是否有一定的剪贴版格式呢? //Sleep(5000); UINT uBuffSize = 0; char sFile[MAX_PATH]; memset(sFile,'\0',MAX_PATH); m_ctrl.GetItemText(0,0,sFile,MAX_PATH); uBuffSize += lstrlen(sFile) + 1; int n=sizeof(DROPFILES); uBuffSize = sizeof(DROPFILES) + (uBuffSize + 1); HANDLE hData = ::GlobalAlloc(GHND, uBuffSize); LPDROPFILES pDropFiles = (LPDROPFILES)::GlobalLock(hData); pDropFiles->pFiles = sizeof(DROPFILES); pDropFiles->fWide = FALSE; char *pData = (char*)((LPBYTE)pDropFiles + sizeof(DROPFILES)); lstrcpy(pData, sFile); // ppData = 1 + _tcschr(ppData, '\0'); ::GlobalUnlock(hData); COleDataSourceEx src; src.CacheGlobalData(CF_HDROP, hData); DROPEFFECT de = src.DoDragDrop(DROPEFFECT_COPY); //实现拖入回收站 IDataObject *piDataObject = (IDataObject*)src.GetInterface(&IID_IDataObject); IEnumFORMATETC *piefEtc; HRESULT hr = piDataObject->EnumFormatEtc(DATADIR_GET, &piefEtc); if(SUCCEEDED(hr)) { hr = piefEtc->Reset(); if(SUCCEEDED(hr)) { FORMATETC fEtc; ULONG ulFetched = 0L; while(1) { hr = piefEtc->Next(DATADIR_GET, &fEtc, &ulFetched); if(FAILED(hr) || ulFetched <= 0) break; CString sFormat; if(GetClipboardFormatName(fEtc.cfFormat, sFormat.GetBuffer(60), 60) && sFormat == CFSTR_TARGETCLSID) { STGMEDIUM sm; hr = piDataObject->GetData(&fEtc, &sm); if(SUCCEEDED(hr)) { CLSID clsid; BYTE *pData = (BYTE*)::GlobalLock(sm.hGlobal); memcpy(&clsid, pData, 16); ::GlobalUnlock(sm.hGlobal); if(clsid == CLSID_RecycleBin) { UINT uuBuffSize; uuBuffSize = strlen(sFile) + 1; char *ppData = new char[uuBuffSize]; lstrcpy(ppData,sFile); SHFILEOPSTRUCT op; op.wFunc = FO_DELETE; op.hwnd = NULL; op.pFrom = ppData; op.pTo = NULL; op.fFlags = FOF_ALLOWUNDO|FOF_NOCONFIRMATION; int nResult = SHFileOperation(&op); delete ppData; } } } } } piefEtc->Release(); } while(src.m_dwRef > 1) src.InternalRelease();比如上面写的程序可以完成拖放,但当我加上 Sleep(5000);就不能拖动文件,这是为什么呢,望高手指点,谢谢!!!! 我试验了一下,没有问题的,不知道是不是你系统的原因。我的代码如下:void CListCtrlEx::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) { int nItem = 0; int nSize = sizeof(DROPFILES); UINT uBufferSize = 0; char* pszStart = NULL; //存放文件名的起始位置 HGLOBAL hMemData = NULL; POSITION pItemPos = NULL; DROPEFFECT DropResult = DROPEFFECT_NONE; CStringList strSelectedList; LPDROPFILES lpDropFiles = NULL; Sleep(5000); //获取当前选定的项 pItemPos = GetFirstSelectedItemPosition(); if(pItemPos == NULL) { TRACE0("No items were selected!"); return; } else { while(pItemPos) { nItem = GetNextSelectedItem(pItemPos); strSelectedList.AddTail(GetItemText(nItem,0)); uBufferSize += lstrlen(GetItemText(nItem,0))+1; //累加每个Item长度 } } uBufferSize = sizeof(DROPFILES) + uBufferSize + 1; //分配全局内存,准备拖放之用,注意此块内存将由接收拖放的窗口负责销毁 hMemData = GlobalAlloc(GPTR,uBufferSize); ASSERT(hMemData != NULL); //锁定之,并设置相关成员 lpDropFiles = (LPDROPFILES)GlobalLock(hMemData); ASSERT(lpDropFiles != NULL); lpDropFiles->pFiles = sizeof(DROPFILES);#ifdef _UNICODE lpDropFiles->fWide = TRUE;#else lpDropFiles->fWide = FALSE;#endif //把选中的所有文件名依次复制到DROPFILES结构体后面(全局内存中) pItemPos = strSelectedList.GetHeadPosition(); pszStart = (char*)((LPBYTE)lpDropFiles + sizeof(DROPFILES)); while(pItemPos != NULL) { lstrcpy(pszStart, (LPCTSTR)strSelectedList.GetNext(pItemPos)); pszStart = strchr(pszStart,'\0') + 1; //下次的起始位置是上一次结尾+1 } //用COleDataSource缓存数据,启动拖放 m_oleDataSource.Empty(); m_oleDataSource.CacheGlobalData(CF_HDROP, hMemData); DropResult = m_oleDataSource.DoDragDrop(DROPEFFECT_MOVE|DROPEFFECT_COPY); switch(DropResult) { case DROPEFFECT_MOVE: case DROPEFFECT_COPY: break; //注意在NT/2000中,DROPEFFECT_MOVE会返回DROPEFFECT_NONE,参见Q182219 case DROPEFFECT_NONE: //如果是NT,就删除Item,否则表明失败 break; default: break; } GlobalUnlock(hMemData); *pResult = 0;} 上面是一段没有完成的代码,不过拖单个文件是没有问题的。另外,Windows有一个小bug,使用OLE拖放的时候,如果调用 COleDataSource::DelayRenderFileData()而没有制定第二个参数(为NULL),则OleDataSource::OnRenderFileData()将不会被调用来得到实际的数据。详情和解决方案请看MS知识库:Q185675 修改子键键值 在拆分出的窗格中添加工具栏 数据库大数据把处理问题 接口序列化的问题 帮帮菜鸟!! 是不是我的线程处理有问题! 关于菜单处理函数的问题! 对socket传过来的数据解析,请问那位大哥指教一下! ★★★紧急求救!加载LIB和.H文件后,调试出现的错误信息,我该如何解决?★★★ 我做了一个网络编程的小程序(并非木马程序),却被网标认为是非法程序,请问如何才能逃避被类似网标的程序监测应用程序的存在?(在线等待 请问十六进制的数如何转化为字符型数据,如果说0x5A 转为Z 有谁做过wavecom gprs模块的stk(sim toolkit)的开发
不过,你要拖放到桌面上,那么是否有一定的剪贴版格式呢?
UINT uBuffSize = 0; char sFile[MAX_PATH];
memset(sFile,'\0',MAX_PATH); m_ctrl.GetItemText(0,0,sFile,MAX_PATH);
uBuffSize += lstrlen(sFile) + 1; int n=sizeof(DROPFILES);
uBuffSize = sizeof(DROPFILES) + (uBuffSize + 1); HANDLE hData = ::GlobalAlloc(GHND, uBuffSize);
LPDROPFILES pDropFiles = (LPDROPFILES)::GlobalLock(hData);
pDropFiles->pFiles = sizeof(DROPFILES);
pDropFiles->fWide = FALSE;
char *pData = (char*)((LPBYTE)pDropFiles + sizeof(DROPFILES));
lstrcpy(pData, sFile);
// ppData = 1 + _tcschr(ppData, '\0');
::GlobalUnlock(hData); COleDataSourceEx src;
src.CacheGlobalData(CF_HDROP, hData); DROPEFFECT de = src.DoDragDrop(DROPEFFECT_COPY); //实现拖入回收站
IDataObject *piDataObject = (IDataObject*)src.GetInterface(&IID_IDataObject); IEnumFORMATETC *piefEtc;
HRESULT hr = piDataObject->EnumFormatEtc(DATADIR_GET, &piefEtc);
if(SUCCEEDED(hr))
{
hr = piefEtc->Reset();
if(SUCCEEDED(hr))
{
FORMATETC fEtc;
ULONG ulFetched = 0L;
while(1)
{
hr = piefEtc->Next(DATADIR_GET, &fEtc, &ulFetched);
if(FAILED(hr) || ulFetched <= 0)
break;
CString sFormat;
if(GetClipboardFormatName(fEtc.cfFormat, sFormat.GetBuffer(60), 60) && sFormat == CFSTR_TARGETCLSID)
{
STGMEDIUM sm;
hr = piDataObject->GetData(&fEtc, &sm);
if(SUCCEEDED(hr))
{
CLSID clsid;
BYTE *pData = (BYTE*)::GlobalLock(sm.hGlobal);
memcpy(&clsid, pData, 16);
::GlobalUnlock(sm.hGlobal);
if(clsid == CLSID_RecycleBin)
{
UINT uuBuffSize;
uuBuffSize = strlen(sFile) + 1; char *ppData = new char[uuBuffSize];
lstrcpy(ppData,sFile); SHFILEOPSTRUCT op;
op.wFunc = FO_DELETE;
op.hwnd = NULL;
op.pFrom = ppData;
op.pTo = NULL;
op.fFlags = FOF_ALLOWUNDO|FOF_NOCONFIRMATION;
int nResult = SHFileOperation(&op);
delete ppData;
} }
}
}
}
piefEtc->Release();
}
while(src.m_dwRef > 1)
src.InternalRelease();比如上面写的程序可以完成拖放,但当我加上 Sleep(5000);就不能拖动文件,这是为什么呢,望高手指点,谢谢!!!!
void CListCtrlEx::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult)
{
int nItem = 0;
int nSize = sizeof(DROPFILES);
UINT uBufferSize = 0;
char* pszStart = NULL; //存放文件名的起始位置
HGLOBAL hMemData = NULL;
POSITION pItemPos = NULL;
DROPEFFECT DropResult = DROPEFFECT_NONE;
CStringList strSelectedList;
LPDROPFILES lpDropFiles = NULL;
Sleep(5000); //获取当前选定的项
pItemPos = GetFirstSelectedItemPosition();
if(pItemPos == NULL)
{
TRACE0("No items were selected!");
return;
}
else
{
while(pItemPos)
{
nItem = GetNextSelectedItem(pItemPos);
strSelectedList.AddTail(GetItemText(nItem,0));
uBufferSize += lstrlen(GetItemText(nItem,0))+1; //累加每个Item长度
}
}
uBufferSize = sizeof(DROPFILES) + uBufferSize + 1;
//分配全局内存,准备拖放之用,注意此块内存将由接收拖放的窗口负责销毁
hMemData = GlobalAlloc(GPTR,uBufferSize);
ASSERT(hMemData != NULL);
//锁定之,并设置相关成员
lpDropFiles = (LPDROPFILES)GlobalLock(hMemData);
ASSERT(lpDropFiles != NULL);
lpDropFiles->pFiles = sizeof(DROPFILES);
#ifdef _UNICODE
lpDropFiles->fWide = TRUE;
#else
lpDropFiles->fWide = FALSE;
#endif
//把选中的所有文件名依次复制到DROPFILES结构体后面(全局内存中)
pItemPos = strSelectedList.GetHeadPosition();
pszStart = (char*)((LPBYTE)lpDropFiles + sizeof(DROPFILES));
while(pItemPos != NULL)
{
lstrcpy(pszStart, (LPCTSTR)strSelectedList.GetNext(pItemPos));
pszStart = strchr(pszStart,'\0') + 1; //下次的起始位置是上一次结尾+1
}
//用COleDataSource缓存数据,启动拖放
m_oleDataSource.Empty();
m_oleDataSource.CacheGlobalData(CF_HDROP, hMemData);
DropResult = m_oleDataSource.DoDragDrop(DROPEFFECT_MOVE|DROPEFFECT_COPY);
switch(DropResult)
{
case DROPEFFECT_MOVE:
case DROPEFFECT_COPY:
break; //注意在NT/2000中,DROPEFFECT_MOVE会返回DROPEFFECT_NONE,参见Q182219
case DROPEFFECT_NONE:
//如果是NT,就删除Item,否则表明失败
break; default:
break;
}
GlobalUnlock(hMemData);
*pResult = 0;
}
另外,Windows有一个小bug,使用OLE拖放的时候,如果调用 COleDataSource::DelayRenderFileData()而没有制定第二个参数(为NULL),则OleDataSource::OnRenderFileData()将不会被调用来得到实际的数据。
详情和解决方案请看MS知识库:Q185675