Доброго времени суток.
Столкнулся с проблемой. Плагин для 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);
}
.....
}
}
Что не так делаю?
Здравствуйте, 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 сразу же после вызова освобождается.
Поэтому, видимо, никакого перехода и не происходит.
Гугл показал мне вот
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'а ?
Решил эту проблему. Кому может понадобиться. Идея — создаю тред, внутри которого создается окно
#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);
}