[개발/VC++] WebBrowser Control 이벤트 연결 – C++

[개발/VC++] WebBrowser Control 이벤트 연결 – C++
WebBrowser Control
IDispatch
IWebBrowser2
.ReadyState
READYSTATE_COMPLETE

.Navigate2()
.get_Document() // IDispatch -> IHTMLDocument2
.get_StatusText()

on DownloadBegin
on DocumentComplete
on DownloadComplete

IOleObject

 

IHTMLWindow2

IHTMLDocument2
.get_all()
.get_parentWindow() // IHTMLWindow2

IHTMLElementCollection
.item()
.tags // IHTMLElementCollection

IHTMLElement

a connectable object
IConnectionPointContainer
.FindConnectionPoint() // DHTMLElementEvents2

DHTMLElementEvents2
.Advise()

outgoing HTMLElementEvents2 interface // event sink object // the client event sink
IDispatch
.Invoke()

—————————————————————————————-
class CTryDlg : public CDialog
{
// Construction
public:
CTryDlg(CWnd* pParent = NULL);    // standard constructor

// Dialog Data
//{{AFX_DATA(CTryDlg)
enum { IDD = IDD_TRY_081209_DIALOG };
CWebBrowser2    m_webBrowser;
//}}AFX_DATA

// Generated message map functions
//{{AFX_MSG(CTryDlg)

afx_msg void OnDocumentCompleteExplorer1(LPDISPATCH pDisp, VARIANT FAR* URL);
DECLARE_EVENTSINK_MAP()
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

BOOL CTryDlg::OnInitDialog()
{

SetIcon(m_hIcon, FALSE);        // Set small icon

// TODO: Add extra initialization here
// {
COleVariant     szURL       = “http://www.google.com“;
m_webBrowser.Navigate2(szURL, NULL, NULL, NULL, NULL);
// }
return TRUE;  // return TRUE  unless you set the focus to a control
}

BEGIN_EVENTSINK_MAP(CTryDlg, CDialog)
//{{AFX_EVENTSINK_MAP(CTryDlg)
ON_EVENT(CTryDlg, IDC_EXPLORER1, 259 /* DocumentComplete */, OnDocumentCompleteExplorer1, VTS_DISPATCH VTS_PVARIANT)
//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()

void CTryDlg::OnDocumentCompleteExplorer1(LPDISPATCH lpDisp, VARIANT FAR* URL)
{
// TODO: Add your control notification handler code here
IUnknown*  pUnk;
LPDISPATCH lpWBDisp;
HRESULT    hr;

pUnk = m_webBrowser.GetControlUnknown();
ASSERT(pUnk);

hr = pUnk->QueryInterface(IID_IDispatch, (void**)&lpWBDisp);
ASSERT(SUCCEEDED(hr));

if (lpDisp == lpWBDisp )
{
// Top-level Window object, so document has been loaded
TRACE(“Web document is finished downloadingn”);
}

lpWBDisp->Release();
}
—————————————————————————————-

—————————————————————————————-
m_pBrowser // IWebBrowser2

// DWebBrowserEvents2::DocumentComplete
void CMyClass::DocumentComplete(LPDISPATCH pDisp, VARIANT* URL)
{
HRESULT hr;
IUnknown* pUnkBrowser = NULL;
IUnknown* pUnkDisp = NULL;
IDispatch* pDocDisp = NULL;
IHTMLDocument2* pDoc = NULL;

// Is this the DocumentComplete event for the top frame window?
// Check COM identity: compare IUnknown interface pointers.
hr = m_pBrowser->QueryInterface(IID_IUnknown, (void**)&pUnkBrowser);

if (SUCCEEDED(hr))
    {
hr = pDisp->QueryInterface(IID_IUnknown, (void**)&pUnkDisp);

if (SUCCEEDED(hr))
{
if (pUnkBrowser == pUnkDisp)
{
// This is the DocumentComplete event for the top frame.
// This page is loaded, so we can access the DHTML Object Model.
hr = m_pBrowser->get_Document(&pDocDisp);

if (SUCCEEDED(hr))
{
// Obtained the document object.
pDocDisp->QueryInterface(IID_IHTMLDocument2, (void**)&pDoc);
if (SUCCEEDED(hr))
{
// Obtained the IHTMLDocument2 interface for the document object
ProcessDocument(pDoc);
}

pDocDisp->Release();
}
}

pUnkDisp->Release();
}

pUnkBrowser->Release();
}
}

// IHTMLDocument2
void CMyClass::ProcessDocument(IHTMLDocument2* pDoc)
{
IHTMLElementCollection* pElemColl = NULL;

hr = pDoc->get_all(&pElemColl);
if (SUCCEEDED(hr))
{
// Obtained element collection.
ProcessElementCollection(pElemColl);
pElemColl->Release();
}
}

void CMyClass::ProcessElementCollection(IHTMLElementCollection* pElemColl)
{
IDispatch* pElemDisp = NULL;
IHTMLElement* pElem = NULL;
_variant_t varID(“myID”, VT_BSTR);
_variant_t varIdx(0, VT_I4);

hr = pElemColl->item(varID, varIdx, &pElemDisp);

if (SUCCEEDED(hr))
{
hr = pElemDisp->QueryInterface(IID_IHTMLElement, (void**)&pElem);

if (SUCCEEDED(hr))
{
// Obtained element with ID of “myID”.
ConnectEvents(pElem);
pElem->Release();
}

pElemDisp->Release();
}
}
void CMyClass::ConnectEvents(IHTMLElement* pElem)
{
HRESULT hr;
IConnectionPointContainer* pCPC = NULL;
IConnectionPoint* pCP = NULL;
DWORD dwCookie;

// Check that this is a connectable object.
hr = pElem->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);

if (SUCCEEDED(hr))
{
// Find the connection point.
hr = pCPC->FindConnectionPoint(DIID_HTMLElementEvents2, &pCP);

if (SUCCEEDED(hr))
{
// Advise the connection point.
// pUnk is the IUnknown interface pointer for your event sink
hr = pCP->Advise(pUnk, &dwCookie);

if (SUCCEEDED(hr))
{
// Successfully advised
}

pCP->Release();
}

pCPC->Release();
}
}
STDMETHODIMP CEventSink::Invoke(DISPID dispidMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS* pdispparams,
VARIANT* pvarResult,
EXCEPINFO* pexcepinfo,
UINT* puArgErr)
{
switch (dispidMember)
{
case DISPID_HTMLELEMENTEVENTS2_ONCLICK:
OnClick();
break;

default:
break;
}

return S_OK;
}

