#pragma once
class CMInvokeCommandInfo : public CMINVOKECOMMANDINFO
{
public:
CMInvokeCommandInfo()
{
memset(this, 0, sizeof(CMINVOKECOMMANDINFO));
this->cbSize = sizeof(CMINVOKECOMMANDINFO);
}
};
/////////////////////////////////////////////////////////////////////////////
// CContextMenuHelper
class CContextMenuHelper
{
public:
CContextMenuHelper(); // 実装しない
virtual ~CContextMenuHelper();
public:
// 選択しているアイテムのコンテキストメニュー
// → 複数のアイテムがありうる
static HRESULT TrackPopupMenu(
HWND hWnd,
IShellFolderPtr spShellFolder,
LPCITEMIDLIST* pidls,
int nCount,
CPoint point,
IContextMenu2** ppContextMenu2 = NULL,
IContextMenu3** ppContextMenu3 = NULL)
{
if (spShellFolder == NULL)
{
return E_FAIL;
}
HRESULT hr = S_OK;
IContextMenuPtr spContextMenu;
hr = spShellFolder->GetUIObjectOf(hWnd, nCount, pidls, IID_IContextMenu, NULL, (void**)&spContextMenu);
if (FAILED(hr))
{
return hr;
}
CMenu menu;
BOOL br = menu.CreatePopupMenu();
if (br == FALSE)
{
return E_FAIL;
}
// CMF_CANRENAMEをつけると、"名前の変更"が表示される
UINT uCMFFlags = CMF_NORMAL | CMF_EXPLORE; // ツリービュー用
// UINT uCMFFlags = CMF_NORMAL; // リストビュー用
hr = spContextMenu->QueryContextMenu((HMENU)menu, 0, 1, 0x7fff, uCMFFlags);
if (FAILED(hr))
{
return hr;
}
// TrackPopupMenu()の前
IContextMenu2Ptr spContextMenu2 = spContextMenu;
IContextMenu3Ptr spContextMenu3 = spContextMenu;
if (ppContextMenu2 != NULL)
{
*ppContextMenu2 = spContextMenu2;
}
if (ppContextMenu3 != NULL)
{
*ppContextMenu3 = spContextMenu3;
}
UINT uFlags = TPM_LEFTALIGN | TPM_RETURNCMD | TPM_RIGHTBUTTON;
int idCmd = menu.TrackPopupMenu(uFlags, point.x, point.y, hWnd);
// TrackPopupMenu()の後
if (ppContextMenu2 != NULL)
{
*ppContextMenu2 = NULL;
}
if (ppContextMenu3 != NULL)
{
*ppContextMenu3 = NULL;
}
spContextMenu2 = NULL;
spContextMenu3 = NULL;
if (idCmd)
{
CMInvokeCommandInfo cmi;
cmi.fMask = 0;
cmi.hwnd = hWnd;
cmi.lpVerb = MAKEINTRESOURCE(idCmd - 1);
cmi.lpParameters = NULL;
cmi.lpDirectory = NULL;
cmi.nShow = SW_SHOWNORMAL;
cmi.dwHotKey = 0;
cmi.hIcon = NULL;
hr = spContextMenu->InvokeCommand(&cmi);
if (FAILED(hr))
{
return hr;
}
}
return hr;
}
// ダブルクリックされたアイテムの実行
static HRESULT ExecDefaultCommand(
HWND hWnd,
IShellFolderPtr spShellFolder,
LPCITEMIDLIST pidl)
{
if (spShellFolder == NULL)
{
return E_FAIL;
}
HRESULT hr = S_OK;;
IContextMenuPtr spContextMenu;
hr = spShellFolder->GetUIObjectOf(hWnd, 1, &pidl, IID_IContextMenu, NULL, (void**)&spContextMenu);
if (FAILED(hr))
{
return hr;
}
CMenu menu;
BOOL br = menu.CreatePopupMenu();
if (br == FALSE)
{
return E_FAIL;
}
UINT uCMFFlags = CMF_DEFAULTONLY | CMF_EXPLORE;
hr = spContextMenu->QueryContextMenu(menu, 0, 1, 0x7fff, uCMFFlags);
if (FAILED(hr))
{
return hr;
}
int idCmd = menu.GetMenuItemID(0);
if (idCmd && (idCmd != -1))
{
CMInvokeCommandInfo cmi;
cmi.fMask = 0;
cmi.hwnd = hWnd;
cmi.lpVerb = MAKEINTRESOURCE(idCmd - 1);
cmi.lpParameters = NULL;
cmi.lpDirectory = NULL;
cmi.nShow = SW_SHOWNORMAL;
cmi.dwHotKey = 0;
cmi.hIcon = NULL;
hr = spContextMenu->InvokeCommand(&cmi);
if (FAILED(hr))
{
return hr;
}
}
return hr;
}
};
/////////////////////////////////////////////////////////////////////////////
// CHandleMenuMessage
template <CLASS T>
class CHandleMenuMessage
{
public:
CHandleMenuMessage()
{
m_lpContextMenu2 = NULL;
m_lpContextMenu3 = NULL;
}
virtual ~CHandleMenuMessage()
{
}
BEGIN_MSG_MAP(CHandleMenuMessage<T>)
MESSAGE_HANDLER(WM_INITMENUPOPUP, OnMenuMessage)
MESSAGE_HANDLER(WM_DRAWITEM, OnMenuMessage)
MESSAGE_HANDLER(WM_MEASUREITEM, OnMenuMessage)
MESSAGE_HANDLER(WM_MENUCHAR, OnMenuMessage2)
ALT_MSG_MAP(1)
MESSAGE_HANDLER(WM_INITMENUPOPUP, OnMenuMessage)
MESSAGE_HANDLER(WM_DRAWITEM, OnMenuMessage)
MESSAGE_HANDLER(WM_MEASUREITEM, OnMenuMessage)
MESSAGE_HANDLER(WM_MENUCHAR, OnMenuMessage2)
END_MSG_MAP()
// Windows Message Handlers
public:
// 完成
LRESULT OnMenuMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
HRESULT hr = S_OK;
if (m_lpContextMenu2 != NULL)
{
hr = m_lpContextMenu2->HandleMenuMsg(uMsg, wParam, lParam);
if (FAILED(hr))
{
// 無視する。。
}
}
return 0;
}
// 完成
LRESULT OnMenuMessage2(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
HRESULT hr = S_OK;
LRESULT lResult = 0;
if (m_lpContextMenu3 != NULL)
{
hr = m_lpContextMenu3->HandleMenuMsg2(uMsg, wParam, lParam, &lResult);
if (FAILED(hr))
{
// 無視する。。
}
}
return lResult;
}
protected:
IContextMenu2* m_lpContextMenu2;
IContextMenu3* m_lpContextMenu3;
};