Google Answers Logo
View Question
 
Q: Recieving events from Internet Explorer ( No Answer,   4 Comments )
Question  
Subject: Recieving events from Internet Explorer
Category: Computers
Asked by: balshetzer-ga
List Price: $20.00
Posted: 19 Mar 2004 10:49 PST
Expires: 18 Apr 2004 11:49 PDT
Question ID: 318368
I am trying to use IE programmatically to do some web mining. I'm more
of a Java coder. I've never used COM, ATL or MFC before so I am a
little overwhelmed by the sheer amount of info I had to read just to
interface with the browser.

I wrote the following code as a test to open a browser window and
receive a single event (DocumentComplete) with the intention of then
retrieving the content and working with it.

However, when I run the code it opens a browser window, which hangs
until the event handler is unregistered at which point the page loads.
I don't understand this behavior. It only happens when I try to
connect an event handler.

Maybe I am making some kind of fundamental error. I have tried to
simplify the code as much as possible removing all attempts to use
ATL. I'd prefer not to have to learn MFC right now.

Here is the cpp file:
#include <stdio.h>
#include "header.h"

void EventHandler::DocumentComplete(IDispatch *pDisp, VARIANT *URL) {
   printf("event triggered");
}

int main(int argc, char* argv[])
{
   CoInitialize(NULL);

   SHDocVw::IWebBrowser2Ptr ie;
   ie.CreateInstance("InternetExplorer.Application");
   
   EventHandler handler;

   IUnknown *pUnk = NULL;
   IUnknown *pHandler = NULL;
   
   DWORD dwCookie;

   HRESULT hr;
   
   hr = handler.QueryInterface(IID_IUnknown, (void**)&pHandler);
   
   hr = ie.QueryInterface(IID_IUnknown, &pUnk);
   
   IConnectionPointContainer* pCPC = NULL;
   IConnectionPoint* pCP = NULL;
   
   // Check that this is a connectable object.
   hr = pUnk->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);
   
   if (SUCCEEDED(hr))
   {
      // Find the connection point.
      hr = pCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &pCP);
      
      if (SUCCEEDED(hr))
      {
         // Advise the connection point.
         hr = pCP->Advise(pHandler, &dwCookie);
         
         if (SUCCEEDED(hr))
         {
            printf("advised\n");
         }
      }
      
      pCPC->Release();
   }

   pUnk->Release();

   ie->Visible = true;
   ie->Navigate("www.microsoft.com");

   Sleep(5000);

   pCP->Unadvise(dwCookie);
   pCP->Release();
   // only at this point does the browser window "unhang"

   ie.Release();
   CoUninitialize();



	printf("done\n");
	return 0;
}

here is header.h (the commented out section was the simple way to
implement the handler. The uncommented is the long way. The stubs look
odd because they are copied out of the header file.):

#ifndef _COMMSTUFF_H
#define _COMMSTUFF_H

#import "shdocvw.dll"

#include <exdisp.h>    // browser control definitions
#include <exdispid.h>  // browser event dispatch IDs

/*
class EventHandler : public IDispEventImpl<1, EventHandler,
&DIID_DWebBrowserEvents2, &LIBID_SHDocVw>
{

public:

   BEGIN_SINK_MAP(EventHandler)
      SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2,
DISPID_DOCUMENTCOMPLETE, DocumentComplete)
   END_SINK_MAP()

   void _stdcall DocumentComplete(LPDISPATCH pDisp, VARIANT* URL);



};
*/

class EventHandler : public DWebBrowserEvents2
{
public:

   // IUnknown
   virtual HRESULT STDMETHODCALLTYPE QueryInterface( 
      /* [in] */ REFIID riid,
      /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) 
   {
      if (riid == IID_IUnknown || riid == IID_IDispatch || riid ==
DIID_DWebBrowserEvents2)
      {
         *ppvObject = (void*)this;
         return S_OK;
      }
      return E_NOINTERFACE;
   }
        
   virtual ULONG STDMETHODCALLTYPE AddRef() { return 1L; }
        
   virtual ULONG STDMETHODCALLTYPE Release() { return 1L; }

   // IDispatch
   virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount( 
   /* [out] */ UINT __RPC_FAR *pctinfo) 
      { return E_NOTIMPL; }
        
   virtual HRESULT STDMETHODCALLTYPE GetTypeInfo( 
      /* [in] */ UINT iTInfo,
      /* [in] */ LCID lcid,
      /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo) 
      { return E_NOTIMPL; }
        
   virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames( 
      /* [in] */ REFIID riid,
      /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
      /* [in] */ UINT cNames,
      /* [in] */ LCID lcid,
      /* [size_is][out] */ DISPID __RPC_FAR *rgDispId) 
      { return E_NOTIMPL; }
        
   virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke( 
      /* [in] */ DISPID dispIdMember,
      /* [in] */ REFIID riid,
      /* [in] */ LCID lcid,
      /* [in] */ WORD wFlags,
      /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
      /* [out] */ VARIANT __RPC_FAR *pVarResult,
      /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
      /* [out] */ UINT __RPC_FAR *puArgErr) 
      { return E_NOTIMPL; }