—————————————————————————————-

IOleInPlaceFrame
IOleClientSite
IOleInPlaceSite

EmbedBrowserObject()
window handle
_IOleClientSiteEx    // USERDATA
IOleInPlaceFrame
IOleClientSite
IOleInPlaceSite
IDocHostUIHandler

CoCreateInstance()
CLSID_WebBrowser
IWebBrowser2
.put_Left()
.put_Top()
.put_Width()
.put_Height()
.Navigate2()

IOleObject
.Close()
.SetClientSite() // IOleClientSite
.SetHostNames()
.DoVerb()

UnEmbedBrowserObject()

ResizeBrowser()

DisplayHTMLPage()

DoPageAction()

GetWebPtrs()
IHTMLDocument2

IHTMLElementCollection

GetWebElement()
IHTMLElement

CreateWebEvtHandler()

FreeWebEvtHandler()

WaitOnReadyState()

더보기
extern “C” {

HINSTANCE        cwebdll;

long WINAPI EmbedBrowserObject(HWND hwnd);
void WINAPI UnEmbedBrowserObject(HWND hwnd);
long WINAPI DisplayHTMLPage(HWND hWnd, const char *url);
void WINAPI ResizeBrowser(HWND hWnd, DWORD x, DWORD y);

}

int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR     lpCmdLine,
int       nCmdShow)
{
// TODO: Place code here.
// {
// Load our DLL containing the OLE/COM code. We do this once-only. It’s named “cwebpage.dll”
if (!(cwebdll = LoadLibrary(“cwebpage.dll”)))
{
MessageBox(0, “Can’t open cwebpage.dll!”, “ERROR”, MB_OK);
return(-1);
}
// }
MSG msg;
HACCEL hAccelTable;

// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);

}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
// {
case WM_CREATE:
// Embed the browser object into our host window. We need do this only
// once. Note that the browser object will start calling some of our
// IOleInPlaceFrame and IOleClientSite functions as soon as we start
// calling browser object functions in EmbedBrowserObject().
if (EmbedBrowserObject(hWnd)) return(-1);
DisplayHTMLPage(hWnd, “http://www.microsoft.com“);
break;
// }
case WM_DESTROY:
// {
// Detach the browser object from this window, and free resources.
UnEmbedBrowserObject(hWnd);
// }
PostQuitMessage(0);
break;
case WM_COMMAND:

break;
case WM_SIZE:
// Resize the browser object to fit the window
ResizeBrowser(hWnd, LOWORD(lParam), HIWORD(lParam));
break;

default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
참조 사이트:

http://support.microsoft.com/kb/315617/en-us/
http://msdn.microsoft.com/en-us/library/bb508508(VS.85).aspx
http://support.microsoft.com/kb/194179/en-us/
http://www.codeproject.com/KB/shell/dlgdhtmlevents.aspx?display=Print
http://msdn.microsoft.com/en-us/library/aa293017(VS.71).aspx
http://urassa.tistory.com/entry/Web-Browser-Control-FAQ

http://www.codeproject.com/KB/COM/cwebpage.aspx?display=Print
http://jjjryu.tistory.com/entry/IE-1
http://support.microsoft.com/kb/196339/en-us/
http://jjjryu.tistory.com/entry/ActiveX-컨트롤-클라이언트
http://www.codeproject.com/KB/shell/AutomateShellWindow.aspx?display=Print
http://www.codeproject.com/KB/shell/iehelper.aspx?display=Print

출처 : http://jjjryu.tistory.com/333