http://www.codeproject.com/Articles/4411/IEHelper-Internet-Explorer-Helper-Class

IEHelper - Internet Explorer Helper Class

By Mustafa Demirhan, 21 Jun 2004
   4.78 (40 votes)

1

2

3

4

5
4.78/5 - 40 votes
3 removed
μ 4.43, σa 1.86 [?]
 
 
 

Introduction

The purpose of this article is to show how to use IWebBrowser2, IHTMLDocument2 and IHTMLElement objects.

Creating a new web browser object

Let's start with a very simple example: How to create a new Internet Explorer window. The code below shows how to do this:

Collapse | Copy Code
HRESULT hr;
IWebBrowser2* pWebBrowser = NULL;
hr = CoCreateInstance (CLSID_InternetExplorer, NULL,
CLSCTX_SERVER, IID_IWebBrowser2, (LPVOID*)&pWebBrowser); if (SUCCEEDED (hr) && (pWebBrowser != NULL))
{
m_pWebBrowser->put_Visible (VARIANT_TRUE);
// OK, we created a new IE Window and made it visible
// You can use pWebBrowser object to do whatever you want to do!
}
else
{
// Failed to create a new IE Window.
// Check out pWebBrowser object and
// if it is not NULL (should never happen), the release it!
if (pWebBrowser)
pWebBrowser->Release ();
}

Connecting to a running instance of IE

Creating a new IE window is a fairly easy task. But what if you want to use an existing Internet Explorer window, instead of creating a new IE window? Well, in this case, the task is more complicated. The function below finds an Internet Explorer window. sTitleToSearch is the title of the web page to be searched for. Usage of wildcard characters is allowed. If you want to find any IE window, then just enter "*" as the title.

Collapse | Copy Code
bool CMyInternetExplorer::FindUsingTitle
(const CString & sTitleToSearch)
{
if (m_pWebBrowser != NULL)
{
m_pWebBrowser->Release ();
m_pWebBrowser = NULL;
} HRESULT hr;
SHDocVw::IShellWindowsPtr spSHWinds;
hr = spSHWinds.CreateInstance (__uuidof(SHDocVw::ShellWindows)); if (FAILED (hr))
return false; ASSERT (spSHWinds != NULL); long nCount = spSHWinds->GetCount (); IDispatchPtr spDisp; for (long i = 0; i < nCount; i++)
{
_variant_t va (i, VT_I4);
spDisp = spSHWinds->Item (va); IWebBrowser2 * pWebBrowser = NULL;
hr = spDisp.QueryInterface (IID_IWebBrowser2, & pWebBrowser); if (pWebBrowser != NULL)
{
HRESULT hr;
IDispatch* pHtmlDocDispatch = NULL;
IHTMLDocument2 * pHtmlDoc = NULL; // Retrieve the document object.
hr = pWebBrowser->get_Document (&pHtmlDocDispatch); if (SUCCEEDED (hr) && (pHtmlDocDispatch != NULL))
{
// Query for IPersistStreamInit.
hr = pHtmlDocDispatch->QueryInterface
(IID_IHTMLDocument2, (void**)&pHtmlDoc);
if (SUCCEEDED (hr) && (pHtmlDoc != NULL))
{
CString sTitle; HWND hWnd = NULL;
pWebBrowser->get_HWND ((long*)(&hWnd));
if (::IsWindow (hWnd))
{
int nLen = ::GetWindowTextLength (hWnd);
::GetWindowText (hWnd,
sTitle.GetBufferSetLength (nLen),
nLen + 1);
sTitle.ReleaseBuffer ();
} // If I cannot get the window title
// (should never happen though)
// So, lets just use the title of the document
if (sTitle.IsEmpty ())
{
BSTR bstrTitle;
hr = pHtmlDoc->get_title (&bstrTitle);
if (!FAILED (hr))
{
sTitle = bstrTitle;
SysFreeString (bstrTitle);
}
} if (StringHelper::WildcardCompareNoCase
(sTitleToSearch, sTitle))
{
m_pWebBrowser = pWebBrowser;
pHtmlDoc->Release ();
pHtmlDocDispatch->Release ();
// Exit the method safely!
return true;
}
pHtmlDoc->Release();
}
pHtmlDocDispatch->Release ();
}
pWebBrowser->Release ();
}
} return false;
}

This approach is described in MSDN in more detail. Click here to get more information.

