Microsoft Internet Explorer 4.x has become a leading Web browser. I was surprised to find out that most of its functionality is contained in one big ActiveX control, Shdocvw.dll. When you run Internet Explorer, you launch a small shell program that loads this Web Browser control in its main window.
You can find complete documentation for the Web Browser control's properties, methods, and events in the Internet SDK, downloadable from http://www.microsoft.com. This documentation is in HTML form, of course.
Because of this modular architecture, you can write your own custom browser program with very little effort. EX08B creates a two-window browser that displays a search engine page side-by-side with the target page, as shown here.
This view window contains two Web Browser controls that are sized to occupy the entire client area. When the user clicks an item in the search (right-hand) control, the program intercepts the command and routes it to the target (left-hand) control.
Here are the steps for building the example:
Repeat for m_target. ClassWizard adds an #include statement for the webbrowser.h file.
private: static const char s_engineAltavista[];Then add the following definition in ex08bView.cpp, outside any function:
const char CEx08bView::s_engineAltavista[] = "http://altavista.digital.com/";
int CEx08bView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; DWORD dwStyle = WS_VISIBLE | WS_CHILD; if (m_search.Create(NULL, dwStyle, CRect(0, 0, 100, 100), this, ID_BROWSER_SEARCH) == 0) { AfxMessageBox("Unable to create search control!\n"); return -1; } m_search.Navigate(s_engineAltavista, NULL, NULL, NULL, NULL); if (m_target.Create(NULL, dwStyle, CRect(0, 0, 100, 100), this, ID_BROWSER_TARGET) == 0) { AfxMessageBox("Unable to create target control!\n"); return -1; } m_target.GoHome(); // as defined in Internet Explorer 4 options return 0; } void CEx08bView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); CRect rectClient; GetClientRect(rectClient); CRect rectBrowse(rectClient); rectBrowse.right = rectClient.right / 2; CRect rectSearch(rectClient); rectSearch.left = rectClient.right / 2; m_target.SetWidth(rectBrowse.right - rectBrowse.left); m_target.SetHeight(rectBrowse.bottom - rectBrowse.top); m_target.UpdateWindow(); m_search.SetLeft(rectSearch.left); m_search.SetWidth(rectSearch.right - rectSearch.left); m_search.SetHeight(rectSearch.bottom - rectSearch.top); m_search.UpdateWindow(); }
The OnCreate function creates two browser windows inside the view window. The right-hand browser displays the top-level AltaVista page, and the left-hand browser displays the "home" page as defined through the Internet icon in the Control Panel. The OnSize function, called whenever the view window changes size, ensures that the browser windows completely cover the view window. The CWebBrowser member functions SetWidth and SetHeight set the browser's Width and Height properties.
protected: afx_msg void OnBeforeNavigateExplorer1(LPCTSTR URL, long Flags, LPCTSTR TargetFrameName, VARIANT FAR* PostData, LPCTSTR Headers, BOOL FAR* Cancel); afx_msg void OnTitleChangeExplorer2(LPCTSTR Text); DECLARE_EVENTSINK_MAP()
Then add the following code in ex08bView.cpp:
BEGIN_EVENTSINK_MAP(CEx08bView, CView) ON_EVENT(CEx08bView, ID_BROWSER_SEARCH, 100, OnBeforeNavigateExplorer1, VTS_BSTR VTS_I4 VTS_BSTR VTS_PVARIANT VTS_BSTR VTS_PBOOL) ON_EVENT(CEx08bView, ID_BROWSER_TARGET, 113, OnTitleChangeExplorer2, VTS_BSTR) END_EVENTSINK_MAP()
void CEx08bView::OnBeforeNavigateExplorer1(LPCTSTR URL, long Flags, LPCTSTR TargetFrameName, VARIANT FAR* PostData, LPCTSTR Headers, BOOL FAR* Cancel) { TRACE("CEx08bView::OnBeforeNavigateExplorer1 -- URL = %s\n", URL); if (!strnicmp(URL, s_engineAltavista, strlen(s_engineAltavista))) { return; } m_target.Navigate(URL, NULL, NULL, PostData, NULL); *Cancel = TRUE; } void CEx08bView::OnTitleChangeExplorer2(LPCTSTR Text) { // Careful! Event could fire before we're ready. CWnd* pWnd = AfxGetApp()->m_pMainWnd; if (pWnd != NULL) { if (::IsWindow(pWnd->m_hWnd)) { pWnd->SetWindowText(Text); } } }
The OnBeforeNavigateExplorer1 handler is called when the user clicks on a link in the search page. The function compares the clicked URL (in the URL string parameter) with the search engine URL. If they match, the navigation proceeds in the search window; otherwise, the navigation is cancelled and the Navigate method is called for the target window. The OnTitleChangeExplorer2 handler updates the EX08B window title to match the title on the target page.