[개발/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 downloading\n");
}
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-%EC%BB%A8%ED%8A%B8%EB%A1%A4-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8
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
'IT-개발,DB' 카테고리의 다른 글
[개발/웹] 웹에서의 비동기 호출 : 고전적인 방식(FRAME 이용) (0) | 2015.01.29 |
---|---|
[ASP.NET] .NET Framework으로 웹 차트 및 그래프를 동적으로 생성 (0) | 2015.01.26 |
[ASP.NET] [GDI+] LineChart 그래프를 만들어보자. (ASP.NET using C#) (0) | 2015.01.22 |
[개발/VC++] SubClassing 하는 방법 (0) | 2015.01.15 |
[개발/VC] IE 서브클래싱(subclass) (0) | 2015.01.15 |
댓글