Search code examples
cwinapidrag-and-dropiconsimagelist

How to figure out the shell's drag/drop icon size for use with SHDoDragDrop?


How do I figure out the right icon size to use so that the icon matches Explorer's default drag-and-drop icon?

(I'm trying to use it with SHDoDragDrop if that matters.)

enter image description here


Solution

  • The size depends on what's in the data object format. From the Shell, it's 96x96.

    You can check that if you drag & drop a file into any valid drop target, the data object will contain the "DragImageBits" format and its data is a SHDRAGIMAGE structure:

    typedef struct SHDRAGIMAGE {
      SIZE     sizeDragImage; // will contain 96x96 when dragged from the Shell
      POINT    ptOffset;
      HBITMAP  hbmpDragImage;
      COLORREF crColorKey;
    } SHDRAGIMAGE, *LPSHDRAGIMAGE;
    

    If you're looking for a more static way, here is a code that seems to work, using the UxThemes API. Note that although it uses documented APIs and defines, I don't think it's documented as such.

    ...
    #include <uxtheme.h>
    #include <vsstyle.h>
    #include <vssym32.h>
    ...
    
    // note: error checking ommited
    auto theme = OpenThemeData(NULL, VSCLASS_DRAGDROP);
    
    SIZE size = {};
    GetThemePartSize(theme, NULL, DD_IMAGEBG, 0, NULL, THEMESIZE::TS_DRAW, &size);
    
    MARGINS margins = {};
    GetThemeMargins(theme, NULL, DD_IMAGEBG, 0, TMT_CONTENTMARGINS, NULL, &margins);
    
    // final size
    size.cx -= margins.cxLeftWidth + margins.cxRightWidth;
    size.cy -= margins.cyTopHeight + margins.cyBottomHeight;
    
    CloseThemeData(theme);
    

    As for DPI settings, I understand you want to mimic Explorer, in this case you'll have to do some computation by yourself depending on your needs and screen context, as the image size extracted by the Shell is itself fixed.