Internet Explorer 9 Launched
Get your copy here.
You can also browse the above site to learn all the new features of IE9, especially its focus on speed and standard compliancy 🙂
Get your copy here.
You can also browse the above site to learn all the new features of IE9, especially its focus on speed and standard compliancy 🙂
Microsoft has released the release candidate of Internet Explorer 9.
Get it here.
Today Microsoft released a public beta of Internet Explorer 9. The new version is much better standard compliant and support such standards as HTML5, CSS3 and SVG2. It scores a nice 95/100 on the Acid3 test. I just installed it myself and I’m impressed with how much faster it works compared to IE8. You can read a full review here.
Download it here.
Now that you know “How To Use the Microsoft WebBrowser Control to Render HTML from Memory” and “How To Navigate to an Anchor in the Microsoft WebBrowser Control when Rendering HTML from Memory“, it’s time to learn how to handle custom URL protocols to tailor the navigation inside the WebBrowser Control to fit your application. The following demonstrates a custom URL protocol called “app”:
<a href="app://some.target">Test</a>
When you would put this link in a normal Internet Explorer window, clicking the link will generate an error because IE does not know how to handle the APP protocol. The name APP is chosen arbitrarily. You can use whatever you want. Handling these custom protocols in your C++ application is actually pretty simple and it doesn’t even involve any real COM coding like in the previous articles. The first thing you need to do is to add a handler for the BeforeNavigate2 handler. Open the resource editor and open your dialog with the WebBrowser control. Right click the WebBrowser control and select “Add Event Handler…”. Select “BeforeNavigate2” as message type, select the appropriate class and click “Add and Edit”. This handler will be called right before the WebBrowser control will navigate to a new page. To handle the custom protocol, implement the handler as follows:
void CMyDlg::BeforeNavigate2Explorer(LPDISPATCH pDisp, VARIANT* URL, VARIANT* Flags, VARIANT* TargetFrameName, VARIANT* PostData, VARIANT* Headers, BOOL* Cancel) { const wchar_t* cpszProtocolName = L"app"; const wchar_t* cpszProtocolSeparator = L"://"; // We only handle VT_BSTR. if (URL->vt != VT_BSTR) return; // Check the protocol of the URL CString str = URL->bstrVal; int iPos = str.Find(cpszProtocolSeparator); if (iPos == -1) // Unable to figure out protocol return; // Extract protocol and check if it's our APP protocol CString strProtocol = str.Mid(0, iPos); if (strProtocol.CompareNoCase(cpszProtocolName)) return; // not our APP protocol // It's our APP protocol, so start processing it. // Start by preventing Internet Explorer from handling the protocol. *Cancel = TRUE; // Extract target URL CString strTarget = str.Mid(iPos+wcslen(cpszProtocolSeparator)); strTarget.TrimRight(L"/"); // Now we are ready to process our protocol. // For this demo, I just render a new HTML page with the name // of the URL target without the protocol part of the string. CString strHTML; strHTML.Format(L"My APP protocol processing: \"%s\"", strTarget); WriteHTML(strHTML); }
The flow is pretty straightforward. The URL protocol is extracted; if it’s not our protocol, we let Internet Explorer handle the URL for us. If it is our custom “APP” protocol, we first set Cancel to TRUE which will prevent Internet Explorer from handling this URL protocol. Once that is done, we are completely free to implement the handling of the “APP” protocol however we want. As demonstration I just write a new HTML document from memory which will just mention that we are processing an “APP” protocol URL and that will also display the target part of the URL.
You can quickly test the code with the following piece of HTML rendered from memory:
WriteHTML(L"<html><body>" L"<p><a href=\"app://FirstAppProtocolTestLink\">test 1</a></p>" L"<p><a href=\"APP://SecondAppProtocolTestLink.Withdots\">test 2</a></p>" L"</body></html>");
Run the application, click on the “test 1” or “test 2” link and see what happens.
That’s it for handling custom URL protocols in C++ 🙂
Microsoft has a WebBrowser control that is actually an Internet Explorer control that you can use to display HTML in your own applications. More information about this WebBrowser control can be found on MSDN. By using this control it’s very easy to display online or offline webpages. However, it’s not immediately obvious how to make it display HTML that you might have in a memory buffer. Of course, one solution is to write the HTML to a temporary file and then load that file using the WebBrowser control, but obviously there is a better way for doing this which I will explain below.
The first thing you have to do is to add the WebBrowser control to your dialog. So, in Visual Studio, open the resource editor and then open the dialog onto which you want to put the WebBrowser control. Once the dialog is opened in the resource editor, right click on an empty space on the dialog and select “Insert ActiveX Control…”. This will open a new window in which you can select “Microsoft Web Browser” and then click OK. Visual Studio will automatically create a wrapper class for this ActiveX control which will probably be called explorer.h and explorer.cpp while the wrapper class will most likely be called CExplorer.
Now, right click the WebBrowser control on your dialog and select “Add Variable”. Make a variable with category set to “Control” and with the variable type set to the wrapper class “CExplorer” and hit OK.
Now we can start writing code. The first thing required is to load up some basic document; I use about:blank. Do this in your OnInitDialog handler as follows.
COleVariant loc(L"about:blank"); m_explorer.Navigate2(loc, NULL, NULL, NULL, NULL);
The above is very important. If you don’t load an initial document, the WebBrowser control will not render any HTML that you try to push to it. This also means that before you can start writing HTML from memory in the WebBrowser control, you have to wait until the initial document has been fully loaded. This can be done with the “DocumentComplete” event. In the dialog editor, right the WebBrowser control and click on “Add Event Handler…”. Select “DocumentComplete” as message type, select the appropriate class and click “Add and Edit”. You can use that handler to change a boolean variable in your code to mark whether the document has been fully loaded. When it is fully loaded you can start writing HTML from memory to it.
Once that is finished, you can add the following helper function:
#include <MsHTML.h> void CMyDlg::WriteHTML(const wchar_t* html) { IDispatch* pHtmlDoc = m_explorer.get_Document(); if (!pHtmlDoc) return; CComPtr<IHTMLDocument2> doc2; doc2.Attach((IHTMLDocument2*)pHtmlDoc); if (!doc2) return; // Creates a new one-dimensional array SAFEARRAY* psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1); if (!psaStrings) return; BSTR bstr = SysAllocString(html); if (bstr) { VARIANT* param; HRESULT hr = SafeArrayAccessData(psaStrings, (LPVOID*)¶m); if (SUCCEEDED(hr)) { param->vt = VT_BSTR; param->bstrVal = bstr; hr = SafeArrayUnaccessData(psaStrings); if (SUCCEEDED(hr)) { doc2->write(psaStrings); doc2->close(); } } } // SafeArrayDestroy calls SysFreeString for each BSTR! if (psaStrings) SafeArrayDestroy(psaStrings); }
With the above function, it’s very easy to dynamically create and display HTML from memory. For example:
WriteHTML(L"<html><body><h1>My Header</h1><p>Some text below the header</p></body></html>");
Note that the above code is expecting a Unicode build. If you don’t use Unicode, you need to change the wchar_t types and you need to change the way how you allocate the BSTR variable.
That’s it. Pretty easy if you know how to do it, but it took me some time to figure it out.
[ Update: Fixed some typos and added mshtml.h reference. ]
[ Update 2: Added a call to “doc2->close();” after “doc2->write()” and added code to check the result of the doc2.Attach() call. ]
It seems Microsoft will not release a Windows 7 E for the European Union after all. Windows 7 E was planned for the EU to be a Windows 7 version without Internet Explorer. Now, Microsoft will implement a ballot screen that will be shown the first time a user starts Internet Explorer. That ballot screen gives the user the option to select a different browser like Firefox, Safari, Chrome, Opera and so on.
After installation of Internet Explorer 8, some wizard in Visual Studio 2005 and 2008 might give a script error. The following wizards might be affected: