{"id":37123,"date":"2004-12-07T07:00:00","date_gmt":"2004-12-07T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2004\/12\/07\/dragging-a-shell-object-part-2-enabling-the-move-operation\/"},"modified":"2004-12-07T07:00:00","modified_gmt":"2004-12-07T07:00:00","slug":"dragging-a-shell-object-part-2-enabling-the-move-operation","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20041207-00\/?p=37123","title":{"rendered":"Dragging a shell object, part 2: Enabling the Move operation"},"content":{"rendered":"<p><P>\nLet&#8217;s say that we did want to support Move in our\ndrag\/drop program, for whatever reason.\nLet&#8217;s do it with some scratch file instead\nof <CODE>clock.avi<\/CODE>, though.  Create a file somewhere\nthat you don&#8217;t mind losing; let&#8217;s say it&#8217;s <CODE>C:\\throwaway.txt<\/CODE>.\nChange the function <CODE>OnLButtonDown<\/CODE> as follows:\n<\/P>\n<PRE>\nvoid OnLButtonDown(HWND hwnd, BOOL fDoubleClick,\n                   int x, int y, UINT keyFlags)\n{\n  IDataObject *pdto;\n  if (SUCCEEDED(GetUIObjectOfFile(hwnd,\n                    <FONT COLOR=\"blue\">L&#8221;C:\\\\throwaway.txt&#8221;<\/FONT>,\n                    IID_IDataObject, (void**)&amp;pdto))) {\n    IDropSource *pds = new CDropSource();\n    if (pds) {\n      DWORD dwEffect;\n      <FONT COLOR=\"blue\">if (DoDragDrop(pdto, pds,\n                 DROPEFFECT_COPY | DROPEFFECT_LINK | DROPEFFECT_MOVE,\n                 &amp;dwEffect) == DRAGDROP_S_DROP) {\n        if (dwEffect &amp; DROPEFFECT_MOVE) {\n          DeleteFile(TEXT(&#8220;C:\\\\throwaway.txt&#8221;));\n        }\n      }<\/FONT>\n      pds-&gt;Release();\n    }\n    pdto-&gt;Release();\n  }\n}\n<\/PRE>\n<P>\nOh wait, there are people out there who think I&#8217;m advocating hard-coded\npaths, so let me change the program to operate on a path passed on the\ncommand line.\nThis is code that is purely a distraction from the point of this\narticle, which is why I avoided it originally.\nPersonally I dislike it when somebody hands me a sample program\nthat is 90% unrelated to the technology the program is trying to demonstrate.\nI have to go\ndigging through the code hunting for the 10% of stuff that matters.\n<\/P>\n<PRE>\n<FONT COLOR=\"blue\">#include &lt;shellapi.h&gt;<\/p>\n<p>LPWSTR *g_argv;\nLPCWSTR g_pszTarget;<\/FONT><\/p>\n<p>void OnLButtonDown(HWND hwnd, BOOL fDoubleClick,\n                   int x, int y, UINT keyFlags)\n{\n  IDataObject *pdto;\n  if (SUCCEEDED(GetUIObjectOfFile(hwnd,\n                    <FONT COLOR=\"blue\">g_pszTarget<\/FONT>,\n                    IID_IDataObject, (void**)&amp;pdto))) {\n  &#8230;\n          DeleteFile<FONT COLOR=\"blue\">W(g_pszTarget<\/FONT>);\n  &#8230;\n}<\/p>\n<p>BOOL\nInitApp(void)\n{\n  <FONT COLOR=\"blue\">int argc;\n  g_argv = CommandLineToArgvW(GetCommandLineW(), &amp;argc);\n  if (!g_argv || argc != 2) return FALSE;\n  g_pszTarget = g_argv[1];\n  if (PathIsRelative(g_pszTarget)) return FALSE;<\/FONT>\n  &#8230;\n}\n<\/PRE>\n<P>\nWoo-hoo, eight distracting lines of code that have nothing to do\nwith the subject of dragging shell objects around.  I hope you&#8217;re\nhappy.\n<\/P>\n<P>\nWhere was I?  Oh right, explaining the first batch of blue code\nthat by now has scrolled off your screen thanks to the intervening\nmeaningless drivel.\n<\/P>\n<P>\nNow that we allow move, we need to check whether the resulting effect\nwas <CODE>DROPEFFECT_MOVE<\/CODE>, which tells us,\n&#8220;The drop target wanted to perform a move operation, but it only\ngot as far as copying the object; please finish the move operation\nby deleting the original.&#8221;\n<\/P>\n<P>\nNotice that <CODE>DROPEFFECT_MOVE<\/CODE> does <STRONG>not<\/STRONG>\nmean, &#8220;The drop target performed a move.&#8221;\nRather, it tells you that the drop target wants you to delete\nthe original.\nIf the drop target was able to delete the original (or move it\ndirectly), then you will not get\n<CODE>DROPEFFECT_MOVE<\/CODE> back.\n<\/P>\n<P>\n(One case where <CODE>DROPEFFECT_MOVE<\/CODE> doesn&#8217;t even mean\nthat a Move operation occurred at all is if the user dragged\nthe object to an &#8220;Incinerator&#8221; icon, the purpose of which is\nto destroy whatever is dropped onto it.  In this case the\nIncinerator would return <CODE>DROPEFFECT_MOVE<\/CODE> without\neven making a copy. Result: The object is deleted.\nA better name for <CODE>DROPEFFECT_MOVE<\/CODE> would have been\n<CODE>DROPEFFECT_DELETEORIGINAL<\/CODE>.)\n<\/P>\n<P>\nIf the data object represents a file, then the shell is pretty\ngood at figuring out how to move the file to the destination\ninstead of copying it and asking you to delete the original.\nYou will typically get <CODE>DROPEFFECT_MOVE<\/CODE> back only\nif the data object represents a non-file, since in that case\nthe shell doesn&#8217;t know how to delete the original.\n<\/P>\n<P>\nBut what if you want to know whether the operation was a move,\nregardless of whether the operation was optimized by the drop\ntarget?\nWe&#8217;ll look at that next time.\n<\/P>\n<P>\n(By the way, if you execute a Move of the throwaway file,\ndon&#8217;t forget to move it back so you can run the scratch\nprogram again!)\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Let&#8217;s say that we did want to support Move in our drag\/drop program, for whatever reason. Let&#8217;s do it with some scratch file instead of clock.avi, though. Create a file somewhere that you don&#8217;t mind losing; let&#8217;s say it&#8217;s C:\\throwaway.txt. Change the function OnLButtonDown as follows: void OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, [&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-37123","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Let&#8217;s say that we did want to support Move in our drag\/drop program, for whatever reason. Let&#8217;s do it with some scratch file instead of clock.avi, though. Create a file somewhere that you don&#8217;t mind losing; let&#8217;s say it&#8217;s C:\\throwaway.txt. Change the function OnLButtonDown as follows: void OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/37123","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=37123"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/37123\/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=37123"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=37123"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=37123"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}