IE浏览器作为微软Windows系统捆绑销售的一个浏览工具,用来浏览千姿百态的网页,目前它已经占据了浏览器市场的半壁江山,成为Windows用户不可或缺的工具。首先,它的界面设计的很漂亮,如扁平按纽(按钮上的图像为灰色,当鼠标放在按钮上时,按钮突起,这种状态称为手柄,并且其上的图像变得鲜艳醒目)、按钮上的文字说明以及按钮边上的小黑三角形状的下拉箭头(单击时显示下拉菜单)、工具条上的地址输入栏等,都体现了Windows2000的风格;其次,它的收藏栏可以收藏用户喜爱的网络地址,这一切都为IE的流行打下了坚实的基础。说了那么多,也许读者朋友们感觉到IE实现起来一定非常困难,其实IE也是个"纸老虎",实现它的难点主要是在界面效果和显示收藏夹上,笔者在本实例中有针对性的叙述了IE界面、收藏网页的显示、网页的浏览等功能的实现,仔细看过这篇文章后,相信读者朋友们一定可以打造出一个属于自己的浏览器。本实例中的程序代码编译运行后的界面效果如图一所示:
图二、包含按钮图标的位图 |
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { CImageList img; //图像列表对象; CString str; //字符串对象; if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndReBar.Create(this)) //创建CReBar对象; { TRACE0("Failed to create rebar\n"); return -1; } if (!m_wndToolBar.CreateEx(this)) //使用CreateEx()函数创建工具条对象; { TRACE0("Failed to create toolbar\n"); return -1; } //设置工具栏中的按钮最大最小尺寸; m_wndToolBar.GetToolBarCtrl().SetButtonWidth(50, 150); //设置工具栏上的按钮支持下拉箭头风格; m_wndToolBar.GetToolBarCtrl().SetExtendedStyle(TBSTYLE_EX_DRAWDDARROWS); //向图像列表装载热点图像资源,IDB_HOTTOOLBAR为热点图像资源ID img.Create(IDB_HOTTOOLBAR, 22, 0, RGB(255, 0, 255)); m_wndToolBar.GetToolBarCtrl().SetHotImageList(&img); img.Detach(); //图象列表装载正常状态的图像资源,IDB_COLDTOOLBAR为图像资源ID img.Create(IDB_COLDTOOLBAR, 22, 0, RGB(255, 0, 255)); m_wndToolBar.GetToolBarCtrl().SetImageList(&img); img.Detach(); //设置工具条为扁平风格 m_wndToolBar.ModifyStyle(0, TBSTYLE_FLAT | TBSTYLE_TRANSPARENT); //设置工具条上的按钮个数为9个; m_wndToolBar.SetButtons(NULL, 9); // 装载字符串资源,设置按钮上的文本和按钮的标识号; m_wndToolBar.SetButtonInfo(0, ID_GO_BACK, TBSTYLE_BUTTON, 0); str.LoadString(IDS_BACK); m_wndToolBar.SetButtonText(0, str); m_wndToolBar.SetButtonInfo(1, ID_GO_FORWARD, TBSTYLE_BUTTON, 1); str.LoadString(IDS_FORWARD); m_wndToolBar.SetButtonText(1, str); m_wndToolBar.SetButtonInfo(2, ID_VIEW_STOP, TBSTYLE_BUTTON, 2); str.LoadString(IDS_STOP); m_wndToolBar.SetButtonText(2, str); m_wndToolBar.SetButtonInfo(3, ID_VIEW_REFRESH, TBSTYLE_BUTTON, 3); str.LoadString(IDS_REFRESH); m_wndToolBar.SetButtonText(3, str); m_wndToolBar.SetButtonInfo(4, ID_GO_START_PAGE, TBSTYLE_BUTTON, 4); str.LoadString(IDS_HOME); m_wndToolBar.SetButtonText(4, str); m_wndToolBar.SetButtonInfo(5, ID_GO_SEARCH_THE_WEB, TBSTYLE_BUTTON, 5); str.LoadString(IDS_SEARCH); m_wndToolBar.SetButtonText(5, str); m_wndToolBar.SetButtonInfo(6, ID_FAVORITES_DROPDOWN,TBSTYLE_BUTTON | TBSTYLE_DROPDOWN, 6); str.LoadString(IDS_FAVORITES); m_wndToolBar.SetButtonText(6, str); m_wndToolBar.SetButtonInfo(7, ID_FILE_PRINT, TBSTYLE_BUTTON, 7); str.LoadString(IDS_PRINT); m_wndToolBar.SetButtonText(7, str); m_wndToolBar.SetButtonInfo(8, ID_FONT_DROPDOWN, TBSTYLE_BUTTON | TBSTYLE_DROPDOWN, 8); str.LoadString(IDS_FONT); m_wndToolBar.SetButtonText(8, str); // 设置工具栏上的按钮尺寸和显示在按钮上的图标尺寸; CRect rectToolBar; m_wndToolBar.GetItemRect(0, &rectToolBar); m_wndToolBar.SetSizes(rectToolBar.Size(), CSize(30,20)); //创建组合框,用来作为地址栏; if (!m_wndAddress.Create(CBS_DROPDOWN | WS_CHILD, CRect(0, 0, 200, 120), this, AFX_IDW_TOOLBAR + 1)) { TRACE0("Failed to create combobox\n"); return -1; } //创建动画控件对象,并打开AVI资源IDR_MFCAVI; m_wndAnimate.Create(WS_CHILD | WS_VISIBLE, CRect(0, 0, 10, 10), this, AFX_IDW_TOOLBAR + 2); m_wndAnimate.Open(IDR_MFCAVI); //将工具条、地址栏、动画控件等添加到CReBar对象中; m_wndReBar.AddBar(&m_wndToolBar); m_wndReBar.AddBar(&m_wndAnimate, NULL, NULL, RBBS_FIXEDSIZE | RBBS_FIXEDBMP); str.LoadString(IDS_ADDRESS); m_wndReBar.AddBar(&m_wndAddress, str, NULL, RBBS_FIXEDBMP | RBBS_BREAK); //再次设置工具条风格,使之有工具栏提示功能; m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_FIXED); //设置状态条; if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) { TRACE0("Failed to create status bar\n"); return -1; } …….//实现"Favorites"菜单的部分,该部分在第二部分介绍; return 0; } |
void CMainFrame::OnDropDown(NMHDR* pNotifyStruct, LRESULT* pResult) { NMTOOLBAR* pNMToolBar = (NMTOOLBAR*)pNotifyStruct; CRect rect; // 得到下拉箭头的位置; m_wndToolBar.GetToolBarCtrl().GetRect(pNMToolBar->iItem, &rect); rect.top = rect.bottom; ::ClientToScreen(pNMToolBar->hdr.hwndFrom, &rect.TopLeft()); if(pNMToolBar->iItem == ID_FONT_DROPDOWN) //判断是否为选择字体的下拉箭头; { CMenu menu; CMenu* pPopup; menu.LoadMenu(IDR_FONT_POPUP); pPopup = menu.GetSubMenu(0); pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, rect.left, rect.top + 1, AfxGetMainWnd()); } else if(pNMToolBar->iItem == ID_FAVORITES_DROPDOWN) {//判断是否为显示收藏网页的下拉箭头; CMenu* pPopup; pPopup = GetMenu()->GetSubMenu(3); pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, rect.left, rect.top + 1, AfxGetMainWnd()); } *pResult = TBDDRET_DEFAULT; } |
m_wndAnimate.Create(WS_CHILD | WS_VISIBLE, CRect(0, 0, 10, 10), this, AFX_IDW_TOOLBAR + 2); m_wndAnimate.Open(IDR_MFCAVI); |
void CMainFrame::OnNewAddressEnter() { CString str; //获取地址栏中的字符串; m_wndAddress.GetEditCtrl()->GetWindowText(str); ((CMfcieView*)GetActiveView())->Navigate2(str, 0, NULL);//显示该网页; //将该网址添加到地址栏对应的组合框中; COMBOBOXEXITEM item; item.mask = CBEIF_TEXT; item.iItem = -1; item.pszText = (LPTSTR)(LPCTSTR)str; m_wndAddress.InsertItem(&item); } |
void CMainFrame::OnNewAddress() { CString str; m_wndAddress.GetLBText(m_wndAddress.GetCurSel(), str); ((CMFCIEView*)GetActiveView())->Navigate2(str, 0, NULL); } |
TCHAR GetDir( ) //得到存放用户收藏网址的目录; { TCHAR sz[MAX_PATH]; TCHAR szPath[MAX_PATH]; HKEY hKey; DWORD dwSize; CMenu* pMenu; // 得到"Favorites"菜单,并删除空白的子菜单项; pMenu = GetMenu()->GetSubMenu(3); while(pMenu->DeleteMenu(0, MF_BYPOSITION)); // find out from the registry where the favorites are located. if(RegOpenKey(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ User Shell Folders"), &hKey) != ERROR_SUCCESS) { TRACE0("Favorites folder not found\n"); return 0; } dwSize = sizeof(sz); RegQueryValueEx(hKey, _T("Favorites"), NULL, NULL, (LPBYTE)sz, &dwSize); ExpandEnvironmentStrings(sz, szPath, MAX_PATH); RegCloseKey(hKey); Return szPath } int CMainFrame::BuildFavoritesMenu(LPCTSTR pszPath, int nStartPos, CMenu* pMenu) { CString strPath(pszPath); CString strPath2; CString str; WIN32_FIND_DATA wfd; HANDLE h; int nPos; int nEndPos; int nNewEndPos; int nLastDir; TCHAR buf[INTERNET_MAX_PATH_LENGTH]; CStringArray astrFavorites; CStringArray astrDirs; CMenu* pSubMenu; if(strPath[strPath.GetLength() - 1] != _T(’\\’)) strPath += _T(’\\’); strPath2 = strPath; strPath += "*.*"; // 扫描当前目录,首先搜索*.URL文件,然后是可能含有*.URL文件的子目录; h = FindFirstFile(strPath, &wfd); if(h != INVALID_HANDLE_VALUE) { nEndPos = nStartPos; do { if((wfd.dwFileAttributes& (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM))==0) { str = wfd.cFileName; if(str.Right(4) == _T(".url")) {/*URL文件和INI文件格式类似,所以我们可以使用 GetPrivateProfileString() 来得到我们所需要的信息。*/ ::GetPrivateProfileString(_T("InternetShortcut"), T("URL"), _T(""),buf,INTERNET_MAX_PATH_LENGTH, strPath2 + str); str = str.Left(str.GetLength() - 4); // 判断是否已经重复; for(nPos = nStartPos ; nPos < nEndPos ; ++nPos) { if(str.CompareNoCase(astrFavorites[nPos]) < 0) break; } astrFavorites.InsertAt(nPos, str);//添加该字符串; m_astrFavoriteURLs.InsertAt(nPos, buf);//保留相应的地址 ++nEndPos; } } } while(FindNextFile(h, &wfd)); FindClose(h); // 将找到的项目添加到菜单中; for(nPos = nStartPos ; nPos < nEndPos ; ++nPos) { pMenu->AppendMenu(MF_STRING | MF_ENABLED, 0xe00 + nPos, astrFavorites[nPos]); } // 搜索子目录 nLastDir = 0; h = FindFirstFile(strPath, &wfd); ASSERT(h != INVALID_HANDLE_VALUE); do { if(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { //对目录进行搜索; if(lstrcmp(wfd.cFileName,_T(".")) == 0 || lstrcmp(wfd.cFileName, _T("..")) == 0) continue; for(nPos = 0 ; nPos < nLastDir ; ++nPos) { if(astrDirs[nPos].CompareNoCase(wfd.cFileName) > 0) break; } pSubMenu = new CMenu; pSubMenu->CreatePopupMenu(); // call this function recursively. nNewEndPos = BuildFavoritesMenu(strPath2 + wfd.cFileName, nEndPos, pSubMenu); if(nNewEndPos != nEndPos) { // 插入子菜单; nEndPos = nNewEndPos; pMenu->InsertMenu(nPos, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT)pSubMenu->m_hMenu, wfd.cFileName); pSubMenu->Detach(); astrDirs.InsertAt(nPos, wfd.cFileName); ++nLastDir; } delete pSubMenu; } } while(FindNextFile(h, &wfd)); FindClose(h); } return nEndPos; } |
void CMainFrame::OnFavorite(UINT nID) { ((CMFCIEView*)GetActiveView())->Navigate2(m_astrFavoriteURLs[nID-0xe00], 0, NULL); } |
二、编程步骤
1、 启动Visual C++6.0,生成一个单文档视图结构的应用程序,将该程序命名为"mfcie",注意在生成项目的过程中不要选择工具条和状态条选项,项目的视图类的基类设置为ChtmlView;
2、 按照上文中的说明,使用Class Wizard在程序的项目中添加相应的消息响应函数;
3、 向程序的项目中添加AVI、位图资源;
4、 添加代码,编译运行程序。