천객만래 [千客萬來] (It has an interminable succession of visitors)

[개발/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

Posted by SB패밀리

// 웹 페이지 <form 태그의 a 태그 anchor 값 찾기


bool CMyInternetExplorer::FindAnchor (bool bClick, bool bFocus,
      bool bName, bool bOuterText, bool bTooltip, bool bURL,
      LPCTSTR sName, LPCTSTR sOuterText, LPCTSTR sTooltip, LPCTSTR sURL)
{
    ASSERT (m_pWebBrowser != NULL);
    if (m_pWebBrowser == NULL)
        return false;
    
    HRESULT hr;
    IDispatch* pHtmlDocDispatch = NULL;
    IHTMLDocument2 * pHtmlDoc = NULL;
    bool bSearch = true;

    // Retrieve the document object.

    hr = m_pWebBrowser->get_Document (&pHtmlDocDispatch);
    if (SUCCEEDED (hr) && (pHtmlDocDispatch != NULL))
    {
        hr = pHtmlDocDispatch->QueryInterface 
            (IID_IHTMLDocument2,  (void**)&pHtmlDoc);
        if (SUCCEEDED (hr) && (pHtmlDoc != NULL))
        {
            IHTMLElementCollection* pColl = NULL;
            hr = pHtmlDoc->get_all (&pColl);

            if (SUCCEEDED (hr) && (pColl != NULL))
            {
                // Obtained the Anchor Collection...

                long nLength = 0;
                pColl->get_length (&nLength);
                
                for (int i = 0; i < nLength && bSearch; i++)
                {
                    COleVariant vIdx ((long)i, VT_I4);
                    
                    IDispatch* pElemDispatch = NULL;
                    IHTMLElement * pElem = NULL;
                    
                    hr = pColl->item (vIdx, vIdx, &pElemDispatch);
                    
                    if (SUCCEEDED (hr) && 
                                 (pElemDispatch != NULL))
                    {
                        hr = pElemDispatch->QueryInterface 
                           (IID_IHTMLElement, (void**)&pElem);
                        
                        if (SUCCEEDED (hr) && (pElem != NULL))
                        {
                            BSTR bstrTagName;
                            CString sTempTagName;
                            if (!FAILED (pElem->get_tagName 
                                                 (&bstrTagName)))
                            {
                                sTempTagName = bstrTagName;
                                SysFreeString (bstrTagName);
                            }
                            
                            if (sTempTagName == _T ("a") || 
                                        sTempTagName == _T ("A"))
                            {
                                IHTMLAnchorElement * pAnchor = NULL;
                                hr = pElemDispatch->QueryInterface
                                   (IID_IHTMLAnchorElement, 
                                   (void**)&pAnchor);
                                
                                if (SUCCEEDED (hr) && 
                                               (pAnchor != NULL))
                                {
                                    BSTR bstrName, bstrOuterText, 
                                                 bstrURL, bstrTooltip;
                                    CString sTempName, sTempOuter, 
                                                sTempURL, sTempTooltip;
                                    
                                    if (!FAILED (pElem->get_outerText 
                                                      (&bstrOuterText)))
                                    {
                                        sTempOuter = bstrOuterText;
                                        SysFreeString (bstrOuterText);
                                    }
                                    if (!FAILED 
                                      (pElem->get_title 
                                      (&bstrTooltip)))
                                    {
                                        sTempTooltip = bstrTooltip;
                                        SysFreeString (bstrTooltip);
                                    }
                                    if 
                                      (!FAILED (pAnchor->get_name 
                                      (&bstrName)))
                                    {
                                        sTempName = bstrName;
                                        SysFreeString (bstrName);
                                    }
                                    if (!FAILED (pAnchor->get_href 
                                       (&bstrURL)))
                                    {
                                        sTempURL = bstrURL;
                                        SysFreeString (bstrURL);
                                    }

                                    // Do the comparison here!

                                    bool bMatches = true;
                                    if (bMatches && bName)
                                    {
                                      if 
                                      (!StringHelper::WildcardCompareNoCase 
                                      (sName, sTempName))
                                            bMatches = false;
                                    }
                                    if (bMatches && bOuterText)
                                    {
                                      if 
                                       (!StringHelper::WildcardCompareNoCase
                                       (sOuterText, sTempOuter))
                                            bMatches = false;
                                    }
                                    if (bMatches && bURL)
                                    {
                                      if
                                       (!StringHelper::WildcardCompareNoCase
                                       (sURL, sTempURL))
                                            bMatches = false;
                                    }
                                    if (bMatches && bTooltip)
                                    {
                                      if 
                                      (!StringHelper::WildcardCompareNoCase 
                                        (sTooltip, sTempTooltip))
                                            bMatches = false;
                                    }
                                    
                                    if (bMatches)
                                    {
                                        // No need to search more!

                                        bSearch = false;
                                        
                                        if (bFocus)
                                            pAnchor->focus ();
                                        if (bClick)
                                            pElem->click ();
                                    }
                                    pAnchor->Release ();
                                }
                            }
                            pElem->Release ();
                        }
                        pElemDispatch->Release ();
                    }        
                }
                pColl->Release ();
            }
            pHtmlDoc->Release();
        }
        pHtmlDocDispatch->Release ();
    }
    
    if (bSearch == false)
        return true;

    return false;
}
Posted by SB패밀리

// 웹 페이지 <form 태그의 input 태그 값 채우기


bool CMyInternetExplorer::FindInput  (bool bClick, bool bSelect, 
          bool bChangeValue, bool bSetCheck,
          bool bType, bool bName, bool bValue, 
          LPCTSTR sTypeToLook, LPCTSTR sNameToLook, 
          LPCTSTR sValueToLook,
          bool bNewCheckValue, LPCTSTR sNewValue)
{
    ASSERT (m_pWebBrowser != NULL);
    if (m_pWebBrowser == NULL)
        return false;
    
    HRESULT hr;
    IDispatch* pHtmlDocDispatch = NULL;
    IHTMLDocument2 * pHtmlDoc = NULL;
    bool bSearch = true;

    // Retrieve the document object.

    hr = m_pWebBrowser->get_Document (&pHtmlDocDispatch);
    if (SUCCEEDED (hr) && (pHtmlDocDispatch != NULL))
    {
        hr = pHtmlDocDispatch->QueryInterface 
           (IID_IHTMLDocument2,  (void**)&pHtmlDoc);
        if (SUCCEEDED (hr) && (pHtmlDoc != NULL))
        {
            IHTMLElementCollection* pColl = NULL;
            hr = pHtmlDoc->get_all (&pColl);

            if (SUCCEEDED (hr) && (pColl != NULL))
            {
                // Obtained the Anchor Collection...

                long nLength = 0;
                pColl->get_length (&nLength);
                
                for (int i = 0; i < nLength && bSearch; i++)
                {
                    COleVariant vIdx ((long)i, VT_I4);
                    
                    IDispatch* pElemDispatch = NULL;
                    IHTMLElement * pElem = NULL;
                    
                    hr = pColl->item (vIdx, vIdx, &pElemDispatch);
                    
                    if (SUCCEEDED (hr) && (pElemDispatch != NULL))
                    {
                        hr = pElemDispatch->QueryInterface 
                          (IID_IHTMLElement, (void**)&pElem);
                        
                        if (SUCCEEDED (hr) && (pElem != NULL))
                        {
                            BSTR bstrTagName;
                            CString sTempTagName;
                            if (!FAILED (pElem->get_tagName 
                                              (&bstrTagName)))
                            {
                                sTempTagName = bstrTagName;
                                sTempTagName.MakeLower ();
                                //AfxMessageBox (sTempTagName);

                                SysFreeString (bstrTagName);
                            }
                            if (sTempTagName == _T ("input"))
                            {
                                IHTMLInputElement * pInputElem = NULL;
                                hr = pElemDispatch->QueryInterface 
                                  (IID_IHTMLInputElement, 
                                  (void**)&pInputElem);
                                
                                if (SUCCEEDED (hr) && 
                                            (pInputElem != NULL))
                                {
                                    BSTR bstrType, bstrName, bstrValue;
                                    CString sTempType, 
                                      sTempName, sTempValue;
                                    
                                    if (!FAILED 
                                       (pInputElem->get_type 
                                       (&bstrType)))
                                    {
                                        sTempType = bstrType;
                                        SysFreeString (bstrType);
                                    }
                                    if (!FAILED (pInputElem->get_name 
                                        (&bstrName)))
                                    {
                                        sTempName = bstrName;
                                        SysFreeString (bstrName);
                                    }
                                    if (!FAILED 
                                      (pInputElem->get_value 
                                      (&bstrValue)))
                                    {
                                        sTempValue = bstrValue;
                                        SysFreeString (bstrValue);
                                    }
                                    // Do the comparison here!

                                    bool bMatches = true;
                                    if (bMatches && bType)
                                    {
                                      if 
                                       (!StringHelper::WildcardCompareNoCase
                                        (sTypeToLook, sTempType))
                                            bMatches = false;
                                    }
                                    if (bMatches && bName)
                                    {
                                      if 
                                       (!StringHelper::WildcardCompareNoCase 
                                        (sNameToLook, sTempName))
                                            bMatches = false;
                                    }
                                    if (bMatches && bValue)
                                    {
                                      if 
                                       (!StringHelper::WildcardCompareNoCase 
                                        (sValueToLook, sTempValue))
                                            bMatches = false;
                                    }
                                    
                                    if (bMatches)
                                    {
                                      // No need to search more!

                                      bSearch = false;

                                      if (bSetCheck)
                                      {
                                         if (bNewCheckValue)
                                           pInputElem->put_checked 
                                                      (VARIANT_TRUE);
                                         else
                                            pInputElem->put_checked 
                                                   (VARIANT_FALSE);
                                      }
                                      if (bChangeValue)
                                      {
                                        CString sTemp (sNewValue);
                                        BSTR bstrNewValue = 
                                             sTemp.AllocSysString ();
                                        pInputElem->put_value 
                                            (bstrNewValue);
                                        SysFreeString 
                                           (bstrNewValue);
                                      }
                                      if (bSelect)
                                        pInputElem->select ();

                                      if (bClick)
                                         pElem->click ();
                                    }
                                    pInputElem->Release ();
                                }
                            }
                            pElem->Release ();
                        }
                        pElemDispatch->Release ();
                    }        
                }
                pColl->Release ();
            }
            pHtmlDoc->Release();
        }
        pHtmlDocDispatch->Release ();
    }

    if (bSearch == false)
        return true;
    
    return false;
}
Posted by SB패밀리



[개발/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

Posted by SB패밀리


[펌] ActiveX에서 javascript 함수 호출방법


출처 : http://k.80port.net/board/view.php?id=techboard&page=5&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=headnum&desc=asc&no=140

void CallScript()

{
    HRESULT hr;
    IWebBrowser2 * pparent=NULL;
    pparent = (IWebBrowser2*) GetIWebPointer();
    LPDISPATCH lpDispatch = NULL;


    hr = pparent->get_Document(&lpDispatch);
    if (!SUCCEEDED(hr))
    {
        AfxMessageBox("error get document");
        lpDispatch->Release();
        return;
    }

    IHTMLDocument2 *m_pDoc2;
    hr = lpDispatch->QueryInterface(IID_IHTMLDocument2, (void**) &m_pDoc2);
    if (!SUCCEEDED(hr))
    {
        AfxMessageBox("error get document interface");
        m_pDoc2->Release();
        return;
    }
   
    CComQIPtr< IHTMLDocument > pDoc( m_pDoc2 );

    //
    // 스크립트 엔진의 디스패치 를 얻는다.
    //

    CComPtr< IDispatch > pDisp;
    hr = pDoc->get_Script( &pDisp );

    //
    // 스크립트 엔진디스패치에서 주어진 함수를 찾는다. 즉 dispid를 세트.
    //

    OLECHAR FAR* szFunctionName = L"EndUpload";        // 호출할 Javascript 명
    DISPID dispid;

    hr = pDisp->GetIDsOfNames( IID_NULL, &szFunctionName, 1,
                              LOCALE_SYSTEM_DEFAULT, &dispid);

    //
    // Invoke하기 위한 파라미터 세트.
    //

    DISPPARAMS dispParams;
    dispParams.rgvarg = NULL;
    dispParams.rgdispidNamedArgs = NULL;
    dispParams.cArgs = 0;
    dispParams.cNamedArgs = 0;

    hr = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
                       DISPATCH_METHOD, &dispParams, NULL, NULL, NULL);
 }

 

방법 2

void CallScript()
{
    LPOLECLIENTSITE pIClientSite;
    IDispatch* pIHTMLDocument = NULL;
    IHTMLDocument2* pDoc = NULL;
    IServiceProvider* pISP = NULL;

    CComPtr< IDispatch > pDisp;

    try
    {
        pIClientSite = GetClientSite();
       
        hr = pIClientSite->QueryInterface(IID_IServiceProvider, (void**)&pISP);
        if (hr != S_OK) throw 0;
       
        hr = pISP->QueryService(SID_SContainerDispatch, IID_IDispatch, (void **)&pIHTMLDocument);
        if (hr != S_OK) throw 0;

        hr = pIHTMLDocument->QueryInterface(IID_IHTMLDocument2,(void**)&pDoc);
        if (hr != S_OK) throw 0;
       
        hr = pDoc->get_Script( &pDisp );
        if (hr != S_OK) throw 0;
       
        OLECHAR FAR* szFunctionName = L"EndUpload";        // 호출할 Javascript 명
       
        DISPID dispid;
       
        hr = pDisp->GetIDsOfNames( IID_NULL, &szFunctionName, 1,  LOCALE_SYSTEM_DEFAULT, &dispid);
        if (hr != S_OK) throw 0;
       
        DISPPARAMS dispParams;
        dispParams.rgvarg = NULL;
        dispParams.rgdispidNamedArgs = NULL;
        dispParams.cArgs = 0;
        dispParams.cNamedArgs = 0;
       
        hr = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispParams, NULL, NULL, NULL);
        if (hr != S_OK) throw 0;

    }
    catch (...)
    {
         
    }

    if(pDoc) pDoc->Release();   
    if(pIHTMLDocument) pIHTMLDocument->Release();   
    if(pISP) pISP->Release();   
    if(pDisp) pDisp->Release();
//    if(pIClientSite) pIClientSite->Release();
}
 

