{"id":8783,"date":"2011-12-28T07:00:00","date_gmt":"2011-12-28T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2011\/12\/28\/using-the-mns_dragdrop-style-dragging-out\/"},"modified":"2011-12-28T07:00:00","modified_gmt":"2011-12-28T07:00:00","slug":"using-the-mns_dragdrop-style-dragging-out","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20111228-00\/?p=8783","title":{"rendered":"Using the MNS_DRAGDROP style: Dragging out"},"content":{"rendered":"<p>\nWindows&nbsp;2000 introduced the <code>MNS_DRAG&shy;DROP<\/code> menu\nstyle, which permits drag\/drop operations in a menu.\nNobody uses this style, probably because it&#8217;s totally undiscoverable\nby the end-user.\nBut I&#8217;ll write a sample program anyway.\n<\/p>\n<p>\nMind you, I knew nothing about the <code>MNS_DRAG&shy;DROP<\/code>\nmenu style until I started writing this entry.\nBut I simply read the documentation, which says that if you set this\nstyle, you will receive <code>WM_MENU&shy;DRAG<\/code>\nand\n<code>WM_MENU&shy;GET&shy;OBJECT<\/code>\nmessages.\nThe\n<code>WM_MENU&shy;DRAG<\/code> message is sent when the user\ndrags a menu item, so let&#8217;s go with that first.\nThe documentation says that you get information about the item\nthat was dragged, and then you return a code that specifies\nwhether you want the menu to remain up or whether you want it torn down.\n<\/p>\n<p>\nSimple enough. Let&#8217;s do it.\n<\/p>\n<p>\nStart with\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2003\/07\/23\/54576.aspx\">\nthe scratch program<\/a>,\nadd\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2004\/09\/20\/231739.aspx\">\nthe function <code>Get&shy;UI&shy;Object&shy;Of&shy;File<\/code><\/a>\nand\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2004\/12\/06\/275659.aspx\">\nthe class <code>CDrop&shy;Source<\/code><\/a>,\nand change the calls to\n<code>Co&shy;Initialize<\/code> and <code>Co&shy;Uninitialize<\/code>\ninto\n<code>Ole&shy;Initialize<\/code> and <code>Ole&shy;Uninitialize<\/code>,\nrespectively.\nNext, define the menu we&#8217;re going to play with:\n<\/p>\n<pre>\n\/\/ resource header file\n#define IDM_MAIN 1\n#define IDC_CLOCK 100\n\/\/ resource file\nIDM_MAIN MENU PRELOAD\nBEGIN\n    POPUP \"&amp;Test\"\n    BEGIN\n        MENUITEM \"&amp;Clock\", IDC_CLOCK\n    END\nEND\n<\/pre>\n<p>\nNow we can add some new code to our scratch program.\nFirst, we add a menu to our window and\nenable drag\/drop on it:\n<\/p>\n<pre>\nBOOL\nOnCreate(HWND hwnd, LPCREATESTRUCT lpcs)\n{\n <font COLOR=\"blue\">MENUINFO mi = { sizeof(mi), MIM_STYLE, MNS_DRAGDROP };\n return SetMenuInfo(GetMenu(hwnd), &amp;mi);<\/font>\n}\n\/\/ InitApp\n <font COLOR=\"red\">\/\/ <strike>wc.lpszMenuName = NULL;<\/strike><\/font>\n <font COLOR=\"blue\">wc.lpszMenuName = MAKEINTRESOURCE(IDM_MAIN);<\/font>\n<\/pre>\n<p>\nFor both dragging and dropping, we need a way to obtain the\nCOM object associated with a menu item,\nso I&#8217;ll put them in this common helper function:\n<\/p>\n<pre>\nHRESULT GetMenuObject(HWND hwnd, HMENU hmenu, UINT uPos,\n                      REFIID riid, void **ppvOut)\n{\n HRESULT hr = E_NOTIMPL;\n *ppvOut = NULL;\n if (hmenu == GetSubMenu(GetMenu(hwnd), 0)) {\n  switch (GetMenuItemID(hmenu, uPos)) {\n  case IDC_CLOCK:\n   hr = GetUIObjectOfFile(hwnd, L\"C:\\\\Windows\\\\clock.avi\",\n                                             riid, ppvOut);\n   break;\n  }\n }\n return hr;\n}\n<\/pre>\n<p>\nIf the menu is our &#8220;Test&#8221; popup menu, then\nwe know how to map the menu items to COM objects.\nFor now, we have only one item,\nnamely <i>Clock<\/i>,\nwhich corresponds to\nthe <code>C:\\Windows\\clock.avi<\/code>&sup1; file.\n<\/p>\n<p>\nNow we can hook up a handler to the\n<code>WM_MENU&shy;DRAG<\/code> message:\n<\/p>\n<pre>\n#define HANDLE_WM_MENUDRAG(hwnd, wParam, lParam, fn) \\\n (fn)((hwnd), (UINT)(wParam), (HMENU)(lParam))\nLRESULT OnMenuDrag(HWND hwnd, UINT uPos, HMENU hmenu)\n{\n LRESULT lres = MND_CONTINUE;\n IDataObject *pdto;\n if (SUCCEEDED(GetMenuObject(hwnd, hmenu, uPos,\n                                 IID_PPV_ARGS(&amp;pdto)))) {\n  IDropSource *pds = new(std::nothrow) CDropSource();\n  if (pds) {\n   DWORD dwEffect;\n   if (DoDragDrop(pdto, pds, DROPEFFECT_COPY | DROPEFFECT_LINK,\n                  &amp;dwEffect) == DRAGDROP_S_DROP) {\n    lres = MND_ENDMENU;\n   }\n   pds-&gt;Release();\n  }\n  pdto-&gt;Release();\n }\n return lres;\n}\n<\/pre>\n<p>\nThis function is where the magic happens,\nbut it&#8217;s really not all that magical.\nWe get the data object for the menu item being dragged\nand tell OLE to do a drag\/drop operation with it.\nJust to make things interesting, I&#8217;ll say that the\nmenu should be dismissed if the user dropped the object somewhere;\notherwise, the menu remains on the screen.\n<\/p>\n<p>\nFinally, we hook up the message handler to our window procedure:\n<\/p>\n<pre>\nHANDLE_MSG(hwnd, WM_MENUDRAG, OnMenuDrag);\n<\/pre>\n<p>\nAnd there you have it.\nA program that calls up a menu with drag enabled.\nIf you drag the item labeled <i>Clock<\/i>, then the drag\/drop\noperation proceeds as if you were dragging the\n<code>clock.avi<\/code> file.\n<\/p>\n<p>\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/12\/29\/10251523.aspx\">\nNext time<\/a>,\nwe&#8217;ll look at the drop half of drag and drop.\n<\/p>\n<p>\n<b>Footnote<\/b>\n<\/p>\n<p>\n&sup1; I hard-coded the <code>clock.avi<\/code> file\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2004\/12\/06\/275659.aspx\">\nfor old time&#8217;s sake<\/a>.\nYes, I know the file is no longer included with Windows.\nThat&#8217;ll teach people to use hard-coded paths!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Windows&nbsp;2000 introduced the MNS_DRAG&shy;DROP menu style, which permits drag\/drop operations in a menu. Nobody uses this style, probably because it&#8217;s totally undiscoverable by the end-user. But I&#8217;ll write a sample program anyway. Mind you, I knew nothing about the MNS_DRAG&shy;DROP menu style until I started writing this entry. But I simply read the documentation, which [&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-8783","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Windows&nbsp;2000 introduced the MNS_DRAG&shy;DROP menu style, which permits drag\/drop operations in a menu. Nobody uses this style, probably because it&#8217;s totally undiscoverable by the end-user. But I&#8217;ll write a sample program anyway. Mind you, I knew nothing about the MNS_DRAG&shy;DROP menu style until I started writing this entry. But I simply read the documentation, which [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/8783","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=8783"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/8783\/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=8783"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=8783"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=8783"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}