{"id":397,"date":"2010-04-05T11:37:21","date_gmt":"2010-04-05T10:37:21","guid":{"rendered":"http:\/\/www.nuonsoft.com\/blog\/?p=397"},"modified":"2010-04-05T11:37:21","modified_gmt":"2010-04-05T10:37:21","slug":"how-to-navigate-to-an-anchor-in-the-microsoft-webbrowser-control-when-rendering-html-from-memory","status":"publish","type":"post","link":"https:\/\/www.nuonsoft.com\/blog\/2010\/04\/05\/how-to-navigate-to-an-anchor-in-the-microsoft-webbrowser-control-when-rendering-html-from-memory\/","title":{"rendered":"How To Navigate to an Anchor in the Microsoft WebBrowser Control when Rendering HTML from Memory"},"content":{"rendered":"<p>In my previous blog entry titled &#8220;<a href=\"http:\/\/www.nuonsoft.com\/blog\/2010\/03\/24\/how-to-use-the-microsoft-webbrowser-control-to-render-html-from-memory\/\">How To Use the Microsoft WebBrowser Control to Render HTML from Memory<\/a>&#8221; I described a method how you could use the Microsoft WebBrowser Control to display HTML from memory. One commenter said that it was not possible to navigate to an anchor in the body onload handler. I did some research and it seems all navigation within the rendered page is not working. For example, the following piece of HTML code will not work correctly:<\/p>\n<blockquote>\n<pre>&lt;a href=\"#n25\"&gt;Jump to anchor n25&lt;\/a&gt;\r\n&lt;a name=\"n25\"&gt;25&lt;\/a&gt;<\/pre>\n<\/blockquote>\n<p>It took me a while to find a workaround, so that&#8217;s why I&#8217;m posting it now for other people to use. Basically, we cannot use the standard navigation techniques. I tried several possible workaround and the only one that I got working properly is by manually scrolling the window until the requested anchor is visible. It sounds complicated, but it really works pretty nicely. I wrote this little wrapper function to do all the hard work.<\/p>\n<blockquote>\n<pre>void CMyDlg::ScrollToAnchor(const wchar_t* anchor)\r\n{\r\n\u00a0\u00a0\u00a0 IDispatch* pHtmlDoc = m_explorer.get_Document();\r\n\u00a0\u00a0\u00a0 if (!pHtmlDoc)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return;\r\n\u00a0\u00a0\u00a0 CComPtr&lt;IHTMLDocument2&gt; doc2;\r\n\u00a0\u00a0\u00a0 doc2.Attach((IHTMLDocument2*)pHtmlDoc);\r\n\u00a0\u00a0\u00a0 if (doc2)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 CComPtr&lt;IHTMLElementCollection&gt; anchors;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 HRESULT hr = doc2-&gt;get_anchors(&amp;anchors);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (SUCCEEDED(hr) &amp;&amp; anchors)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 _variant_t index = 0;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 _variant_t str = anchor;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 IDispatch *pdisp;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 hr = anchors-&gt;item(str, index, &amp;pdisp);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (SUCCEEDED(hr) &amp;&amp; pdisp)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 CComPtr&lt;IHTMLElement&gt; el;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 hr = pdisp-&gt;QueryInterface(IID_IHTMLElement, (void**)&amp;el);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (SUCCEEDED(hr) &amp;&amp; el)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 long yTotal = 0;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 while (1)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 long y;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 el-&gt;get_offsetTop(&amp;y);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 yTotal += y;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 CComPtr&lt;IHTMLElement&gt; el2;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 hr = el-&gt;get_offsetParent(&amp;el2);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (SUCCEEDED(hr) &amp;&amp; el2)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 el = el2;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 break;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 CComPtr&lt;IHTMLWindow2&gt; wnd;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 hr = doc2-&gt;get_parentWindow(&amp;wnd);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (SUCCEEDED(hr) &amp;&amp; wnd)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 wnd-&gt;scrollTo(0, yTotal);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 }\r\n}<\/pre>\n<\/blockquote>\n<p>What it does is it gets a pointer to the document. Then gets a list of all the anchors in the document and get the anchor with the given name out of that list. Once we have the target element, we calculate the offset from the top of the document. This is done in a while loop, because the target anchor could be inside another element like a div or a table. After calculating the offset, we get a pointer to the HTML window and call the scrollTo function to make it scroll to the anchor position.<\/p>\n<p>Now the only thing you need to do is to render your HTML using the method in my <a href=\"http:\/\/www.nuonsoft.com\/blog\/2010\/03\/24\/how-to-use-the-microsoft-webbrowser-control-to-render-html-from-memory\/\">previous blog entry<\/a> and then call this new ScrollToAnchor function with the name of the anchor to which you want to scroll.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my previous blog entry titled &#8220;How To Use the Microsoft WebBrowser Control to Render HTML from Memory&#8221; I described a method how you could use the Microsoft WebBrowser Control to display HTML from memory. One commenter said that it was not possible to navigate to an anchor in the body onload handler. I did [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,34,7,16,17],"tags":[74,65,64,75,63,62,67],"class_list":["post-397","post","type-post","status-publish","format-standard","hentry","category-c","category-internet-explorer","category-mfc","category-microsoft","category-software-development","tag-anchor","tag-cexplorer","tag-html","tag-scrolling","tag-web-browser","tag-webbrowser","tag-writehtml"],"_links":{"self":[{"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/posts\/397","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/comments?post=397"}],"version-history":[{"count":2,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/posts\/397\/revisions"}],"predecessor-version":[{"id":399,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/posts\/397\/revisions\/399"}],"wp:attachment":[{"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/media?parent=397"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/categories?post=397"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/tags?post=397"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}