Posted by SB패밀리
1. IWebBrowser2 에서 IHTMLDocument2 인터페이스 구하기

IWebBrowser2 *m_pWebFromUnknown;
IWebBrowser2 *m_pWebFromDoc;

STDMETHODIMP CTestObj::SetSite( IUnknown *pUnkSite )
{
    IOleClientSite *pClientSite;
    HRESULT hr;

    hr = pUnkSite-> QueryInterface( IID_IOleClientSite, 
    (LPVOID *)&pClientSite );
    if ( FAILED( hr ) ) return S_OK;

    IOleContainer *pContainer;
    hr = pClientSite-> GetContainer( &pContainer );
    pClientSite-> Release();
    if ( FAILED( hr ) ) return S_OK;
    
    IServiceProvider *pServiceProvider;
    hr = pContainer-> QueryInterface( IID_IServiceProvider, 
    (LPVOID *)&pServiceProvider );
    pContainer-> Release();
    if ( FAILED( hr ) ) return S_OK;

    hr = pServiceProvider-> QueryService( 
SID_SWebBrowserApp, IID_IWebBrowser2, (LPVOID *)
&m_pWebFromUnknown );
    pServiceProvider-> Release();
    if ( FAILED( hr ) ) return S_OK;

    LPDISPATCH pDocDisp;
    hr = m_pWebFromUnknown-> get_Document( &pDocDisp );
    m_pWebFromUnknown-> Release();

    return S_OK;
}

 

