{"id":21483,"date":"2008-07-24T10:00:00","date_gmt":"2008-07-24T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2008\/07\/24\/reading-a-contract-from-the-other-side-simulating-a-drop\/"},"modified":"2008-07-24T10:00:00","modified_gmt":"2008-07-24T10:00:00","slug":"reading-a-contract-from-the-other-side-simulating-a-drop","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20080724-00\/?p=21483","title":{"rendered":"Reading a contract from the other side: Simulating a drop"},"content":{"rendered":"<p><P>\nMost people, when they think of the\n<CODE>IDropTarget<\/CODE> interface,\nthink only of implementing a drop target.\nBut you can read the contract from the other side,\nbecause the description of how a drag source interacts with a drop target\ntells you how to be a drag source.\n<\/P>\n<P>\nTo summarize, the sequence of drop target operations go like this:\n<\/P>\n<UL>\n<LI><CODE>IDropTarget::DragEnter<\/CODE> is called to indicate that\n    an object has been dragged into the drop target.\n    If the drop target returns a failure code, then the drop operation\n    ends immediately.\n<LI>Otherwise, <CODE>IDropTarget::DragOver<\/CODE> calls\n    are made to advise the drop target as to the object&#8217;s location.\n<LI>If the user completes the drop operation, then call\n    <CODE>IDropTarget::Drop<\/CODE>.\n    Otherwise call <CODE>IDropTarget::Leave<\/CODE>.\n    A drop operation can fail to complete because the user hit the\n    Escape key, for example, or dragged the mouse out of the drop target.\n<\/UL>\n<P>\nLet&#8217;s write a simple program that drops one file onto another.\n<\/P>\n<PRE>\n#include &lt;windows.h&gt;\n#include &lt;shlobj.h&gt;\n#include &lt;shellapi.h&gt;\n#include &lt;tchar.h&gt;<\/p>\n<p>&#8230; Insert the function <A HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2004\/09\/20\/231739.aspx\">GetUIObjectOfFile<\/A> here &#8230;<\/p>\n<p>int __cdecl wmain(int argc, WCHAR **argv)\n{\n if (argc == 3 &amp;&amp; SUCCEEDED(CoInitialize(NULL))) {\n  IDataObject *pdto;\n  if (SUCCEEDED(GetUIObjectOfFile(NULL, argv[1],\n                         IID_IDataObject, (void**)&amp;pdto))) {\n   IDropTarget *pdt;\n   if (SUCCEEDED(GetUIObjectOfFile(NULL, argv[2],\n                          IID_IDropTarget, (void**)&amp;pdt))) {\n    POINTL pt = { 0, 0 };\n    DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_LINK;\n    if (SUCCEEDED(pdt-&gt;DragEnter(pdto, MK_LBUTTON,\n                                 pt, &amp;dwEffect))) {\n     dwEffect &amp;= DROPEFFECT_COPY | DROPEFFECT_LINK;\n     if (dwEffect) {\n      pdt-&gt;Drop(pdto, MK_LBUTTON, pt, &amp;dwEffect);\n     } else {\n      pdt-&gt;DragLeave();\n     }\n    }\n    pdt-&gt;Release();\n   }\n   pdto-&gt;Release();\n  }\n  CoUninitialize();\n }\n return 0;\n}\n<\/PRE>\n<P>\nThis is a pretty straightforward implementation of the\nhost side of the drag\/drop protocol.\nRun this program with the <I>full paths<\/I> to two files,\nthe first being the file to drop, and the second being\nthe file you want to drop it onto.\n(Modifying this program to accept relative paths is left\nas an exercise for the reader.)\nFor example, you might try\n<\/P>\n<PRE>\nfakedrop c:\\autoexec.bat c:\\windows\\notepad.exe\n<\/PRE>\n<P>\nNow, sure, dropping a file on a program is nothing exciting.\nYou could&#8217;ve just run the program with the file as the\ncommand line argument, after all.\nBut that&#8217;s looking at it too narrowly;\nyou are simulating a drop operation,\nafter all.\nFor example,\nyou can drop a file onto a shortcut to a printer, and the\nfile will print;\nor you can drop a file onto a folder and it will be copied\nthere (since we specified <CODE>DROPEFFECT_COPY | DROPEFFECT_LINK<\/CODE>,\n<A HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2004\/11\/12\/256472.aspx\">\nbut folders prefer copy to link if the Ctrl+Shift keys are not held down<\/A>);\nor you can drop a file onto the\n<CODE>Mail Recipient.MAPIMail<\/CODE> shortcut in your\n&#8220;Send To&#8221; folder to create a mail message with the file as\nan attachment.\n<\/P>\n<P>\nOh wait, that last example with\n<CODE>Mail Recipient.MAPIMail<\/CODE>\ndoesn&#8217;t work.\nWe&#8217;ll look at why next time,\nalthough I suspect you already know the reason.\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Most people, when they think of the IDropTarget interface, think only of implementing a drop target. But you can read the contract from the other side, because the description of how a drag source interacts with a drop target tells you how to be a drag source. To summarize, the sequence of drop target operations [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-21483","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Most people, when they think of the IDropTarget interface, think only of implementing a drop target. But you can read the contract from the other side, because the description of how a drag source interacts with a drop target tells you how to be a drag source. To summarize, the sequence of drop target operations [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/21483","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=21483"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/21483\/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=21483"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=21483"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=21483"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}