locked
How to get Explorer-like drag images? RRS feed

  • Question

  • Hi,

    On Vista, Windows Explorer uses some new kind of drag images. It consists of a quadratic (with rounded corners) bluish background with a large (48x48 I guess) icon on it. At the bottom of the drag image there's some blue text explaining what will happen if you drop the item.
    What do I have to do if I want such drag-images in my app?
    I've a listview window which is the source of the drag operation. I call SHDoDragDrop() instead of DoDragDrop(), so that I don't have to fiddle around with IDragSourceHelper to get any drag images. However, I only get old-style drag images.
    I noticed that I get an empty quadratic (with rounded corners) bluish drag image WITHOUT icon if I intercept the DI_GETDRAGIMAGE message and simply return FALSE. So how do I get the listview item's icon onto this rounded square? And how do I make the blue text display?

    Thanks in advance
    TiKu
    Saturday, September 23, 2006 11:56 PM

All replies

  • push :]
    Friday, November 10, 2006 10:13 AM
  • Thanks Microsoft for such incredible good documentation. :] I finally found it out myself.


    As I wrote, you'll get the bluish drag-image without any content if you intercept DI_GETDRAGIMAGE and return FALSE. To get some content, simply draw the image like you would do if you'd return TRUE instead of FALSE.

    To get the textual drop-effect description at the bottom-right corner of the drag-image, all you have to do is call SHDoDragDrop() passing NULL as drag source object. Don't ask me how I found this one out. :)

    There're still two things I'd like to know:
    1. How do I customize the textual drop-effect description? I know it has to do with the DROPDESCRIPTION struct, but as usual there's not much documentation...
    2. Is drawing a drag-image in DI_GETDRAGIMAGE and returning FALSE really the right way to fill this bluish thing?

    TiKu
    Saturday, January 6, 2007 4:09 AM
  • Push :]
    Sunday, January 14, 2007 11:39 PM
  • *push*

    As using the shell's default IDropSource implementation sometimes isn't what I want, I'd like to know how to get Vista-style drag images with my own IDropSource implementation.
    So far, I've this:

    // DI_GETDRAGIMAGE message handler
    LPSHDRAGIMAGE pDragImage = (LPSHDRAGIMAGE) lParam;
    pDragImage->sizeDragImage.cx = 100;
    pDragImage->sizeDragImage.cy = 100;
    // create a 100x100 bitmap compatible to the screen and draw into this bitmap
    // then set pDragImage->hbmpDragImage to this bitmap's handle
    return FALSE;

    My implementation of IDropSource::GiveFeedback(DWORD dwEffect) includes this code:

    FORMATETC format = {(CLIPFORMAT) ::RegisterClipboardFormat(CFSTR_DROPDESCRIPTION), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
    STGMEDIUM storageMedium = {0};
    storageMedium.tymed = TYMED_HGLOBAL;
    storageMedium.hGlobal = ::GlobalAlloc(GHND, sizeof(DROPDESCRIPTION));
    if(storageMedium.hGlobal) {
       DROPDESCRIPTION* pDD = (DROPDESCRIPTION*) ::GlobalLock(storageMedium.hGlobal);

       pDD->type = (DROPIMAGETYPE) dwEffect;
       lstrcpyn(pDD->szMessage, L"Move to %1", MAX_PATH);
       lstrcpyn(pDD->szInsert, L"Test", MAX_PATH);

       ::GlobalUnlock(storageMedium.hGlobal);
       pDataObject->SetData(&format, &storageMedium, TRUE);
    }
    return S_OK;

    And this is how I'm starting the drag operation:
    IDragSourceHelper* pDragSourceHelper = NULL;
    IDragSourceHelper2* pDragSourceHelper2 = NULL;
    ::CoCreateInstance(CLSID_DragDropHelper, NULL, CLSCTX_ALL, IID_IDragSourceHelper, reinterpret_cast<void**>(&pDragSourceHelper));
    if(pDragSourceHelper) {
       pDragSourceHelper->QueryInterface(IID_IDragSourceHelper2, reinterpret_cast<void**>(&pDragSourceHelper2));
       if(pDragSourceHelper2) {
          pDragSourceHelper2->SetFlags(DSH_ALLOWDROPDESCRIPTIONTEXT);
          pDragSourceHelper2->InitializeFromWindow(hWnd, &mousePosition, pDataObject);
          DoDragDrop(pDataObject, pDragSource/*this*/, supportedEffects, &performedEffects);
       }
    }

    But this doesn't really work. The description text is missing and the effect doesn't seem to be updated if I press the modifier keys.

    How do I make the description text being displayed?

    TiKu
    Sunday, March 18, 2007 1:13 AM
  • I'll file a bug to get the MSDN docs updated to include CFSTR_DROPDESCRIPTION

     

    but there is a Windows SDK sample that demonstrates how to do this. if you install the latest SDK you will find it here.

     

    c:\Program Files\Microsoft SDKs\Windows\v6.1\Samples\winui\Shell\AppPlatform\DragAndDrop\DragDropExample.cpp

     

    Chris

     

    Monday, April 14, 2008 3:55 AM
  • This sample works well. But it begins dragging from WM_COMMAND|STN_CLICKED message.

    My application need to begins dragging from WM_POINTERDOWN message (to support multi-touch monitor). But the dragging operation will be interrupted just begin dragging.

    I have implemented an IDropSource interface and it works well with WM_POINTER* message, but it has no shell-style drop description text (DROPDESCRIPTION) even I set the DROPDESCRIPTION to IDataObject.

    I have tried to modify that example to begin dragging from WM_POINTERDOWN message, it doesn't work, and causes memory leak (The implemented IDataObject didn't free).

    Does anyone know how to begin dragging from WM_POINTERDOWN message and display the DROPDESCRIPTION like the shell?

    Friday, May 1, 2015 9:10 AM