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

익스플로러에서 새창이 생성될때 그 창의 포인터를 얻는 방법






익스플로러에서 새창이 생성되면 Newwindow2이벤트가 일어납니다. 새로 생성된 익스플로러창의 포인터를 얻는 방법이 있나요? 
제가 만든 브라우저가 포함된 다이얼로그 폼으로 Set하면 됩니다. 그러나 일반적으로 생성되는 새창의 포인터를 얻고 싶습니다. 즉, IWebBrowser2의 포인터를 얻고 싶습니다. 그 이유는 현재창에 이벤트를 sink시키고 새로운 창이 생기면 그 창도 이벤트를 sink시키려고 하는데 새로운 창의 IWebBrowser2포인터를 얻어 올 수가 없어요.. 
그래서, 브라우저 인스턴스를 만들고 그 브라우저의 IWebBrowser2포인터의 Get_Application()함수를 이용하여 ppDisp에 넘겼는데 새로운창도 뜨고, 인스턴스로 생성한 창도 떠서 두개가 뜨게 됩니다. 
다음은 브라우저컨트롤이 포함된 다이얼로그의 예제입니다.

void CMyIETestDlg::OnNewWindow2Explorer(LPDISPATCH FAR* ppDisp, BOOL FAR* Cancel) 

 // TODO: Add your control notification handler code here 
 CMyIETestDlg *m_dlgNewWB = new CMyIETestDlg; 
 m_dlgNewWB->Create(IDD_MYIETEST_DIALOG); 
 *ppDisp = m_dlgNewWB->m_pIE.GetApplication(); 
}

위와 같이 자기가 만든 다이얼로그폼안의 웹브라우저의 포인터를 ppDisp에 넘겨주면 되는데.. 다음과 같이 하면 되지 않아요.. 좋은 방법이 있으면 알려주세요.

void CMyIETestDlg::OnNewWindow2Explorer(LPDISPATCH FAR* ppDisp, BOOL FAR* Cancel) 

 IWebBrowser2 *m_pIE=NULL; 
 HRESULT hr = CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, (void**)&m_pIE); 
 m_pIE->get_Application (ppDisp); 
}


void CMyIETestDlg::OnNewWindow2Explorer(LPDISPATCH FAR* ppDisp, BOOL FAR* Cancel)
{
 IWebBrowser2 *m_pIE=NULL;
 HRESULT hr = CoCreateInstance(CLSID_InternetExplorer, NULL,
 CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, (void**)&m_pIE);
 m_pIE->get_Application (ppDisp);
}

여기에서 LPDISPATCH FAR* ppDisp 로 넘어온 포인터가 새로운
웹브라우져의 IDispatch 인터페이스 포인터를 받는 포인터입니다.
즉, 원하시는 포인터가 해당 파라미터로 넘어오고 이때 이벤트를
싱크시키면 됩니다.


출처 : 인터넷

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패밀리
[개발/VC] 웹페이지 로드될 때까지 기다리기

m_pWebBrowser->Navigate(...); 로 페이지 호출 후 페이지가 로딩 완료될 때까지 기다리는 함수이다.

bool CMyInternetExplorer::WaitTillLoaded (int nTimeout)
{
    READYSTATE result;
    DWORD nFirstTick = GetTickCount ();

    do
    {
        m_pWebBrowser->get_ReadyState (&result);
        
        if (result != READYSTATE_COMPLETE)
            Sleep (250);
        
        if (nTimeout > 0)
        {
            if ((GetTickCount () - nFirstTick) > nTimeout)
                break;
        }
    } while (result != READYSTATE_COMPLETE);

    if (result == READYSTATE_COMPLETE)
        return true;
    else
        return false;
}
Posted by SB패밀리

IE 의 URL을 구하는 것은 생각보다 쉽습니다.
좋은 예제파일이 함께 있어서 올려봅니다.
따라해 보세요.

실행중인 IE의 URL 구하기
 
// URL을 추출합니다. ASSERT(m_spSHWinds != NULL);
long nCount = m_spSHWinds->GetCount();
IDispatchPtr spDisp;
for (long i = 0; i < nCount; i++)

 _variant_t va(i, VT_I4); 
 spDisp = m_spSHWinds->Item(va); 
 SHDocVw::IWebBrowser2Ptr spBrowser(spDisp);
 if (spBrowser != NULL)  
  m_ctrlUrlList.AddString(spBrowser->GetLocationURL());


