Search code examples
c++winapiinternet-explorercontextmenubho

How to show my own context menu in Internet Explorer


I'm writing add-on for Internet Explorer 9 and I have to change default context menu to my own. I'm writing a BHO in C++ and I'm using ATL. I managed to handle event of showing context menu (HTMLDocumentEvents2::oncontextmenu), but I can't display my own one. Here is the code fired when you click right mouse button:

VARIANT_BOOL STDMETHODCALLTYPE CSpellCheckerBHO::OnContextMenu( IHTMLEventObj *pEvtObj)
{
    HMENU contextMenu = CreatePopupMenu();

    MENUITEMINFO item_info = { 0 };
    item_info.cbSize = sizeof(MENUITEMINFO);
    item_info.fMask = MIIM_TYPE | MIIM_ID;
    item_info.fType = MFT_STRING;
    item_info.wID = 0;
    item_info.dwTypeData = L"TEST";
    item_info.cch = 4;

    BOOL result = InsertMenuItem(contextMenu, 0, FALSE, &item_info);
    HWND browserHandle = 0;
    HRESULT hr = _webBrowser->get_HWND((LONG_PTR*)&browserHandle);

    result = TrackPopupMenuEx(contextMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, 0,0, browserHandle , NULL);

    return VARIANT_FALSE;
}

_webBrowser is a pointer to IWebBrowser2 object, I got it from SetSite function.

The standard context menu is not displayed (due to returning VARIANT_FALSE), but TrackPopupMenuEx does nothing and returns 0.

Do you know what I am doing wrong? I need simple menu with some text items.


Solution

  • I fgured it out. Igor Tandetnik helped me on IE addon forum. HWND was from different proccess and TrackPopupMenuEx expects HWND belonging to the calling thread. Here's the code that works:

    VARIANT_BOOL STDMETHODCALLTYPE CSpellCheckerBHO::OnContextMenu( IHTMLEventObj *pEvtObj)
    {
        HMENU contextMenu = CreatePopupMenu();
    
        MENUITEMINFO item_info = { 0 };
        item_info.cbSize = sizeof(MENUITEMINFO);
        item_info.fMask = MIIM_ID | MIIM_STRING;
        item_info.wID = 0;
        item_info.dwTypeData = L"TEST";
        item_info.cch = 4;
    
        BOOL result = InsertMenuItem(contextMenu, 0, TRUE, &item_info);
    
        CComPtr<IDispatch> dispDoc;
        _webBrowser->get_Document(&dispDoc);
        CComQIPtr<IOleWindow> oleWindow = dispDoc;
        HWND browserHandle;
        oleWindow->GetWindow(&browserHandle);
    
    
        CComQIPtr<IHTMLEventObj2> htmlEventObj = pEvtObj;
        long x, y;
        htmlEventObj->get_screenX(&x);
        htmlEventObj->get_screenY(&y);  
    
        result = TrackPopupMenuEx(contextMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, browserHandle , NULL);
    
        return VARIANT_FALSE;
    }