0

I wrote a demo containing a TListView (m_ListView). It shows my files on the D:\ drive. If I drag a TListItem in m_ListView and drop it on the E:\ drive, the selected file will be copied to E:\. This works well, but something is wrong with the end of the drag.

When I do the drag&drop and release my left button when the mouse is hovering over E:\, there will be a shade like in this picture (the file has been copied!):

screenshot

To perform another drag&drop action, I have to click on my TListView again.

What should I do to eliminate this?

I tried using ReleaseCapture(), but that didn't work (or I didn't use it correctly).

Main code:

void _fastcall MC_OLEDragHelper::MyListStartDrag(TObject* vSender, TDragObject*& vDragObject)
{

    int tCount = (int)m_ListView->Items->Count;

    MT_FileList tFileList;
    for(int i=0; i<tCount; i++)
        {
        TListItem* tItem = m_ListView->Items->Item[i];
        if(false == tItem->Selected)
            continue;

        KKSTR tFileName = m_ListViewDragKit->OnItemDragOut(tItem);
        if(true == tFileName.empty())
            continue;

        tFileList.push_back(tFileName);
        }

    //Call DoDragDrop
    DropFiles(&tFileList, DROPEFFECT_COPY);

    return;
}

DropFiles() function:

bool MC_OLEDragHelper::DropFiles(MT_FileList* vFileList, DWORD vDesireEffect)
{
    if(false == m_Available)
        return false;

    if(0 == vFileList->size())
        return false;

    void* tDropfiles = (DROPFILES*)CreateFileDespListItem(vFileList);

    FORMATETC tFormatEtc     = {CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
    STGMEDIUM tStorageMedium = {TYMED_HGLOBAL, {(HBITMAP)tDropfiles}, 0};

    m_DragItemList->Add(&tFormatEtc, &tStorageMedium, 1);

    DWORD tDropEffect;
    DWORD tDragResult = DoDragDrop(m_DragItemList, m_DropSource, vDesireEffect, &tDropEffect);

    bool  tRetVal = false;
    if(tDragResult != DRAGDROP_S_DROP)
        goto WORK_END;

    if(tDropEffect == DROPEFFECT_NONE)
        goto WORK_END;

    tRetVal = true;

WORK_END:
    ReleaseStgMedium(&tStorageMedium);
    DestroyFileDespListItem(HGLOBAL(tDropfiles));

    m_ListView->EndDrag(true);
    return tRetVal;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Alfred Chen
  • 179
  • 3
  • 13
  • It is likely a side effect of mixing VCL-style drag&drop with OLE-style drag&drop. You should consider removing the `OnStartDrag` event and set the `DragMode` to `dmManual`, then use the `OnMouseDown/Up` events to keep track of when the mouse button is held down, and use the `OnMouseMove` event to call `DropFiles()` if the mouse is held down. – Remy Lebeau Mar 05 '15 at 19:41
  • @RemyLebeau Thanks.I adopt your advice and it works well again, but now I get stuck again,when I copy a big file,the UI will be locked until the file is copied,should I create a thread to copy that file? – Alfred Chen Mar 06 '15 at 09:58
  • That scenario is covered by the documentation: [Dragging and Dropping Shell Objects Asynchronously](https://msdn.microsoft.com/en-us/library/windows/desktop/bb776904(v=vs.85).aspx#async) – Remy Lebeau Mar 06 '15 at 16:23
  • @RemyLebeau Thanks,I implement IAsyncOperation and do the work said in MSDN,but it doesn`t work,is there any other work I have to do?By the way, I use CF_HROP as the clipboard format and if I call SetAsyncMode(VARIANT_FALSE),it will act as an synchronize copy normally. – Alfred Chen Mar 09 '15 at 06:47
  • @RemyLebeau I found something wierd,I use a desktop software call Q+ Desktop(something like fences) to tidify my desktop and I can drop files on it with asynchronize operation,that indicate I have correctly implement IAsyncOperation,but it doesn`t work when I drop files in Windows Explorer,when I release the left button,DoDragDrop just return with success,but nothing happened:( – Alfred Chen Mar 09 '15 at 07:42
  • @RemyLebeau Code [here](https://github.com/cyfingm/CB_OLEDrag-Drop) – Alfred Chen Mar 09 '15 at 07:59

0 Answers0