출처 : 인터넷

Posted by SB패밀리


익스플로러에서 새창이 생성될때 그 창의 포인터를 얻는 방법

익스플로러에서 새창이 생성되면 Newwindow2이벤트가 일어납니다. 새로 생성된 익스플로러창의 포인터를 얻는 방법이 있나요?
제가 만든 브라우저가 포함된 다이얼로그 폼으로 Set하면 됩니다. 그러나 일반적으로 생성되는 새창의 포인터를 얻고 싶습니다. 즉, IWebBrowser2의 포인터를 얻고 싶습니다. 그 이유는 현재창에 이벤트를 sink시키고 새로운 창이 생기면 그 창도 이벤트를 sink시키려고 하는데 새로운 창의 IWebBrowser2포인터를 얻어 올 수가 없어요..
그래서, 브라우저 인스턴스를 만들고 그 브라우저의 IWebBrowser2포인터의 Get_Application()함수를 이용하여 ppDisp에 넘겼는데 새로운창도 뜨고, 인스턴스로 생성한 창도 떠서 두개가 뜨게 됩니다.
다음은 브라우저컨트롤이 포함된 다이얼로그의 예제입니다.

void CMyIETestDlg::OnNewWindow2Explorer(LPDISPATCH FAR* ppDisp, BOOL FAR* Cancel)
{
 // TODO: Add your control notification handler code here
 CMyIETestDlg *m_dlgNewWB = new CMyIETestDlg;
 m_dlgNewWB->Create(IDD_MYIETEST_DIALOG);
 *ppDisp = m_dlgNewWB->m_pIE.GetApplication();
}

위와 같이 자기가 만든 다이얼로그폼안의 웹브라우저의 포인터를 ppDisp에 넘겨주면 되는데.. 다음과 같이 하면 되지 않아요.. 좋은 방법이 있으면 알려주세요.

void CMyIETestDlg::OnNewWindow2Explorer(LPDISPATCH FAR* ppDisp, BOOL FAR* Cancel)
{
 IWebBrowser2 *m_pIE=NULL;
 HRESULT hr = CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, (void**)&m_pIE);
 m_pIE->get_Application (ppDisp);
}


void CMyIETestDlg::OnNewWindow2Explorer(LPDISPATCH FAR* ppDisp, BOOL FAR* Cancel)
{
 IWebBrowser2 *m_pIE=NULL;
 HRESULT hr = CoCreateInstance(CLSID_InternetExplorer, NULL,
 CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, (void**)&m_pIE);
 m_pIE->get_Application (ppDisp);
}

여기에서 LPDISPATCH FAR* ppDisp 로 넘어온 포인터가 새로운
웹브라우져의 IDispatch 인터페이스 포인터를 받는 포인터입니다.
즉, 원하시는 포인터가 해당 파라미터로 넘어오고 이때 이벤트를
싱크시키면 됩니다.


출처 : 인터넷

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패밀리
쌈꼬쪼려 소백촌닭

출처 : http://support.microsoft.com/kb/324419/ko

 아래 내용은 더 이상 마이크로소프트사에서 지원하지 않는 내용으로 언제 제거가 될지 몰라 복사하여 나름대로 정리하였습니다.

 기술 자료: 324419 - 마지막 검토: 2003년 5월 12일 월요일 - 수정: 2.0
BUG: 사용자가 BeforeNavigate에서 다시 탐색할 때 스크롤 막대 및 테두리의 프레임셋 나타난다


스크롤 막대 제거
테두리 제거

 

[현상]

 

다음 조건에 해당하는 경우 빈 스크롤 막대 및 경우에 따라 테두리가 나타납니다. 프레임셋을 WebBrowser 컨트롤을 호스팅하는 응용 프로그램...다음 조건에 해당하는 경우 빈 스크롤 막대 및 경우에 따라 테두리가 나타납니다.

- 프레임셋을 WebBrowser 컨트롤을 호스팅하는 응용 프로그램을 표시합니다. - 및 -

- BeforeNavigate 또는 BeforeNavigate2 이벤트 처리기 내의 다른 곳에서 프레임셋의 프레임에 이동합니다.

