实现拖出,现在程序的“拖”数据源是Listview,具体的内容根据Listview选中的文件从ftp下载(这个无所谓,反正从其他地方来的,数据库的stream等等都可以,不同于普通文本拖放),希望拖放完毕,鼠标放开以后开始下载ftp的内容,并保存到本地,(从程序窗口中的listview拖到桌面等地方)

解决方案 »

  1.   

    http://community.csdn.net/Expert/topic/5319/5319586.xml?temp=6.657046E-02
      

  2.   

    DoDragDrop好像是要本地文件夹存在,而且DoDragDrop本身好像是阻塞的方式。
      

  3.   

    如果能在DoDragDrop之后才开始下载数据,或者获得数据就比较好了,取巧的办法是先给个临时文件,然后再填充,但是总感觉应该有比较正统的做法,msdn上的做法是先到临时文件夹的
      

  4.   

    如果能在DoDragDrop之后得到目的文件夹,那就好办了,不知道有头绪么?
      

  5.   

    做法其实有了,但是想讨论更深入点,
    1、拖放前先建立临时文件,这个临时文件可以是很小的,做个样子而已,拖放结束以后开始下载,然后填充这个文件。一个小小的障眼法2、考虑不使用DoDragDrop,其实用DoDragDrop的目的很简单,主要是考虑两个,它能处理鼠标,比如说鼠标移动时候的光标不同,鼠标移过时对窗口的激活,最后就是判断拖放结束后鼠标所在位置是否可接收拖放等,这里可能需要用到不止一个API,而DoDragDrop就一个api搞定了,复杂度不用说,有点感觉本末倒置楼下继续
      

  6.   

    如果能在DoDragDrop之后得到目的文件夹,那就好办了,不知道有头绪么?获得鼠标起点的窗体句柄,可能是shell或者其他
      

  7.   

    仔细看了一下WinRar的拖放过程,应该是先拖放(至少看起来效果是这样的),然后读取数据到临时文件夹,最后真正拷贝到目的地
      

  8.   

    获得鼠标起点的窗体句柄,不太通用。我觉得应该有Shell的COM接口,但是没有找到是哪个……
      

  9.   

    现在想起来,其实和rar一样就可以了,Delphi有套组件TDragDrop,它里面有个虚拟文件的示例,原理还没弄明白,感觉应该用DoDragDrop,其他的方式有点取巧的感觉,不知道是不是这样
      

  10.   

    我用DoDragDrop没有返回的时候(比如,正在下载文件到临时文件夹中等操作),接受拖动的Explorer窗口消息被阻塞。此时如果点击Explorer窗口就会发现提示忙碌。实在是……
    一直没有找出解决的方法(获得鼠标起点的窗体句柄,不太通用,不采用)。
      

  11.   

    如果有什么办法延迟就好了,让DoDragDrop先不要取数据,或者本身提供了这种机制?
      

  12.   

    DoDragDrop先不要取数据?本身好像不提供这个机制吧?这个东东如果是异步就好了……
      

  13.   

    mfc倒是有这样的方法,不过不知道不用mfc怎么实现,纯api呢
      

  14.   

    顶下没错,COLEDataSource有Delay提交的方法,不知道api怎么实现,没看董源码
      

  15.   

    winrar 可能是先建立临时文件夹,
    那么拖放时可以提供一个对应的文件名
      

  16.   

    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    *pResult = 0; if(GetSelectedCount()>0){
    int iSels=GetSelectedCount(),iLen;
    LPTSTR pszFiles=new TCHAR[MAX_PATH*iSels];
    if(pszFiles==NULL)
    return;
    GetSelItemPaths(pszFiles,&iLen);

    DROPFILES df;
    ZeroMemory(&df,sizeof(DROPFILES));
    df.fWide=FALSE;
    df.pFiles=sizeof(DROPFILES); HGLOBAL hGlobal=GlobalAlloc(GMEM_FIXED,iLen+sizeof(DROPFILES));
    memcpy(hGlobal,&df,sizeof(DROPFILES));
    memcpy(((LPBYTE)hGlobal+sizeof(DROPFILES)),pszFiles,iLen);
    delete[] pszFiles; m_DragSource.CacheGlobalData(CF_HDROP,hGlobal);
    SetMiscFlag(MISC_SELFDRAG);
    SetMiscFlag(MISC_DRAGGING);
    DROPEFFECT rdf=m_DragSource.DoDragDrop(DROPEFFECT_COPY|DROPEFFECT_MOVE|DROPEFFECT_LINK|DROPEFFECT_SCROLL);
    CheckSelAvailable();
    m_DragSource.Empty();
    SetMiscFlag(MISC_DRAGGING,FALSE);
    }
    *pResult = 1;
      

  17.   

    void CFileListCtrl::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult)
    {
    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    *pResult = 0; if(GetSelectedCount()>0){
    int iSels=GetSelectedCount(),iLen;
    LPTSTR pszFiles=new TCHAR[MAX_PATH*iSels];
    if(pszFiles==NULL)
    return;
    GetSelItemPaths(pszFiles,&iLen);

    DROPFILES df;
    ZeroMemory(&df,sizeof(DROPFILES));
    df.fWide=FALSE;
    df.pFiles=sizeof(DROPFILES); HGLOBAL hGlobal=GlobalAlloc(GMEM_FIXED,iLen+sizeof(DROPFILES));
    memcpy(hGlobal,&df,sizeof(DROPFILES));
    memcpy(((LPBYTE)hGlobal+sizeof(DROPFILES)),pszFiles,iLen);
    delete[] pszFiles; m_DragSource.CacheGlobalData(CF_HDROP,hGlobal);
    SetMiscFlag(MISC_SELFDRAG);
    SetMiscFlag(MISC_DRAGGING);
    DROPEFFECT rdf=m_DragSource.DoDragDrop(DROPEFFECT_COPY|DROPEFFECT_MOVE|DROPEFFECT_LINK|DROPEFFECT_SCROLL);
    CheckSelAvailable();
    m_DragSource.Empty();
    SetMiscFlag(MISC_DRAGGING,FALSE);
    }
    *pResult = 1;
    }
      

  18.   

    void CFileListCtrl::OnDrop(COleDataObject *pDataObj,BOOL* pbRet)
    {
    CWaitCursor Cursor;
    CWnd* pWnd=GetParent();
    if(pWnd==NULL)
    return;
    pWnd->KillTimer(2);
    *pbRet=FALSE;
    SetMiscFlag(MISC_DRAGGING,FALSE);
    if(ReadMiscFlag(MISC_SELFDRAG)&&GetSelectedCount()==0){
    SetMiscFlag(MISC_SELFDRAG,FALSE);
    return;
    }
    SetMiscFlag(MISC_SELFDRAG,FALSE);

    if(m_pidlfItem==NULL)
    return;

    TCHAR szDst[MAX_PATH],szCurAddr[MAX_PATH];
    SHGetPathFromIDList(m_pidlfItem,szCurAddr);
    if(GetSelectedCount()==1)
    GetSelItemPath(szDst);
    else
    _tcscpy(szDst,szCurAddr);
    CStringArray FileArray;
    FileArray.RemoveAll();
    BOOL bMove=IsStatekeyPressed(VK_SHIFT),bCtrl=IsStatekeyPressed(VK_CONTROL); CMyOleDragDrop::GetFileData(pDataObj,FileArray);
    if(bMove&&bCtrl){
    for(int i=0;i<FileArray.GetSize();i++)
    AddFileLinkItem(FileArray.GetAt(i),szDst,szCurAddr);
    }else{
    if(FileArray.GetSize()>0)
    CopyFileItem(FileArray,szDst,szCurAddr,bMove);
    }
    FileArray.RemoveAll();
    *pbRet=TRUE;
    }
      

  19.   

    谢谢楼上的兄弟
    COleDataSource 有延迟的方法,在codeproject有示例代码,但是现在要在其他语言,比如delphi和vb里面实现,所以最好用api的方式,没看懂mfc的原理,谢谢
      

  20.   

    改成用API应该不难吧,把MFC类的方法改成API调用就行了~
      

  21.   


    谢谢楼上的兄弟
    COleDataSource 有延迟的方法,在codeproject有示例代码,但是现在要在其他语言,比如delphi和vb里面实现,所以最好用api的方式,没看懂mfc的原理,谢谢
    //////////////////////
    用VC做COM dll
    在Delphi或者VB中调用这个dll好了
      

  22.   

    不能用API,那样整个系统都被占用了,其他什么都干不成.
      

  23.   

    TO chenybinCOleDataSource 有延迟的方法,在codeproject有示例代码
    ==================
    指哪个链接?你看的是
    http://www.codeproject.com/shell/dropsourcehelpermfc.asp  ?
      

  24.   

    自已处理吧,用SetCapture,然后用WindowFromPoint判断是桌面还是文件夹,再获取路径
      

  25.   

    看我的blog吧,这个拖放很容易的。
    http://blog.csdn.net/codewarrior/archive/2004/06/15/12039.aspx
    http://blog.csdn.net/codewarrior/archive/2004/06/15/12040.aspx
    http://blog.csdn.net/codewarrior/archive/2004/06/15/12041.aspx
      

  26.   

    to codewarrior :
    非常感谢,这些文章已经看了很多次了,拖出去内容,如果本地不存在,确实有那么点难度,如果能借鉴rar的方式也可以,不过现在没搞定
      

  27.   

    继续迷茫中,主要还是想在Delphi中实现