2. IHTMLDocument2 에서 IWebBrowser2 인터페이스 구하기


STDMETHODIMP CTestObj::setdoc(LPDISPATCH lpDisp)
{
// IHTMLDocument2 인터페이스 포인터에서 IWebBrowser2 인터페이스 
포인터를 구합니다.

    CComQIPtr<  IHTMLDocument2>  pDoc = lpDisp;

    IOleCommandTarget *pCmdTarget = NULL;
    pDoc-> QueryInterface( IID_IOleCommandTarget, (LPVOID *)
&pCmdTarget );

    if ( pCmdTarget ) {
        IServiceProvider *pSP;
        HRESULT hr = pCmdTarget-> QueryInterface( 
        IID_IServiceProvider, (LPVOID *)&pSP );
        pCmdTarget-> Release();

        if ( SUCCEEDED( hr ) ) {
            hr = pSP-> QueryService( 
            SID_SWebBrowserApp, IID_IWebBrowser2, (LPVOID *)&m_pWebFromDoc );

        }
    }

    if ( m_pWebFromDoc == m_pWebFromUnknown ) {
        ::MessageBox( NULL, "똑같습니
            다.", "IWebBrowser2 인터페이스 포인터 비교", MB_OK );
    }

    return S_OK;
}
 
 
Posted by SB패밀리