【问题标题】:How to modify context menu of internet explorer using IDocHostUIHandler::ShowContextMenu?如何使用 IDocHostUIHandler::ShowContextMenu 修改 Internet Explorer 的上下文菜单?
【发布时间】:2011-05-10 16:00:00
【问题描述】:

我正在尝试为 Internet Explorer 7.0 实现自定义菜单。为此,我只能使用IDocHostUIHandler::ShowContextMenu。到目前为止,我能够实现一个带有两个选项的基本上下文菜单。问题是默认情况下它们被禁用。相同的示例代码是:

HRESULT CWebEventHandler::ShowContextMenu(DWORD dwID,POINT *ppt, IUnknown *pcmdTarget, IDispatch *pdispObject) 
{
    if (false) // I will put some guard code here. as of now do not consider it
        return S_FALSE;      // Show standard context menus.
    else
    {
        IOleWindow* pWnd = NULL;
        HRESULT hr = pcmdTarget->QueryInterface(IID_IOleWindow,
            (void**) &pWnd);

        if (SUCCEEDED(hr))
        {
            HWND hwnd;

            if (SUCCEEDED(pWnd->GetWindow(&hwnd)))
            {
                HMENU menu = ::CreatePopupMenu();
                ::AppendMenu(menu, MF_STRING, ID_HELLO, L"&Hello" ); // ID_HELLO & ID_WORLD are two menu resource items
                ::AppendMenu(menu, MF_STRING, ID_WORLD, L"&World" );

                long myRetVal = ::TrackPopupMenu(menu, 
                    TPM_RIGHTBUTTON | TPM_LEFTALIGN | TPM_RETURNCMD, 
                    ppt->x, ppt->y, NULL, hwnd, NULL);

                // Send the command to the browser.
                //
                LRESULT myResult = ::SendMessage(hwnd, WM_COMMAND,
                    myRetVal, NULL);
            }

            pWnd->Release();
        }
    }
    return S_OK; 
}

请建议此代码有什么问题以及为什么我的菜单项被禁用??

谢谢

编辑

同样的帖子也可以在这个链接上找到(http://social.msdn.microsoft.com/Forums/en/ieextensiondevelopment/thread/13584f76-21bd-4764-b5b7-e81932561574

【问题讨论】:

    标签: c++ internet-explorer com contextmenu atl


    【解决方案1】:

    我想我已经解决了这个问题。在if (SUCCEEDED(pWnd->GetWindow(&hwnd))) 中获取 hwnd 对象后,为上下文菜单安装您自己的 CALLBACK。在回调中

    if ((uMsg == WM_INITMENUPOPUP) && (wParam == (WPARAM) menu)) {
            return 0;       
        }
    

    否则让原始处理程序处理它。

    一旦完成

    long myRetVal = ::TrackPopupMenu(g_hPubMenu,TPM_RIGHTBUTTON | TPM_LEFTALIGN | TPM_RETURNCMD, 
                        ppt->x, ppt->y, NULL, hwnd, NULL);
    

    恢复到原来的 proc 处理程序....

    示例

    WNDPROC g_lpPrevWndProc = NULL;
    
    HRESULT CWebEventHandler::ShowContextMenu(DWORD dwID, POINT *ppt, IUnknown *pcmdTarget, IDispatch *pdispObject) 
        {
    
    
    if (false)
            return S_FALSE;      // Show standard context menus.
        else
        {
            IOleWindow* pWnd = NULL;
            HRESULT hr = pcmdTarget->QueryInterface(IID_IOleWindow,
                (void**) &pWnd);
    
            if (SUCCEEDED(hr))
            {
                HWND hwnd;
    
                if (SUCCEEDED(pWnd->GetWindow(&hwnd)))
                {
                    g_lpPrevWndProc = (WNDPROC)SetWindowLong(hwnd, GWL_WNDPROC, (LONG)CtxMenuWndProc);
    
                    if (g_hPubMenu)
                    {
                        DestroyMenu(g_hPubMenu);
                        g_hPubMenu = NULL;
                    }
                    g_hPubMenu = ::CreatePopupMenu();
    
                    ::AppendMenu(g_hPubMenu, MF_STRING|MF_ENABLED   , ID_HELLO, L"&Hello" );
                    ::AppendMenu(g_hPubMenu, MF_STRING|MF_ENABLED   , ID_WORLD, L"&World" );
    
                    long myRetVal = ::TrackPopupMenu(g_hPubMenu, 
                        TPM_RIGHTBUTTON | TPM_LEFTALIGN | TPM_RETURNCMD, 
                        ppt->x, ppt->y, NULL, hwnd, NULL);
    
                    SetWindowLong(hwnd, GWL_WNDPROC, (LONG)g_lpPrevWndProc);
    
                    // Send the command to the browser.
                    //
    
                    if (myRetVal == ID_HELLO)
                    {
                        box(_T("Hello"));
                    }else if(myRetVal == ID_WORLD)
                    {
                        box(_T("World"));
                    }else{
                            LRESULT myResult = ::SendMessage(hwnd, WM_COMMAND,myRetVal, NULL);
                    }
    
                }
    
                pWnd->Release();
            }
        }
        return S_OK; 
    }
    
    
    LRESULT CALLBACK CtxMenuWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        if ((uMsg == WM_INITMENUPOPUP) && (wParam == (WPARAM) g_hPubMenu)) {
            return 0;       
        }
        return CallWindowProc(g_lpPrevWndProc, hwnd, uMsg, wParam, lParam);
    }
    

    【讨论】:

      【解决方案2】:

      我确定您已经弄清楚了,但在第二个示例中,您正在执行以下操作: ::SendMessage(hwnd, WM_COMMAND,myRetVal, NULL);

      还原后: SetWindowLong(hwnd, GWL_WNDPROC, (LONG)g_lpPrevWndProc);

      你的回调永远不会在返回 0 时被执行;不过,在这个特定的样本中也没有这种情况。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-20
        • 1970-01-01
        • 2011-12-03
        • 1970-01-01
        • 2023-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多