This approach uses SHDocVw.ShellWindows collection to enumerate all the instances of shell windows. The ShellWindows object represents a collection of the open windows that belong to the shell. In fact, this collection contains references to Internet Explorer as well as other windows belonging to the shell, such as the Windows Explorer. To differentiate between Internet Explorer and other shell windows, we just try to get the HTML document of the shell window. If we get the document successfully, then this instance of ShellWindow is in fact an Internet Explorer window.

Navigate to a web page

Now, after we get the web browser object and store it in the variable m_pWebBrowser, it is very easy to navigate to a web page.

Collapse | Copy Code
void CMyInternetExplorer::Navigate(LPCTSTR lpszURL, DWORD dwFlags /* = 0 */,
LPCTSTR lpszTargetFrameName /* = NULL */ ,
LPCTSTR lpszHeaders /* = NULL */, LPVOID lpvPostData /* = NULL */,
DWORD dwPostDataLen /* = 0 */)
{
CString strURL (lpszURL);
BSTR bstrURL = strURL.AllocSysString (); COleSafeArray vPostData;
if (lpvPostData != NULL)
{
if (dwPostDataLen == 0)
dwPostDataLen = lstrlen ((LPCTSTR) lpvPostData); vPostData.CreateOneDim (VT_UI1, dwPostDataLen, lpvPostData);
} m_pWebBrowser->Navigate (bstrURL,
COleVariant ((long) dwFlags, VT_I4),
COleVariant (lpszTargetFrameName, VT_BSTR),
vPostData, COleVariant (lpszHeaders, VT_BSTR)); SysFreeString (bstrURL);
}

Wait until the web page is loaded

After starting to load a web page using the function above, to wait until the web page to be completely loaded, we can use the READYSTATE property of IWebBrowser2 object.

Collapse | Copy Code
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;
}

This function waits until the web page is completely loaded or a timeout occurs. To wait indefinitely, set the nTimeout parameter to 0.

Find an anchor on a web page

The following function searches for the specified anchor in a web page. The anchor can be specified either by the name, outer text, tool tip or the URL. The anchor element has the following syntax:

Collapse | Copy Code
<a href = "anhor_URL" name ="anchor_name"
title = "anchor_tooltip">Outer Text</a>

If bClick parameter is set to true, then if the anchor is found, it will also be clicked on.

Collapse | Copy Code
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;
}

The idea here is very simple. We first enumerate all IHTMLElement objects using get_all function of IHTMLDocument2. Then we check all of the elements to see whether it is an anchor object (IHTMLAnchorElement) or not, by checking its tag name. If it is an "a" or an "A", then it is an anchor object. Then I try to get the IHTMLAnchor object by using the QueryInterface function. The reason that I check the name instead of just using QueryInterface function is performance related. I guess it is much faster to check a tag's name than trying to get IHTMLAnchorElement by using QueryInterface function.

Fill a form on a web page

The idea here is similar to the one above. Instead of finding the anchor element, I try to find all the input elements and then do the same operations. The syntax for an input element is a follows:

Collapse | Copy Code
<input type="input_type" value="input_value" name="input_name">
Collapse | Copy Code
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;
}

Some points that you should keep in mind

  • The attached source code includes a few more functions to fill the forms on web pages.
  • The source code above does not search inside Frame objects. However, this should not be a hard task. The frame objects should be enumerated and then the IHTMLDocument2 of each frame should be checked recursively. May be I will implement this in the next update.
  • In order to use IHTMLInputElement object, you need at least Internet Explorer 5.0
  • I am not an expert Internet Explorer programmer. Lately, I needed to automate Internet Explorer and then wrote these functions. I wrote most of them on my own, and they may have some bug fixes in it.
  • Please do not ask me why I used MFC, not ATL. The reason is that I don't know ATL However, if you guys help me to convert this code into ATL, I would be very glad. I may even start learning ATL

