Вы можете привязать событие 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
Вызов в ClickEvents (IDispatch):
http://code.google.com/p/phpdesktop/source/browse/phpdesktop-msie/msie/click_events.h?r=a5b0b350c933#132