이러한 항목은 프레임에서 나타나지 않아야 합니다.


[해결 방법]

스크롤 막대 사용하여 문제를 해결하려면 다음 방법 중 하나를 사용하십시오.

- 프레임 페이지의 HTML 원본을 수동으로 "자동" 또는 "아니요" 값...스크롤 막대 사용하여 문제를 해결하려면 다음 방법 중 하나를 사용하십시오.
프레임 페이지의 HTML 원본을 수동으로 "자동" 또는 "아니요" 값을 <body>태그 스크롤 특성을 추가하십시오.
- 스크롤 특성을 동적으로 통해 동적 HTML(DHTML) 추가하십시오.
- 사용자 정의 메시지 게시 및 사용자 정의 메시지 처리기 탐색을 수행하는 탐색을 지연하십시오.

테두리가 문제를 해결하려면 다음 방법 중 하나를 사용하십시오.

- 사용자 정의 메시지, 게시 후 탐색 사용자 정의 메시지 처리기에서 수행하십시오.
- IDocHostUIHandler 인터페이스를 구현하고 DOCHOSTUIFLAG_NO3DBORDER GetHostInfo 메서드를 반환하십시오
.

자세한 내용은 이 문서의 "추가 정보" 절을 참조하십시오.


[현재 상태]

Microsoft는 이 문서의 시작 부분에 나열한 제품에서 문제를 확인했습니다.Microsoft는 이 문서의 시작 부분에 나열한 제품에서 문제를 확인했습니다.


[추가 정보]

Windows Mobile 기반 스마트폰에 GPRS 연결이 구성되어 있는지 확인합니다참고: 이 단계는 Microsoft Visual C++ 6....Windows Mobile 기반 스마트폰에 GPRS 연결이 구성되어 있는지 확인합니다
참고: 이 단계는 Microsoft Visual C++ 6.0 기록됩니다.

 

1. 프레임셋 페이지의 만들려면 다음 코드를 사용하고 페이지 frameset.htm 이름:
------------------------------------------------------------------------------------------
<HTML>
 <FRAMESET rows="100%" cols="33%,33%,34%">
  <FRAME src="http://aplus.pe.kr/zbxe/framesetChild.htm" frameborder="0" scrolling="0">
  </FRAME>
  <FRAME src="http://aplus.pe.kr/zbxe/framesetChild.htm" frameborder="0" scrolling="0">
  </FRAME>
  <FRAME src="http://aplus.pe.kr/zbxe/framesetChild.htm" frameborder="0" scrolling="0">
  </FRAME>
 </FRAMESET>
</HTML>

------------------------------------------------------------------------------------------     

2. frameset.htm 웹 서버에 복사하십시오.
3. 다음 코드를 사용하여 프레임 페이지 만들기 및 페이지 framesetChild.htm 이름:
------------------------------------------------------------------------------------------
<HTML>
 <body>
  This is a frame<br>
 </body>
</HTML>
------------------------------------------------------------------------------------------

4. framesetChild.htm 웹 서버에 복사하십시오.
5. 기본 Microsoft Foundation 클래스 (MFC) 대화 상자 기반 응용 프로그램을 만듭니다.
6. 대화 상자를 마우스 오른쪽 단추로 클릭한 다음 ActiveX 컨트롤 삽입 을 클릭하십시오. Microsoft 웹 브라우저 컨트롤 을 클릭하십시오.
7. WebBrowser 컨트롤의 컨트롤의 데이터 구성원을 추가하려면 다음과 같이 하십시오.

 a. 클래스 마법사를 열고 멤버 변수 탭을 클릭하십시오.
 b. 대화 상자 클래스에 클래스 이름 목록에서 선택되어 있는지 확인하십시오.
 c. WebBrowser 컨트롤의 기본 ID가 되는 IDC_EXPLORER1 를 클릭한 다음 변수 추가 클릭하십시오.
 d. 컨트롤 프로젝트에 삽입되지 않는 것을 알리는 메시지가 나타납니다. 컨트롤을 프로젝트에 추가하고 확인 클릭하십시오. CWebBrowser2 클래스의 클래스 확인 대화 상자에서 기본값을 다시 확인 을 클릭하십시오.
 e. 사용자의 멤버 변수 m_webBrowser, 이름을 지정한 다음 확인 을 누릅니다.
 f. 클래스 마법사를 닫습니다.

