Last time,
we looked at using the MNS_DRAGDROP
style
for dragging items out of a menu.
Today, we’ll look at dropping them in.
Take the program from last time and make the following additions. First, let’s add a second item to the menu.
// resource header file #define IDM_MAIN 1 #define IDC_CLOCK 100 #define IDC_WMP 101 // resource file IDM_MAIN MENU PRELOAD BEGIN POPUP "&Test" BEGIN MENUITEM "&Clock", IDC_CLOCK MENUITEM "&WMP", IDC_WMP END END // scratch.cpp HRESULT GetMenuObject(HWND hwnd, HMENU hmenu, UINT uPos, REFIID riid, void **ppvOut) { HRESULT hr = E_NOTIMPL; *ppvOut = NULL; if (hmenu == GetSubMenu(GetMenu(hwnd), 0)) { switch (GetMenuItemID(hmenu, uPos)) { case IDC_CLOCK: hr = GetUIObjectOfFile(hwnd, L"C:\\Windows\\clock.avi", riid, ppvOut); break; case IDC_WMP: hr = GetUIObjectOfFile(hwnd, L"C:\\Program Files" L"\\Windows Media Player\\wmplayer.exe", riid, ppvOut); break; } } return hr; }
Yes, I hard-coded another path. This is a demo, not production code.
Anyway, it’s time to hook up the
WM_MENUGETOBJECT
message:
#define HANDLE_WM_MENUGETOBJECT(hwnd, wParam, lParam, fn) \ (fn)((hwnd), (MENUGETOBJECTINFO*)(lParam)) LRESULT OnMenuGetObject(HWND hwnd, MENUGETOBJECTINFO *pmgoi) { LRESULT lres = MNGO_NOINTERFACE; if (!(pmgoi->dwFlags & (MNGOF_BOTTOMGAP | MNGOF_TOPGAP)) && SUCCEEDED(GetMenuObject(hwnd, pmgoi->hmenu, pmgoi->uPos, *(IID*)pmgoi->riid, &pmgoi->pvObj))) { lres = MNGO_NOERROR; } return lres; } HANDLE_MSG(hwnd, WM_MENUGETOBJECT, OnMenuGetObject);
To handle the
WM_MENUGETOBJECT
message,
you convert the hmenu
, uPos
pair
into a COM object, requesting the interface provided by the
riid
member,
and putting the result into the pvObj
member.
(Exercise: Why is the riid
member
typed as void *
rather than REFIID
?)
When the user tries to drop on a menu item, we just give them
the corresponding object in the shell namespace.
Notice that I filter out the GAP
messages,
since they indicate that the user is trying to drop between
items rather than on them.
Run this program, open the Test menu, and drag the Clock
menu item onto the WMP menu item.
If all goes well
(assuming you changed the path for clock.avi
to some other AVI file),
the AVI file will be opened by Windows Media Player,
since that’s the behavior of Windows Media Player when you
drop an AVI file on it.
So that’s menu drag/drop. It’s really not all that exciting.
Of course, what people tend to be most interested in is not
generic drag/drop for menus but menu customization via drag/drop.
That’s not something that
MNS_DRAGDROP
gives you directly;
that’s something you need to build yourself out of the
building blocks provided.
We’ll snap some blocks together next time.
0 comments