IEHelper - Internet Explorer Helper Class的更多相关文章

  1. 如何使用BHO定制你的Internet Explorer浏览器

    原文出处:Browser Helper Objects: The Browser the Way You Want It一.简介 有时,你可能需要一个定制版本的浏览器.在这种情况下,你可以自由地把一些 ...

  2. 企业IT管理员IE11升级指南【1】—— Internet Explorer 11增强保护模式 (EPM) 介绍

    企业IT管理员IE11升级指南 系列: [1]—— Internet Explorer 11增强保护模式 (EPM) 介绍 [2]—— Internet Explorer 11 对Adobe Flas ...

  3. 企业IT管理员IE11升级指南【2】—— Internet Explorer 11 对Adobe Flash的支持

    企业IT管理员IE11升级指南 系列: [1]—— Internet Explorer 11增强保护模式 (EPM) 介绍 [2]—— Internet Explorer 11 对Adobe Flas ...

  4. 企业IT管理员IE11升级指南【6】—— Internet Explorer 11面向IT专业人员的常见问题

    企业IT管理员IE11升级指南 系列: [1]—— Internet Explorer 11增强保护模式 (EPM) 介绍 [2]—— Internet Explorer 11 对Adobe Flas ...

  5. IE中无法执行JS脚本 解决WINDOWS SERVER 2008弹出INTERNET EXPLORER增强安全配置正在阻止来自下列网站的内容

    在默认状态下,使用Windows Server 2008系统自带的IE浏览器访问网页内容时,我们时常发现“Internet Explorer增强安全配置正在阻止来自下列网站的内容”的提示导致不能打开网 ...

  6. Fix Internet Explorer Crashes with SharePoint 2013 Online Presence Indicators

    IE中,只要是鼠标浮动到人名字上面的状态的时候,这个状态是与Lync相连接的,IE就会出现停止工作. 以下是解决方法. Until the other day when I figured this ...

  7. Selenium2学习-037-WebUI自动化实战实例-IE浏览器显示比例问题:org.openqa.selenium.remote.SessionNotFoundException: Unexpected error launching Internet Explorer. Browser zoom level was set to 94%. It should be set to 100%

    好久没有写博文了,今天在给部门新人演示 Selenium WebDriver 启动其支持的各种浏览器时,启动 IE 时总是无法打开对应的百度网址,页面如下所示:

  8. Internet Explorer 无法启用 JavaScript 怎么办?

    在 Internet Expllorer 8/9 中,有些同学在浏览网页时,收到提示:“需要启用 JavaScript …”,并且会发现网页上某些功能不能用了,比如点击网页里的按钮没反应等等. 怎么启 ...

  9. How to Enable 64-bit Processes for Enhanced Protected Mode in Internet Explorer 11 (IE11)

       Information Enhanced Protected Mode (EPM) adds additional security to Protected Mode and includes ...

随机推荐

  1. tomcat根据繁忙线程数对keepalive进行动态调整

    众所周知,Keep-Alive功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接.我们经常所用的tomcat服务器就支持HTTP Ke ...

  2. ZOJ 2625 Rearrange Them(DP)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1625 题目大意:将n个数重新排列,使得每个数的前一个数都不能和之前的 ...

  3. How to: Change icon in Inno Setup

    1. Change the installer executable icon or the icon showed in Start Menu folder Using SetupIconFile ...

  4. RX学习笔记:Bootstrap

    Bootstrap https://getbootstrap.com 2016-07-01 在学习FreeCodeCamp课程中了解到Bootstrap,并于课程第一个实战题卡在响应式部分,于是先对B ...

  5. tomcat错误信息解决方案 严重:StandardServer.await:

    看到这个报错我的第一反应就是端口被占用,用netstat -ant命令查看发现8080端口没有被占用,也可以看到 tomcat的进程已经存在,但是不能对外提供服务. 1.独立运行的tomcat.exe ...

  6. UniqueID,页面子控件唯一标示

    aspx: <form id="form1" runat="server">     <asp :Repeater ID="MyDa ...

  7. Node.js学习心得

    最近花了三四周的时间学习了Node.js ,感觉Node.js在学习过程中和我大学所学的专业方向.NET在学习方法上有好多的相似之处,下面就将我学习的心得体会以及参考的资料总结归纳如下,希望对于刚入门 ...

  8. PHP输出

    样例: $a = true;$b = false;$c = 086;$d = 0x86;echo "$a hase value: ".$a; echo "<br/& ...

  9. Android开发第2篇 - Git插件安装

    一.Eclipse上安装GIT插件EGit Eclipse的版本eclipse-java-helios-SR2-win32.zip(在Eclipse3.3版本找不到对应的 EGit插件,无法安装) E ...

  10. bottle + vue.js 打造你的单页应用

    看到各种单页应用之后,觉得单页应用简直酷毙了,作为一个技术宅,在假期的 时候恶补了一下vue ,觉得还不错,不过想想前端的东西毕竟还是太广博了.我也不知道怎么写反正应用起来有点别扭,就是资料太少了,成 ...