シェルアイテム(ファイルやフォルダ)のコンテキストメニューの表示

(2003.02.11)
#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;
};
一覧に戻る
© 2003 WAC.com All Right Reserved.