Figure 1   An SDI/MDI Fix


 BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) 
 {
    if (pMsg->message == WM_KEYDOWN)
    {
       if (!(::IsChild(m_wndToolBar.GetDlgItem(
           ID_URL_NAME)->GetSafeHwnd(), pMsg->hwnd))
          || pMsg->wParam == VK_TAB)
       {
          LPDISPATCH lpDispatch = NULL;
 
          lpDispatch = ((CMyView*)
             GetActiveView())->m_webBrowser.GetDocument();
 
          ASSERT(lpDispatch);
 
          // Get an IDispatch pointer for the 
          // IOleInPlaceActiveObject interface.
          //
          IOleInPlaceActiveObject* pIOIPAO = NULL;
 
          lpDispatch->QueryInterface(IID_IOleInPlaceActiveObject,
                                    (void**)&pIOIPAO);
          lpDispatch->Release();
 
          ASSERT(pIOIPAO);
 
          // Pass the keydown command to 
          // IOleInPlaceActiveObject::TranslateAccelerator
          //
          HRESULT hr = pIOIPAO->TranslateAccelerator(pMsg);
          pIOIPAO->Release();
 
          // TranslateAccelerator will return S_FALSE if it
          // doesn't process the message.
          //
          if (S_OK == hr)
             return TRUE;
        }
     }
 
     return CFrameWnd::PreTranslateMessage(pMsg);
 }


Figure 2   ATL and C++ Fixes

ATL


 LRESULT CMyClass::OnKeydown(UINT uMsg, WPARAM wParam, LPARAM lParam,
                             BOOL& bHandled)
 {
    // m_spWebBrowser is a data member of type IWebBrowser2.
    // Using CComQIPtr in this way queries m_spWebBrowser
    // for the IOleInPlaceActiveObject interface which is
    // then stored in the pIOIPAO variable.
    //
    CComQIPtr<IOleInPlaceActiveObject,
              &IID_IOleInPlaceActiveObject> pIOIPAO(m_spWebBrowser);
 
    HRESULT hr = S_FALSE;
 
    if (pIOIPAO)
    {
       MSG msg;
       msg.message = uMsg;
       msg.wParam = wParam;
       msg.lParam = lParam;
 
       hr = pIOIPAO->TranslateAccelerator(&msg);
    }
 
    return hr;
 }
SDK

 LRESULT CMyClass::OnKeydown(UINT uMsg, WPARAM wParam, LPARAM lParam,
                             BOOL& bHandled)
 {
    IOleInPlaceActiveObject* pIOIPAO;
 
    HRESULT hr = m_pWebBrowser->QueryInterface(IID_IWebBrowser2, (void**)&pIOIPAO);
                                               
    if (SUCCEEDED(hr))
    {
       MSG msg;
       msg.message = uMsg;
       msg.wParam = wParam;
       msg.lParam = lParam;
 
       hr = pIOIPAO->TranslateAccelerator(&msg);
       pIOIPAO->Released);
    }
 
    return hr;
 }


Figure 3   UI Activation


 STDMETHODIMP CWBExplorerBar::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
 {
     _ASSERT(m_pIOleObject);
 
     HRESULT hr = E_FAIL;
 
     if (m_pIOleObject)
     {
        RECT  rc;
        GetClientRect(m_hwndParent, &rc);
 
        // If we are being activated, we must UI Activate the WebBrowser
        // control in order for all accelerators to work.
        if (fActivate)
        {
           hr = m_pIOleObject->DoVerb(OLEIVERB_UIACTIVATE, lpMsg,
                                      this, 0, _hwndParent, &rc);
        }
        else
        {
           hr = m_pIOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, lpMsg,
                                      this, 0, _hwndParent, &rc);
        }
     }
 
     return hr;
 }


Figure 4   Enabling Accelerator Keys


 STDMETHODIMP CWBExplorerBar::TranslateAcceleratorIO(LPMSG pMsg)
 {
     LPDISPATCH pDisp = NULL;
     IOleInPlaceActiveObject* pIOIPAO;
     HRESULT hr = S_FALSE;
 
     // Send accelerator messages to the WebBrowser control
     // so that keys such as Backspace and Delete will work correctly.
     // Note that s_ denotes a static data member.
     hr = s_pWebBrowserOC->get_Application(&pDisp);
 
     if (SUCCEEDED(hr))
     {
        hr = pDisp->QueryInterface(IID_IOleInPlaceActiveObject, 
                                   (LPVOID*)&pIOIPAO);
        pDisp->Release();
 
        if (SUCCEEDED(hr))
        {
           hr = pIOIPAO->TranslateAccelerator(pMsg);
           pIOIPAO->Release();
        }
     }
 
     return hr;
 }