Обработка события DISPID_NAVIGATEERROR
От: REASY  
Дата: 06.05.11 08:32
Оценка:
Доброго времени суток.
Столкнулся с проблемой. Плагин для IE, мониторит url, по которым ходит пользователь. Нужно реализовать следующее: Если переходят на сервер, которого нет(не reslov'иться)(допустим, askdkalsjdlkasdklaklsdklasd.ru), то перехватить это и вместо показа стандартной страницы об ошибке(или переход на autosearch), перенаправить пользователя, допустим, на http://blablabla.ru
Вот такой код пишу:
STDMETHODIMP CPlugin::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, 
                             WORD wFlags,
                             DISPPARAMS* pDispParams, VARIANT* pvarResult,
                             EXCEPINFO*  pExcepInfo,  UINT* puArgErr)
{
.....
switch (dispidMember)
{
   ....
   case DISPID_NAVIGATEERROR:
   {
      IDispatch* pDisp = pDispParams->rgvarg[4].pdispVal;
      url = SafeGetString(pDispParams->rgvarg[3].pvarVal);
      targetFrameName = SafeGetString(pDispParams->rgvarg[2].pvarVal);
      dwStatusCode = SafeGetLongVal(pDispParams->rgvarg[1].pvarVal);
   
      bool isMain = m_spWebBrowser.IsEqualObject(pDisp);
      TR(L"DISPID_NAVIGATEERROR %d, url=%ls, target frame=%ls", dwStatusCode, url.c_str(),     targetFrameName.c_str());
    if (dwStatusCode == INET_E_RESOURCE_NOT_FOUND)
    {
       // не кидать на страницу поиска
       *(((*pDispParams).rgvarg)[0].pboolVal) = VARIANT_TRUE;
       // нужного эффекта ниже написанный код не дает, то есть 
       // на http://blablabla.ru не перекидывает.
       CComPtr<IWebBrowser2> spBrowser;
       pDisp->QueryInterface(IID_IWebBrowser2, (void**)&spBrowser);

       spBrowser->Navigate(L"http://blablabla.ru", NULL, NULL, NULL, NULL);
   }    
.....
}
}

Что не так делаю?
dispid_navigateerror
Re: Обработка события DISPID_NAVIGATEERROR
От: okman Беларусь https://searchinform.ru/
Дата: 06.05.11 10:24
Оценка:
Здравствуйте, REASY.


if (dwStatusCode == INET_E_RESOURCE_NOT_FOUND)
    {
       // не кидать на страницу поиска
       *(((*pDispParams).rgvarg)[0].pboolVal) = VARIANT_TRUE;
       // нужного эффекта ниже написанный код не дает, то есть 
       // на http://blablabla.ru не перекидывает.
       CComPtr<IWebBrowser2> spBrowser;
       pDisp->QueryInterface(IID_IWebBrowser2, (void**)&spBrowser);

       spBrowser->Navigate(L"http://blablabla.ru", NULL, NULL, NULL, NULL);
   }



Navigate, если мне не изменяет память, работает асинхронно — ее окончания нужно подождать.
А в приведенном коде объект spBrowser сразу же после вызова освобождается.
Поэтому, видимо, никакого перехода и не происходит.
Re[2]: Обработка события DISPID_NAVIGATEERROR
От: REASY  
Дата: 06.05.11 12:18
Оценка:
Здравствуйте, okman, Вы писали:
O>Navigate, если мне не изменяет память, работает асинхронно — ее окончания нужно подождать.
O>А в приведенном коде объект spBrowser сразу же после вызова освобождается.
O>Поэтому, видимо, никакого перехода и не происходит.

Так этот же код в событии DISPID_BEFORENAVIGATE2 нормально отрабатывает.
Re[3]: Обработка события DISPID_NAVIGATEERROR
От: REASY  
Дата: 07.05.11 23:19
Оценка:
Гугл показал мне вот http://www.ms-news.net/f1858/navigateerror-action-cancelled-7912678.html.
Человек пишет "Then try the following. From NavigateError handler, post (don't send)
yourself a message. In this message's handler, call Navigate() for your
error page." А как получить доступ к сообщениям, которые приходят обработчику Internet Explorer'а ?
Re[4]: Обработка события DISPID_NAVIGATEERROR
От: REASY  
Дата: 09.05.11 17:15
Оценка:
Решил эту проблему. Кому может понадобиться. Идея — создаю тред, внутри которого создается окно
#define WM_NAVIGATE_ERROR WM_USER + 0x100

DWORD WINAPI Run(LPVOID lpParam) 
{
    CoInitialize(NULL);

    HANDLE hMutex = *((HANDLE *)lpParam);
    DWORD dwRes = WaitForSingleObject(hMutex, INFINITE);
    
    HWND hwnd;
    MSG msg;
    WNDCLASS w;
    memset(&w,0,sizeof(WNDCLASS));
    w.style = CS_HREDRAW | CS_VREDRAW;
    w.cbClsExtra = w.cbWndExtra = 0;    
    w.lpfnWndProc = WndProc;
    w.hInstance = NULL;
    w.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    w.lpszClassName = L"Invisible Class for IE";
    w.lpszMenuName = NULL;
    w.hCursor = NULL;
    RegisterClass(&w);
    hwnd = CreateWindow(w.lpszClassName,L"BLABLABLA",WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,0,0,NULL,NULL);
    if (hwnd == NULL){      
        ReleaseMutex(hMutex);
        return 1;
    }
    m_InvisibleHWND = hwnd;

    UpdateWindow(hwnd);

    ReleaseMutex(hMutex);

    while (GetMessage(&msg, NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    
    CoUninitialize();
    return msg.wParam;

}

Функция обработки сообщений окна. Т.к. разные треды, то нужен маршалинг указателя. Для этого воспользуемся CComGITPtr:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_NAVIGATE_ERROR:
        {
            CComVariant varURL = CComBSTR(TEXT("http://ya.ru/"));
            CComVariant vEmpty;
            HRESULT hr;

            IWebBrowser2* pWebBrowser;
            DWORD dwCookie = (DWORD)wParam;

            ATLASSERT(dwCookie != 0);
            
            CComGITPtr<IWebBrowser2> pFromGIT(dwCookie);            
            hr = pFromGIT.CopyTo(&pWebBrowser);    
            if (hr == S_OK)
                hr = pWebBrowser->Navigate2(&varURL, &vEmpty, &vEmpty, &vEmpty, &vEmpty);
            break;
    
        }
        
    case WM_DESTROY:
        PostQuitMessage(0);        
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

В Invoke() при обработке DISPID_NAVIGATEERROR отправляю своему созданному окну сообщение, где WPARAM — это cookie CComGITPtr:
if (dwStatusCode == INET_E_RESOURCE_NOT_FOUND)
{
   DWORD m_GITCookie = 0;
   CComGITPtr<IWebBrowser2> pToGIT(m_spWebBrowser);    
   m_GITCookie = pToGIT.Detach();        
   ATLASSERT(m_GITCookie!=0);
   PostMessage(PluginBHO::GetHWND(), WM_NAVIGATE_ERROR, (WPARAM)m_GITCookie, 0);
}
dispid_navigateerror маршалинг
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.