{"id":37063,"date":"2004-12-10T07:00:00","date_gmt":"2004-12-10T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2004\/12\/10\/dragging-a-shell-object-part-5-making-somebody-else-do-the-heavy-lifting\/"},"modified":"2004-12-10T07:00:00","modified_gmt":"2004-12-10T07:00:00","slug":"dragging-a-shell-object-part-5-making-somebody-else-do-the-heavy-lifting","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20041210-00\/?p=37063","title":{"rendered":"Dragging a shell object, part 5: Making somebody else do the heavy lifting"},"content":{"rendered":"<p><P>\nCreating that drag image was a bit of work.\nFortunately, the listview control is willing to do some\nof the work for you.\n<\/P>\n<P>\nThrow away the <CODE>OnLButtonDown<\/CODE> function\n(and the <CODE>HANDLE_MESSAGE<\/CODE> that goes with it).\nInstead, we&#8217;ll make the listview do all our presentation\nfor us.\n<\/P>\n<PRE>\nBOOL\nOnCreate(HWND hwnd, LPCREATESTRUCT lpcs)\n{\n  <FONT COLOR=\"blue\">g_hwndChild = CreateWindow(WC_LISTVIEW, NULL,\n                             WS_CHILD | WS_VISIBLE | LVS_ICON |\n                             LVS_SHAREIMAGELISTS, \/\/ flag added 13 Dec\n                             0, 0, 0, 0,\n                             hwnd, (HMENU)1, g_hinst, 0);\n  if (!g_hwndChild) return FALSE;<\/p>\n<p>  SHFILEINFOW sfi;\n  HIMAGELIST himl = (HIMAGELIST)\n    SHGetFileInfoW(g_pszTarget, 0, &amp;sfi, sizeof(sfi),\n                   SHGFI_SYSICONINDEX |\n                   SHGFI_DISPLAYNAME | SHGFI_LARGEICON);\n  if (!himl) return FALSE;<\/p>\n<p>  ListView_SetImageList(g_hwndChild, himl, LVSIL_NORMAL);<\/p>\n<p>  LVITEM item;\n  item.iSubItem = 0;\n  item.mask = LVIF_TEXT | LVIF_IMAGE;\n  item.pszText = sfi.szDisplayName;\n  item.iImage = sfi.iIcon;\n  if (ListView_InsertItem(g_hwndChild, &amp;item) &lt; 0)\n    return FALSE;<\/FONT><\/p>\n<p>  return TRUE;\n}\n<\/PRE>\n<P>\nWe now let the listview control worry about the icon and its\ntext and all the other UI that goes along with it.\nAnd we can make the listview worry about the drag image, too.\n<\/P>\n<PRE>\n<FONT COLOR=\"blue\">void OnBeginDrag(HWND hwnd, NMLISTVIEW *plv)\n{\n  IDataObject *pdto;\n  if (SUCCEEDED(GetUIObjectOfFile(hwnd, g_pszTarget,\n                   IID_IDataObject, (void**)&amp;pdto))) {\n    IDragSourceHelper *pdsh;\n    if (SUCCEEDED(CoCreateInstance(CLSID_DragDropHelper, NULL,\n                    CLSCTX_ALL, IID_IDragSourceHelper, (void**)&amp;pdsh))) {\n      pdsh-&gt;InitializeFromWindow(g_hwndChild, &amp;plv-&gt;ptAction, pdto);\n      pdsh-&gt;Release();\n    }<\/p>\n<p>    IDropSource *pds = new CDropSource();\n    if (pds) {\n      DWORD dwEffect;\n      if (DoDragDrop(pdto, pds, DROPEFFECT_MOVE |\n                     DROPEFFECT_COPY | DROPEFFECT_LINK,\n                     &amp;dwEffect) == DRAGDROP_S_DROP &amp;&amp;\n          (dwEffect &amp; DROPEFFECT_MOVE)) {\n        DeleteFileW(g_pszTarget);\n      }\n      pds-&gt;Release();\n    }\n    pdto-&gt;Release();\n  }\n}<\/p>\n<p>LRESULT OnNotify(HWND hwnd, int idCtrl, NMHDR *pnm)\n{\n  if (idCtrl == 1) {\n    NMLISTVIEW *plv;\n    switch (pnm-&gt;code) {\n    case LVN_BEGINDRAG:\n      plv = (NMLISTVIEW*)pnm;\n      OnBeginDrag(hwnd, plv);\n      break;\n    }\n  }\n  return 0;\n}<\/p>\n<p>    HANDLE_MSG(hwnd, WM_NOTIFY, OnNotify);<\/FONT>\n<\/PRE>\n<P>\nInstead of detecting the drag operation, we let the listview do it\nand just wait for the <CODE>LVN_BEGINDRAG<\/CODE> notification,\nat which point we get the data object for the file we want to drag\nand ask the listview to create the drag image by passing its window\nhandle to\n<A HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/shellcc\/platform\/shell\/reference\/ifaces\/idragsourcehelper\/InitializeFromWindow.asp\">\nthe <CODE>IDragSourceHelper::InitializeFromWindow<\/CODE> method<\/A>.\n<\/P>\n<P>\nThe listview control does the work of generating the drag image\nand setting it into the data object.  In our specific case, it\nmay have been a toss-up which way is easier, but if you enable\nmultiple-selection capability in the listview, using\nthe <CODE>IDragSourceHelper::InitializeFromWindow<\/CODE> method<\/A>\nis a major savings because the listview will do the work of\ngenerating the radial gradient alpha channel that you see when\ndragging multiple files in Explorer.\n<\/P>\n<P>\nYou may notice some color fringes around the icons generated by\nthe listview.  That&#8217;s because we&#8217;re using version&nbsp;5 of the\ncommon controls, which doesn&#8217;t support alpha channels very well.\nIf you\n<A HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/shellcc\/platform\/commctls\/userex\/cookbook.asp\">\nswitch to version&nbsp;6<\/A>,\nyou&#8217;ll find that the fringes are gone and the icon looks a lot\nprettier.\n<\/P>\n<P>\nThat&#8217;s all for now on the subject of initiating a drag\/drop operation.\nBack to one-day topics for a while.\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Creating that drag image was a bit of work. Fortunately, the listview control is willing to do some of the work for you. Throw away the OnLButtonDown function (and the HANDLE_MESSAGE that goes with it). Instead, we&#8217;ll make the listview do all our presentation for us. BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpcs) { g_hwndChild = CreateWindow(WC_LISTVIEW, [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-37063","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Creating that drag image was a bit of work. Fortunately, the listview control is willing to do some of the work for you. Throw away the OnLButtonDown function (and the HANDLE_MESSAGE that goes with it). Instead, we&#8217;ll make the listview do all our presentation for us. BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpcs) { g_hwndChild = CreateWindow(WC_LISTVIEW, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/37063","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=37063"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/37063\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=37063"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=37063"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=37063"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}