html.cpp
上传用户:zexelpump
上传日期:2007-01-04
资源大小:22k
文件大小:8k
源码类别:

WEB源码(ASP,PHP,...)

开发平台:

Visual C++

  1. /*
  2.     Implement an HTML parser using IE4's IHTMLDocument2 interface.
  3. */
  4. #include <windows.h>
  5. #include <comdef.h>
  6. #include <io.h>
  7. #include "html.h"
  8. #include <iostream>
  9. using namespace std;
  10. /*
  11. static function used to force dynamic allocation
  12. */
  13. HTMLParser *HTMLParser::Create()
  14. {
  15. return new HTMLParser;
  16. }
  17. // constructor/destructor
  18. HTMLParser::HTMLParser()
  19. {
  20. HRESULT hr;
  21. LPCONNECTIONPOINTCONTAINER pCPC = NULL;
  22. LPOLEOBJECT pOleObject = NULL;
  23. LPOLECONTROL pOleControl = NULL;
  24.     // initialize all the class member variables
  25.     m_dwRef = 1; // must start at 1 for the current instance
  26.     m_hrConnected = S_FALSE;
  27.     m_dwCookie = 0;
  28.     m_pMSHTML = NULL;
  29.     m_pCP = NULL;
  30.     m_pAnchorLinks = NULL;
  31.     m_pImageLinks = NULL;
  32. // Create an instance of an dynamic HTML document
  33. if (FAILED(hr = CoCreateInstance( CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER, IID_IHTMLDocument2, (LPVOID*)&m_pMSHTML )))
  34. {
  35. goto Error;
  36. }
  37. if (FAILED(hr = m_pMSHTML->QueryInterface(IID_IOleObject, (LPVOID*)&pOleObject)))
  38. {
  39. goto Error;
  40. }
  41. hr = pOleObject->SetClientSite((IOleClientSite*)this);
  42. pOleObject->Release();
  43. if (FAILED(hr = m_pMSHTML->QueryInterface(IID_IOleControl, (LPVOID*)&pOleControl)))
  44. {
  45. goto Error;
  46. }
  47. hr = pOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_DLCONTROL);
  48. pOleControl->Release();
  49. // Hook up sink to catch ready state property change
  50. if (FAILED(hr = m_pMSHTML->QueryInterface(IID_IConnectionPointContainer, (LPVOID*)&pCPC)))
  51. {
  52. goto Error;
  53. }
  54. if (FAILED(hr = pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &m_pCP)))
  55. {
  56. goto Error;
  57. }
  58. m_hrConnected = m_pCP->Advise((LPUNKNOWN)(IPropertyNotifySink*)this, &m_dwCookie);
  59. Error:
  60. if (pCPC) pCPC->Release();
  61. }
  62. HTMLParser::~HTMLParser()
  63. {
  64.     if ( m_pAnchorLinks )
  65.         m_pAnchorLinks->Release();
  66.     if ( m_pImageLinks )
  67.         m_pImageLinks->Release();
  68. if (SUCCEEDED(m_hrConnected))
  69. m_pCP->Unadvise(m_dwCookie);
  70. if (m_pCP) 
  71. m_pCP->Release();
  72.     if ( m_pMSHTML )
  73.         m_pMSHTML->Release();
  74. }
  75. STDMETHODIMP HTMLParser::QueryInterface(REFIID riid, LPVOID* ppv)
  76. {
  77. *ppv = NULL;
  78. if (IID_IUnknown == riid || IID_IPropertyNotifySink == riid)
  79. {
  80. *ppv = (LPUNKNOWN)(IPropertyNotifySink*)this;
  81. AddRef();
  82. return NOERROR;
  83. }
  84. else if (IID_IOleClientSite == riid)
  85. {
  86. *ppv = (IOleClientSite*)this;
  87. AddRef();
  88. return NOERROR;
  89. }
  90. else if (IID_IDispatch == riid)
  91. {
  92. *ppv = (IDispatch*)this;
  93. AddRef();
  94. return NOERROR;
  95. }
  96. else
  97. return E_NOTIMPL;
  98. }
  99. STDMETHODIMP_(ULONG) HTMLParser::AddRef()
  100. {
  101. return ++m_dwRef;
  102. }
  103. STDMETHODIMP_(ULONG) HTMLParser::Release()
  104. {
  105. if (--m_dwRef == 0) 
  106. delete this; 
  107. return 0; 
  108. }
  109. return m_dwRef;
  110. }
  111. STDMETHODIMP HTMLParser::OnChanged(DISPID dispID)
  112. {
  113. HRESULT hr;
  114. if (DISPID_READYSTATE == dispID)
  115. {
  116. VARIANT vResult = {0};
  117. EXCEPINFO excepInfo;
  118. UINT uArgErr;
  119. long lReadyState;
  120. DISPPARAMS dp = {NULL, NULL, 0, 0};
  121. if (SUCCEEDED(hr = m_pMSHTML->Invoke(DISPID_READYSTATE, IID_NULL, LOCALE_SYSTEM_DEFAULT, 
  122. DISPATCH_PROPERTYGET, &dp, &vResult, &excepInfo, &uArgErr)))
  123. {
  124. lReadyState = (READYSTATE)V_I4(&vResult);
  125. switch (lReadyState)
  126. {
  127. case READYSTATE_UNINITIALIZED:
  128. case READYSTATE_LOADING: 
  129. case READYSTATE_LOADED:
  130. case READYSTATE_INTERACTIVE:
  131. break;
  132. case READYSTATE_COMPLETE: 
  133. // IE4 is finished parsing the file
  134. BOOL fRet = PostThreadMessage(GetCurrentThreadId(),
  135. WM_USER_LOAD_COMPLETE,
  136. (WPARAM)0,
  137. (LPARAM)0);
  138. break;
  139. }
  140. VariantClear(&vResult);
  141. }
  142. }
  143. return NOERROR;
  144. }
  145. STDMETHODIMP HTMLParser::Invoke(DISPID dispIdMember,
  146.             REFIID riid,
  147.             LCID lcid,
  148.             WORD wFlags,
  149.             DISPPARAMS __RPC_FAR *pDispParams,
  150.             VARIANT __RPC_FAR *pVarResult,
  151.             EXCEPINFO __RPC_FAR *pExcepInfo,
  152.             UINT __RPC_FAR *puArgErr)
  153. {
  154. if (!pVarResult)
  155. {
  156. return E_POINTER;
  157. }
  158. switch(dispIdMember)
  159. {
  160. case DISPID_AMBIENT_DLCONTROL:
  161. // This tells IE4 that we want to download the page, 
  162. // but we don't want to run scripts, Java applets, or 
  163. // ActiveX controls
  164. V_VT(pVarResult) = VT_I4;
  165. V_I4(pVarResult) =  DLCTL_DOWNLOADONLY | 
  166. DLCTL_NO_SCRIPTS | 
  167. DLCTL_NO_JAVA |
  168. DLCTL_NO_DLACTIVEXCTLS |
  169. DLCTL_NO_RUNACTIVEXCTLS;
  170. break;
  171. default:
  172. return DISP_E_MEMBERNOTFOUND;
  173. }
  174. return NOERROR;
  175. }
  176. BOOL HTMLParser::LoadHTMLFile(LPCSTR pcszFile)
  177. {
  178.     HRESULT        hr;
  179. LPPERSISTFILE  pPF;
  180. IHTMLElementCollection* pColl = NULL;
  181.     MSG msg;
  182. if ( !IsConnected() )
  183. return FALSE;
  184.     // kill any previous links
  185.     if ( m_pAnchorLinks )
  186.     {
  187.         m_pAnchorLinks->Release();
  188.         m_pAnchorLinks = NULL;
  189.     }
  190.     if ( m_pImageLinks )
  191.     {
  192.         m_pImageLinks->Release();
  193.         m_pImageLinks = NULL;
  194.     }
  195. // avoid IE error msg box if the file does not exist
  196.     if ( access(pcszFile, 0x00) != 0x00 )
  197.     {
  198.         return FALSE;
  199.     }
  200.     _bstr_t bstrFile(pcszFile);
  201. // use IPersistFile to load the HTML
  202.     if ( SUCCEEDED(hr = m_pMSHTML->QueryInterface(IID_IPersistFile, (LPVOID*) &pPF)))
  203. {
  204. hr = pPF->Load((LPCWSTR)bstrFile, 0);
  205. pPF->Release();
  206. }
  207.     BOOL bOK = FALSE;
  208.     if (SUCCEEDED(hr))
  209.     {
  210. while (GetMessage(&msg, NULL, 0, 0))
  211. {
  212. // notification from OnChanged
  213. if (WM_USER_LOAD_COMPLETE == msg.message && NULL == msg.hwnd)
  214. {
  215.                 bOK = TRUE;
  216.                 break;
  217. }
  218. else
  219. {
  220. DispatchMessage(&msg);
  221. }
  222. }
  223.     }
  224.     if ( bOK )
  225.     {
  226. try
  227. {
  228. if ( FAILED(m_pMSHTML->get_links(&m_pAnchorLinks)) ||
  229.  FAILED(m_pMSHTML->get_images(&m_pImageLinks)) ) 
  230. {
  231. throw exception();
  232. }
  233. catch ( exception e )
  234. {
  235. if ( m_pAnchorLinks )
  236. {
  237. m_pAnchorLinks->Release();
  238. m_pAnchorLinks = NULL;
  239. }
  240. if ( m_pImageLinks )
  241. {
  242. m_pImageLinks->Release();
  243. m_pImageLinks = NULL;
  244. }
  245. bOK = FALSE;
  246. }
  247.     }
  248. return bOK;
  249. }
  250. /*
  251. Get the number of links present in the current HTML file
  252. */
  253. long HTMLParser::GetLinkCount()
  254. {
  255.     long lCount = 0;
  256.     if ( m_pAnchorLinks )
  257.         m_pAnchorLinks->get_length(&lCount);
  258.     return lCount;
  259. }
  260. /*
  261. Get the number of images present in the current HTML file
  262. */
  263. long HTMLParser::GetImageCount()
  264. {
  265.     long lCount = 0;
  266.     if ( m_pImageLinks )
  267.         m_pImageLinks->get_length(&lCount);
  268.     return lCount;
  269. }
  270. /*
  271. Get the URL associated with a given link
  272. */
  273. BOOL HTMLParser::GetLinkURL(long lIndex, string &rstrURL)
  274. {
  275. if ( IsConnected() && m_pAnchorLinks )
  276.     return GetURLFromCollection(m_pAnchorLinks, IID_IHTMLAnchorElement, lIndex, rstrURL);
  277. else
  278. return FALSE;
  279. }
  280. /*
  281. Get the URL associated with a given image
  282. */
  283. BOOL HTMLParser::GetImageURL(long lIndex, string &rstrURL)
  284. {
  285. if ( IsConnected() && m_pImageLinks )
  286.     return GetURLFromCollection(m_pImageLinks, IID_IHTMLImgElement, lIndex, rstrURL);
  287. else
  288. return FALSE;
  289. }
  290. /*
  291. Get the URL associated with an element in a collection.  The element must
  292. be an image or an anchor.
  293. */
  294. BOOL HTMLParser::GetURLFromCollection(IHTMLElementCollection *pCollection, REFIID rIID, long lIndex, string &rstrURL)
  295. {
  296. VARIANT     varIndex;
  297. VARIANT     var2;
  298.     HRESULT     hr;
  299. IDispatch*  pDisp = NULL; 
  300.     BOOL        bFound = FALSE;
  301.     varIndex.vt = VT_UINT;
  302. varIndex.lVal = lIndex;
  303. VariantInit( &var2 );
  304. hr = pCollection->raw_item( varIndex, var2, &pDisp );
  305. if ( SUCCEEDED(hr) && pDisp)
  306. {
  307. IHTMLImgElement* pImgElem = NULL;
  308. IHTMLAnchorElement* pAnchorElem = NULL;
  309.         BSTR bstr = NULL;
  310.         if ( rIID == IID_IHTMLImgElement &&             
  311.      SUCCEEDED(pDisp->QueryInterface(rIID, (void **)&pImgElem)) )
  312. {
  313. pImgElem->get_href(&bstr);
  314.             pImgElem->Release();
  315.             bFound = (bstr != NULL);
  316. }
  317.         else if ( rIID == IID_IHTMLAnchorElement &&             
  318.           SUCCEEDED(pDisp->QueryInterface(rIID, (void **)&pAnchorElem)) )
  319.         {
  320. pAnchorElem->get_href(&bstr);
  321.             pAnchorElem->Release();
  322.             bFound = (bstr != NULL);
  323. }
  324. pDisp->Release();
  325.         if ( bFound && bstr )
  326.         {
  327. // _bstr_t wrapper will delete since fCopy is FALSE
  328.             _bstr_t bstrHREF(bstr, FALSE);
  329.             rstrURL = (LPCSTR)bstrHREF; 
  330.         }
  331.         
  332. }
  333.     return bFound;
  334. }