    void StatusTextChange (
       _bstr_t Text ){}
    void ProgressChange (
        long Progress,
        long ProgressMax ){}
    void CommandStateChange (
        long Command,
        VARIANT_BOOL Enable ){}
    void DownloadBegin ( ){}
    void DownloadComplete ( ){}
    void TitleChange (
        _bstr_t Text ){}
    void PropertyChange (
        _bstr_t szProperty ){}
    void BeforeNavigate2 (
        IDispatch * pDisp,
        VARIANT * URL,
        VARIANT * Flags,
        VARIANT * TargetFrameName,
        VARIANT * PostData,
        VARIANT * Headers,
        VARIANT_BOOL * Cancel ){}
    void NewWindow2 (
        IDispatch * * ppDisp,
        VARIANT_BOOL * Cancel ){}
    void NavigateComplete2 (
        IDispatch * pDisp,
        VARIANT * URL ){}
    void DocumentComplete (
        IDispatch * pDisp,
        VARIANT * URL );
    void OnQuit ( ){}
    void OnVisible (
       VARIANT_BOOL Visible ){ }
    void OnToolBar (
        VARIANT_BOOL ToolBar ){}
    void OnMenuBar (
        VARIANT_BOOL MenuBar ){}
    void OnStatusBar (
        VARIANT_BOOL StatusBar ){}
    void OnFullScreen (
        VARIANT_BOOL FullScreen ){}
    void OnTheaterMode (
        VARIANT_BOOL TheaterMode ){}
    void WindowSetResizable (
        VARIANT_BOOL Resizable ){}
    void WindowSetLeft (
        long Left ){}
    void WindowSetTop (
        long Top ){}
    void WindowSetWidth (
        long Width ){}
    void WindowSetHeight (
        long Height ){}
    void WindowClosing (
        VARIANT_BOOL IsChildWindow,
        VARIANT_BOOL * Cancel ){}
    void ClientToHostWindow (
        long * CX,
        long * CY ){}
    void SetSecureLockIcon (
        long SecureLockIcon ){}
    void FileDownload (
        VARIANT_BOOL * Cancel ){}
    void NavigateError (
        IDispatch * pDisp,
        VARIANT * URL,
        VARIANT * Frame,
        VARIANT * StatusCode,
        VARIANT_BOOL * Cancel ){}
    void PrintTemplateInstantiation (
        IDispatch * pDisp ){}
    void PrintTemplateTeardown (
        IDispatch * pDisp ){}
    void UpdatePageStatus (
        IDispatch * pDisp,
        VARIANT * nPage,
        VARIANT * fDone ){}
    void PrivacyImpactedStateChange (
        VARIANT_BOOL bImpacted ){}

};



#endif
Answer  
There is no answer at this time.

Comments  
Subject: Re: Recieving events from Internet Explorer
From: lizard43-ga on 19 Mar 2004 16:17 PST
 
I've done a bit of IE programming, but without compiling your code, I
don't have a clue what's wrong with your stuff.

Since you don't want to learn MFC or ATL, perhaps start with a already
working project?  Have you checked out Code Guru's IE page at:
http://www.codeguru.com/Cpp/I-N/ieprogram/

Or Code Project?  I couldn't easily find their IE articles, but I know
they have them somewhere:
http://codeproject.com

Hope this helped you on your journey...
Subject: Re: Recieving events from Internet Explorer
From: bluejayq-ga on 19 Mar 2004 16:52 PST
 
In order for COM to operate across processes, your app must be in a
state where it can receive messages. In other words, you need to have
some sort of message loop. Otherwise, the other app will hang trying
to send you a message.

The easiest solution is to replace your Sleep(5000) with something like (untested):

for (int i = 0; i < 5000; ++i)
{
  MSG msg;
  while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  {
     TranslateMessage(&msg);
     DispatchMessage(&msg);
  }
  Sleep(1);
}

This isn't really all that great because your app never goes idle and
the loop always takes 5 seconds regardles of how long the operation
actually takes. You'd be much better off using a standard message
loop:

MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
  TranslateMessage(&msg);
  DispatchMessage(&msg);
}

and then using a PostQuitMessage (or some other custom message) when
you want to break out of it (e.g. when your processing is done).

HTH

- Jay
Subject: Re: Recieving events from Internet Explorer
From: balshetzer-ga on 20 Mar 2004 09:00 PST
 
Thanks bluejay. I knew there was something fundamental about Windows
Programming that I was missing. If you would like the $20 please post
as an answer (I think thats how this web site works anyway).
Subject: Re: Recieving events from Internet Explorer
From: goo_gle_ga-ga on 23 Mar 2004 10:19 PST
 
please also be aware that DocumentComplete might not do what you
want.. the documentation indicates that DocumentComplete will fire
multiple times in a page with frames, which might confuse the app
youre trying to make. It also is not fired by any web navigating
component that is not visible on screen :/

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy