如何使用 IDocHostUIHandler::ShowContextMenu 修改 Internet Explorer 的上下文菜单?

发布于 2024-10-02 15:29:16 字数 1762 浏览 1 评论 0原文

我正在尝试为 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 )

I am trying to implement a custom menu for Internet Explorer 7.0. For this i have to use IDocHostUIHandler::ShowContextMenu only. Till now i am able to implement a basic context menu with two options. The problem is that they are disabled by default. The sample code for the same is:

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; 
}

Kindly suggest what is wrong with this code & why my menu entries are disabled??

Thanks

EDIT

The same post is available on this link also ( http://social.msdn.microsoft.com/Forums/en/ieextensiondevelopment/thread/13584f76-21bd-4764-b5b7-e81932561574 )

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

鹿! 2024-10-09 15:29:16

我想我已经解决了问题。在 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);

恢复到原始过程处理程序......

示例

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);
}

I think i have solved the problem. After getting the hwnd object in if (SUCCEEDED(pWnd->GetWindow(&hwnd))) install your own CALLBACK for context menu. In the callback

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

otherwise let the original handler process it.

once done with

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

revert back to the original proc handler....

Sample

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);
}
一袭白衣梦中忆 2024-10-09 15:29:16

我确信您已经弄清楚了这一点,但在第二个示例中,您正在做:
::SendMessage(hwnd, WM_COMMAND,myRetVal, NULL);

恢复后:
SetWindowLong(hwnd, GWL_WNDPROC, (LONG)g_lpPrevWndProc);

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

I'm sure you already figured this out, but in the second sample, you are doing:
::SendMessage(hwnd, WM_COMMAND,myRetVal, NULL);

after reverting:
SetWindowLong(hwnd, GWL_WNDPROC, (LONG)g_lpPrevWndProc);

Your callback will never get executed on the return 0; path, though, nor was there such a case in this particular sample.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文