8. BeforeNavigate2 이벤트 처리기를 추가하려면 다음과 같이 하십시오.

 a. 클래스 마법사를 열고 메시지 맵 탭을 클릭하십시오.
 b. 대화 상자 클래스에 클래스 이름 목록에서 선택되어 있는지 확인하십시오.
 c. IDC_EXPLORER1개체 ID 목록에서 클릭한 다음 메시지 목록에서 BeforeNavigate2 를 클릭하십시오.
 d. 처리기를 추가하려면 함수 추가 클릭하십시오.
 
9. 다음 코드를 추가하여:
------------------------------------------------------------------------------------------
void CMFCReproDlg::OnBeforeNavigate2Explorer1(LPDISPATCH pDisp, VARIANT FAR* URL, VARIANT FAR* Flags, VARIANT FAR* TargetFrameName, VARIANT FAR* PostData, VARIANT FAR* Headers, BOOL FAR* Cancel)
{
 static int nCount = 0;

 nCount++;
 if (nCount == 2) // this should be the navigate for the first frame in frameset
 {
  IWebBrowser* pWB = NULL;
  HRESULT hr = pDisp->QueryInterface(IID_IWebBrowser, (void**)&pWB);
  COleVariant ve((long)0);
  pWB->Navigate(::SysAllocString(L"
http://myserver/mydirectory/framesetChild.htm"), &ve, &ve, &ve, &ve);
  *Cancel = VARIANT_TRUE;
 }
}
     
------------------------------------------------------------------------------------------

10. OnInitDialog 함수의 끝에 있는 프레임 페이지를 탐색하려면 다음 코드를 추가합니다.
------------------------------------------------------------------------------------------
BOOL CMFCReproDlg::OnInitDialog()
{
 ...
 m_webBrowser.Navigate("
http://myserver/mydirectory/frameset.htm", NULL, NULL, NULL, NULL);
  
   
------------------------------------------------------------------------------------------

11. 응용 프로그램을 빌드하고 이를 실행하십시오. 첫 번째 프레임 스크롤 막대 및 테두리를 오른쪽에 연관되어 있습니다.

 

스크롤 막대 제거

스크롤 막대를 제거하려면 다음 방법 중 하나를 사용하십시오.

- 스크롤 특성 값이 "자동" 또는 "아니요" framesetChild.htm 페이지에 다음과 같은 추가:
------------------------------------------------------------------------------------------
<HTML>
 <body scroll="auto">
  This is a frame<br>
 </body>
</HTML>
------------------------------------------------------------------------------------------

- 동적으로 스크롤 특성 값이 "자동" 또는 "아니요" DHTML 통해 코드에서 다음과 같은 추가:

------------------------------------------------------------------------------------------
#include <mshtml.h>
// For brevity, this code adds the attribute to all documents.
void CMFCReproDlg::OnDocumentCompleteExplorer1(LPDISPATCH pDisp, VARIANT FAR* URL)
{
 HRESULT hr = S_OK;
 IWebBrowser2* pWB = NULL;

 hr = pDisp->QueryInterface(IID_IWebBrowser2, reinterpret_cast<void**>(&pWB));
 
 IDispatch* pDocDisp = NULL;
 hr = pWB->get_Document(&pDocDisp);
 
 if (pDocDisp)
 {
  VARIANT v;
  VariantInit(&v);

  IHTMLDocument2* pDoc = NULL;
  hr = pDocDisp->QueryInterface(IID_IHTMLDocument2, reinterpret_cast<void **>(&pDoc));

  IHTMLElement* pElement = NULL;
  hr = pDoc->get_body(&pElement);

  IHTMLBodyElement* pBodyElement = NULL;
  hr = pElement->QueryInterface(IID_IHTMLBodyElement, (void**)&pBodyElement);

  if (pBodyElement)
  {
   pBodyElement->put_scroll(::SysAllocString(L"auto"));  // "no"
   pBodyElement->Release();
  }
  pElement->Release();
  pDoc->Release();
  pDocDisp->Release();
 }
 pWB->Release();
}

------------------------------------------------------------------------------------------ 

참고: 이 처음 두 옵션 경우에만 스크롤 막대를 제거합니다. 테두리 여전히 지속될 수 있습니다.

- 사용자 정의 메시지, 게시 후 탐색 탐색 지연시킬 수 있는 사용자 정의 메시지 처리기가 수행하십시오.


헤더 파일에 다음 코드를 추가하여:
------------------------------------------------------------------------------------------
class CMFCReproDlg : public CDialog
{
...
 afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
};
      
------------------------------------------------------------------------------------------

구현 파일에 다음 코드를 추가합니다:
------------------------------------------------------------------------------------------
#define WM_MYMESSAGE (WM_USER + 1)
BEGIN_MESSAGE_MAP(CMFCReproDlg, CDialog)
 //{{AFX_MSG_MAP(CMFCReproDlg)
 ON_WM_SYSCOMMAND()
 ON_WM_PAINT()
 ON_WM_QUERYDRAGICON()
 //}}AFX_MSG_MAP
 ON_MESSAGE(WM_MYMESSAGE, OnMyMessage)
END_MESSAGE_MAP()

struct CMyData
{
 IWebBrowser2* m_pWB;
 BSTR m_pUrl;
};

void CMFCReproDlg::OnBeforeNavigate2Explorer1(LPDISPATCH pDisp, VARIANT FAR* URL, VARIANT FAR* Flags, VARIANT FAR* TargetFrameName, VARIANT FAR* PostData, VARIANT FAR* Headers, BOOL FAR* Cancel)
{
 static int nCount = 0;

 nCount++;
 if (nCount == 2) // this should be the navigate for the first frame in frameset
 {
        *Cancel = VARIANT_TRUE;
        CMyData *data = new CMyData;
  HRESULT hr = pDisp->QueryInterface(IID_IWebBrowser2, (void**)(&data->m_pWB));
        data->m_pUrl = ::SysAllocString(L"
http://myserver/mydirectory/framesetChild.htm");
  PostMessage(WM_MYMESSAGE, (WPARAM)data, 0);
 }
}
LRESULT CMFCReproDlg::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
    CMyData *data = (CMyData*)wParam;
    COleVariant ve((long)0);
    data->m_pWB->Navigate(data->m_pUrl, &ve, &ve, &ve, &ve);
    delete data;
 return 1;
}
     

------------------------------------------------------------------------------------------

 

테두리 제거


테두리를 제거하려면 다음 방법 중 하나를 사용하십시오.

 - 사용자 정의 메시지, 게시 후 탐색 사용자 정의 메시지 처리기에서 수행하십시오.

 - Microsoft 기술 자료 문서 Q196835 IDocHostUIHandler 인터페이스를 추가할 수 사용자 지정 컨트롤을 사이트를 제공할 수 있는 단계를 수행하십시오. 자세한 내용은 아래 문서 번호를 눌러 Microsoft 기술 자료에 있는 문서를 클릭하십시오.
 196835  (http://support.microsoft.com/kb/196835/EN-US/ ) HOWTO: MFC 기본 컨트롤 포함 무시

모든 함수를 구현하는 후 DOCHOSTUIFLAG_NO3DBORDER DOCHOSTUIINFO stucture GetHostInfo 메서드에 대한 dwFlags 필드에서 추가해야 합니다. IDocHostUIHandler 구현하는 단계를 제공하기 위해 이 문서에서는 다루지 않습니다.
참고: ATL 클래스 CAxHostWindow, IDocHostUIHandler 인터페이스를 구현하므로 ATL (액티브 템플릿 라이브러리) 컨테이너에서 테두리 문제가 나타나지 않습니다. 기본적으로 이 플래그는 CAxHostWindow 사용할 수 있습니다.


--------------------------------------------------------------------------------

본 문서의 정보는 다음의 제품에 적용됩니다.

Microsoft Internet Explorer 5.5

키워드:   kbmt kbbug kbpending KB324419 KbMtko

더 이상 지원되지 않는 제품의 KB 내용에 대한 고지 사항

이 문서에서는 Microsoft에서 더 이상 지원하지 않는 제품에 대해 설명합니다. 따라서 이 문서는 "있는 그대로" 제공되며 업데이트되지 않습니다.

 

 

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패밀리