Вы можете привязать к OnClick событие, прежде чем документ является полным при создании браузера в OnCreate() с помощью IHTMLDocument2 :: put_onclick():
#include <comutil.h>
ClickEvents<RootFrame> clickEvents;
_variant_t clickDispatch;
clickDispatch.vt = VT_DISPATCH;
clickDispatch.pdispVal = &clickEvents;
CComQIPtr<IDispatch> dispatch;
hr = webBrowser2->get_Document(&dispatch);
ASSERT_EXIT(SUCCEEDED(hr), "webBrowser->get_Document(&dispatch)");
CComQIPtr<IHTMLDocument2> htmlDocument2;
hr = dispatch->QueryInterface(IID_IHTMLDocument2, (void**) &htmlDocument2);
ASSERT_EXIT(SUCCEEDED(hr), "dispatch->QueryInterface(&htmlDocument2)");
htmlDocument2->put_onclick(clickDispatch);
ClickEvents
класс реализует IDispatch, вам нужно только реализовать Invoke
метод, в остальное возвращение E_NOTIMPL:
HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
HRESULT hr;
CComQIPtr<IWebBrowser2> webBrowser2;
hr = rootFrame->GetDlgControl(rootFrame->rootview.GetDlgCtrlID(), IID_IWebBrowser2, (void**) &webBrowser2);
ASSERT_EXIT(SUCCEEDED(hr), "rootframe->GetDlgControl(IID_IWebBrowser2) failed");
CComQIPtr<IDispatch> dispatch;
hr = webBrowser2->get_Document(&dispatch);
ASSERT_EXIT(SUCCEEDED(hr), "webBrowser2->get_Document(&dispatch)");
CComQIPtr<IHTMLDocument2> htmlDocument2;
hr = dispatch->QueryInterface(IID_IHTMLDocument2, (void**) &htmlDocument2);
ASSERT_EXIT(SUCCEEDED(hr), "dispatch->QueryInterface(&htmlDocument2)");
CComQIPtr<IHTMLWindow2> htmlWindow2;
hr = htmlDocument2->get_parentWindow((IHTMLWindow2**) &htmlWindow2);
ASSERT_EXIT(SUCCEEDED(hr), "htmlDocument2->get_parentWindow(&htmlWindow2)");
CComQIPtr<IHTMLEventObj> htmlEvent;
hr = htmlWindow2->get_event(&htmlEvent);
ASSERT_EXIT(SUCCEEDED(hr), "htmlWindow2->get_event(&htmlEvent)");
CComQIPtr<IHTMLElement> htmlElement;
hr = htmlEvent->get_srcElement(&htmlElement);
ASSERT_EXIT(SUCCEEDED(hr), "htmlEvent->get_srcElement(&htmlElement)");
CComBSTR hrefAttr(L"href");
VARIANT attrValue;
VariantInit(&attrValue);
hr = htmlElement->getAttribute(hrefAttr, 0 | 2, &attrValue); // 0 = case insensitive, 2 = return BSTR
ASSERT_EXIT(SUCCEEDED(hr), "htmlElement->getAttribute()");
wchar_t href[2084]; // maximum url length in IE, http://support.microsoft.com/kb/208427
wcsncpy_s(href, _countof(href), attrValue.bstrVal, _TRUNCATE);
if (!rootFrame->IsURLAllowed(href)) {
VARIANT variant;
variant.vt = VT_BOOL;
variant.boolVal = VARIANT_FALSE;
htmlEvent->put_returnValue(variant);
ShellExecute(0, L"open", href, 0, 0, SW_SHOWNORMAL);
}
return S_OK;
}
Как вы можете видеть, после запроса некоторых интерфейсов, я наконец-то есть элемент, который получил щелкнул, то я называю IsURLAllowed(), определенный в моем корневом фрейме, чтобы проверить, следует ли разрешить открытие url в текущем окне веб-браузера или открыть его, используя браузер по умолчанию на компьютере пользователя.
Это обрабатывает все ссылки, даже если они были добавлены в документ с использованием javascript.
То же самое должно быть сделано с событиями «onsubmit» для форм.
Я также думаю, что у меня есть решение для переадресации «window.location» в javascript, я еще не протестировал его, но я скоро проверю его, и тогда я обновлю этот ответ. Вы можете использовать комбинацию событий «onunload» и «onbeforeunload» вместе с DWebBrowserEvents2 :: BeforeNavigate2(), после вызова onunload/onbeforeunload вы узнаете, что пользователь покидает текущую страницу, поэтому теперь в BeforeNavigate2() вы можете отменить ее. Вы можете присоединить разгрузочные события, используя IHTMLWindow2 :: put_onunload() и IHTMLWindow2 :: put_onbeforeunload().
См. Источники полного решения для «onclick» ниже.
AttachClickEvents в BrowserFrame:
http://code.google.com/p/phpdesktop/source/browse/phpdesktop-msie/msie/browser_frame.h?r=709d00b991b5#125
Invoke в ClickEvents (IDispatch):
http://code.google.com/p/phpdesktop/source/browse/phpdesktop-msie/msie/click_events.h?r=a5b0b350c933#132
Обратите внимание, что я не предлагал сохранить этот вопрос там статична, а спросить вопрос о конкретной проблеме с надежной идентификацией контекста для 'BeforeNavigate2()' и др. –
Георг, я понимаю, но моя цель - просто решить проблему, изложенную выше, и я буду рад любому решению, будь то BeforeNavigate2 или что-то еще. –