Как мне прослушать событие Запуск IE с IWebBrowser2 в C++ XE2?
В настоящее время я хочу автоматизировать работающий IE. Я успешно подключил работающий IE, используя приведенный ниже код (я предполагаю, что в одной вкладке есть только один IE)
#include "atl/atlbase.h"
#include <exdisp.h>
#include <mshtml.h>
CComQIPtr<IWebBrowser2> pCurIE;
void __fastcall TForm4::Button3Click(TObject *Sender)
{
bool SuccessToHook = false;
CComPtr<IShellWindows> m_spSHWinds;
if (FAILED(m_spSHWinds.CoCreateInstance( __uuidof( ShellWindows)))){
return ;
}
LONG nCount;
m_spSHWinds->get_Count( &nCount);
ShowMessage(nCount);
for (int i = 0; i < nCount; i++) {
CComPtr<IDispatch> pDisp;
m_spSHWinds->Item( CComVariant(i), &pDisp);
CComQIPtr<IWebBrowser2> pIE(pDisp);
if (pIE == NULL){
continue ;
}
CComPtr<IDispatch> pDispDoc;
pIE->get_Document(&pDispDoc);
CComQIPtr<IHTMLDocument2> pHtmlDoc(pDispDoc);
if (pHtmlDoc){
pCurIE = pIE;
SuccessToHook = true;
break ;
}
}
ShowMessage(SuccessToHook ? "Success to hook." : "Failed to hook." );
}
Теперь я могу контролировать текущий запущенный IE, например, навигацию и читать текущее состояние. Но так как я хочу показывать сообщения, когда запускаются события типа onDocumentComplete Event. Я понятия не имею, как прослушать событие после моего текущего кода. Простой пример кода с BCB будет очень полезен, так как есть несколько примеров с VC++, но мой проект на C++ XE2.
Спасибо @ Реми Лебо и этой ссылке, я наконец-то решил свою проблему. Я оставляю свой код здесь и надеюсь, что он может быть полезным для кого-то еще.
Класс, полученный из TEventDispatcher
#include <exdisp.h>
#include <exdispid.h>
#include <mshtml.h>
#include <mshtmdid.h>
#include <utilcls.h>
//---------------------------------------------------------------------------
class TForm4;
class EventHandler:public TEventDispatcher<EventHandler,&DIID_DWebBrowserEvents2>{
private:
bool connected;
TForm4 *theform;
IUnknown* server;
protected:
HRESULT InvokeEvent(DISPID id, TVariant *params){
switch(id){
case DISPID_DOCUMENTCOMPLETE:
ShowMessage("On Document Complete");
break;
default:
break;
}
}
public:
EventHandler(){
connected = false; //not connected;
theform = false; //backptr to form is null
}
~EventHandler(){
if (connected)
Disconnect();
}
void Connect(TForm4 *form, IUnknown* srv){
server = srv;
theform = form; //back pointer to form to do stuff with it.
server->AddRef(); //addref the server
ConnectEvents(server);
}
void Disconnect(){
DisconnectEvents(server); //disconnect the events
server->Release();
}
};
Начать слушать
void __fastcall TForm4::Button5Click(TObject *Sender)
{
Event = new EventHandler();
Event->Connect(this, pCurIE);
}
Хватит слушать
void __fastcall TForm4::Button6Click(TObject *Sender)
{
Event->Disconnect();
}
1 ответ
Вы должны написать класс в вашем коде, который реализует DWebBrowserEvents2
интерфейс. Затем вы можете запросить браузер для его IConnectionPointContainer
интерфейс, вызовите IConnectionPointContainer::FindConnectionPoint()
способ найти IConnectionPoint
что соответствует DWebBrowserEvents2
и позвоните IConnectionPoint::Advise()
метод, передавая ему экземпляр вашего класса. Не забудьте позвонить IConnectionPoint::Unadvise()
когда вы закончите, используя события.
Чтобы помочь вам в этом, вы можете получить свой класс из VCL TEventDispatcher
класс в utilcls.h. это ConnectEvents()
а также DisconnectEvents()
методы обрабатывают IConnectionPoint
вещи для вас. Затем вы просто переопределите абстрактный InvokeEvent()
метод (каждое из событий браузера имеет свои DISPID
ценности).