我要从我的列表控件中把所显示的文件拖放到比如桌面上,但当我的拖放函数如begindrag()中操作时间较长时就无法完成拖动,我用的是即使方式,函数是CacheGlobalData(),查了一下资料好象要用延迟方式DelayRenderData(),但具体怎么做小弟还是无从下手,哪位兄弟有这方面的经验不吝赐教,小弟万分感激!!!!!!!

解决方案 »

  1.   

    CacheGlobalData不行么?我觉得可以啊。我以前都是这么做的。
    不过,你要拖放到桌面上,那么是否有一定的剪贴版格式呢?
      

  2.   

    //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);就不能拖动文件,这是为什么呢,望高手指点,谢谢!!!!
      

  3.   

    我试验了一下,没有问题的,不知道是不是你系统的原因。我的代码如下:
    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;
    }
      

  4.   

    上面是一段没有完成的代码,不过拖单个文件是没有问题的。
    另外,Windows有一个小bug,使用OLE拖放的时候,如果调用 COleDataSource::DelayRenderFileData()而没有制定第二个参数(为NULL),则OleDataSource::OnRenderFileData()将不会被调用来得到实际的数据。
    详情和解决方案请看MS知识库:Q185675