IE瀏覽器作為微軟Windows系統捆綁的瀏覽工具,用於瀏覽各種網頁。目前已經占據了瀏覽器市場的半壁江山,成為Windows用戶不可或缺的工具。首先,它的界面設計得很漂亮,比如扁平的按鈕(按鈕上的圖像是灰色的,鼠標放在按鈕上,按鈕突出來,稱為手柄,上面的圖像變得明亮醒目),按鈕上的文字說明,按鈕旁邊黑色小三角形狀的下拉箭頭(點擊時顯示下拉菜單),工具欄上的地址輸入欄等。,這些都體現了Windows2000的風格。其次,它的收藏欄可以收集用戶喜歡的網址,為IE的普及打下了堅實的基礎。說到這裏,讀者可能會覺得IE壹定很難實現。其實IE也是“紙老虎”,實現的難度主要在界面效果和收藏夾的顯示上。在這個例子中,作者描述了IE界面的實現,喜歡的網頁的顯示,網頁的瀏覽等功能。仔細閱讀這篇文章後,我相信讀者將能夠建立壹個自己的瀏覽器。本例中編譯後的程序代碼的界面效果如圖1所示:
圖壹。瀏覽器的操作界面
壹、實現方法
1,瀏覽器界面實現
首先啟動Visual C++6.0生成壹個名為mfcie的單文檔項目,註意在這個過程中不要選擇工具欄和狀態欄選項,以便我們在後續工作中用代碼實現Windwos2000風格的工具欄和狀態欄時更加方便。向工具欄添加地址欄;項目的view類的基類設置為ChtmlView,這個類的Navigate2()成員函數專門用來實現超文本格式的文檔。定義CStatusBar m_wndStatusBar(狀態欄對象)、CToolBar m_wndToolBar(工具欄對象)、CReBar m_wndReBar(、CComboBoxEx m _ wndAddress(擴展組合框對象,用作地址欄)、CAnimateCtrl m_wndAnimate(動畫控件,用於在工具欄上顯示動畫)、圖像列表對象CImageList img(存儲工具欄上顯示的圖標)等對象。在當前項目的AVI資源文件中添加位圖(Bitmap)資源,ID標誌為IDR_MFCAVI,ID標誌分別為IDB_COLDTOOLBAR和IDB_HOTTOOLBAR,如下圖:
圖二。包含按鈕圖標的位圖
1)IE風格工具欄
IE風格界面的實現主要在主框架類的cminframe:: oncreate()函數中實現。其主要思想是:CReBar對象作為工具欄、地址欄和動畫控件的容器,CImageList對象再分別加載工具欄上按鈕的熱圖像和正常狀態下顯示的圖像,並將該對象附加到toolbar對象上,使其相關聯。為了顯示平面工具欄,需要使用CreateEx()函數創建CToolBar對象m_wndToolBar,並使用ModifyStyle()函數將工具欄的樣式設置為平面類型。註意,這個新樣式不能用CToolBar::Create()或CToolBar:: SetBarStyle()設置。CToolBar類不支持TBSTYLE_FLAT。要解決這個問題,我們必須繞過CToolBar類,使用CWnd::ModifyStyle()。要設置帶有下拉按鈕的工具欄按鈕,可以調用SetButtonInfo()將按鈕的樣式設置為TBSTYLE_DROPDOWN。至於有中文提示的按鈕,可以用工具欄中的SetButtonText()輕松實現。以下是實現IE風格界面的代碼和註釋:
int CMainFrame::OnCreate(LPCREATESTRUCT LPCREATESTRUCT)
{
CImageList img//圖像列表對象;
CString字符串;//字符串對象;
if(CFrameWnd::OnCreate(lpCreateStruct)= =-1)
return-1;
如果(!M_wndReBar。Create(this)) //創建壹個CReBar對象;
{ TRACE0("未能創建rebar \ n ");
return-1;}
如果(!M_wndToolBar。CreateEx(this)) //使用CreateEx()函數創建工具欄對象;
{ TRACE0("未能創建工具欄\ n ");
return-1;}
//設置工具欄中按鈕的最大和最小尺寸;
m_wndToolBar。GetToolBarCtrl()。SetButtonWidth(50,150);
//設置工具欄上的按鈕支持下拉箭頭樣式;
m_wndToolBar。GetToolBarCtrl()。SetExtendedStyle(TB style _ EX _ draw ddarrows);
//將熱點圖片資源加載到圖片列表中,其中IDB_HOTTOOLBAR為熱點圖片資源Idimg.create (IDB _ hottoolbar,22,0,RGB (255,0,255));
m_wndToolBar。GetToolBarCtrl()。SetHotImageList(& amp;img);
img。detach();
//圖片列表加載的是普通圖片資源,IDB_COLDTOOLBAR是圖片資源ID。
img。Create(IDB_COLDTOOLBAR,22,0,RGB(255,0,255));
m_wndToolBar。GetToolBarCtrl()。set imagelist(& amp;img);
img。detach();
//將工具欄設置為平面樣式。
m_wndToolBar。ModifyStyle(0,TB style _ FLAT | TB style _ TRANSPARENT);
//將工具欄上的按鈕數量設置為9;
m_wndToolBar。SetButtons(NULL,9);
//加載字符串資源,設置按鈕上的文本和按鈕的標識號;
m_wndToolBar。SetButtonInfo(0,ID_GO_BACK,TBSTYLE_BUTTON,0);
海峽。LoadString(IDS _ BACK);
m_wndToolBar。SetButtonText(0,str);
m_wndToolBar。SetButtonInfo(1,ID_GO_FORWARD,TBSTYLE_BUTTON,1);
海峽。LoadString(IDS _ FORWARD);
m_wndToolBar。SetButtonText(1,str);
m_wndToolBar。SetButtonInfo(2,ID_VIEW_STOP,TBSTYLE_BUTTON,2);
海峽。LoadString(IDS _ STOP);
m_wndToolBar。SetButtonText(2,str);
m_wndToolBar。SetButtonInfo(3,ID_VIEW_REFRESH,TBSTYLE_BUTTON,3);
海峽。LoadString(IDS _ REFRESH);
m_wndToolBar。SetButtonText(3,str);
m_wndToolBar。SetButtonInfo(4,ID_GO_START_PAGE,TBSTYLE_BUTTON,4);
海峽。LoadString(IDS _ HOME);
m_wndToolBar。SetButtonText(4,str);
m_wndToolBar。SetButtonInfo(5,ID_GO_SEARCH_THE_WEB,TBSTYLE_BUTTON,5);
海峽。LoadString(IDS _ SEARCH);
m_wndToolBar。SetButtonText(5,str);
m_wndToolBar。SetButtonInfo(6,ID_FAVORITES_DROPDOWN,TB style _ BUTTON | TB style _ drop down,6);
海峽。LoadString(IDS _ FAVORITES);
m_wndToolBar。SetButtonText(6,str);
m_wndToolBar。SetButtonInfo(7,ID_FILE_PRINT,TBSTYLE_BUTTON,7);
海峽。LoadString(IDS _ PRINT);
m_wndToolBar。SetButtonText(7,str);
m_wndToolBar。SetButtonInfo(8,ID_FONT_DROPDOWN,TB style _ BUTTON | TB style _ drop down,8);
海峽。LoadString(IDS _ FONT);
m_wndToolBar。SetButtonText(8,str);
//設置工具欄上的按鈕大小和按鈕上顯示的圖標大小;
CRect rectToolBar
m_wndToolBar。GetItemRect(0 & amp;rect toolbar);
m_wndToolBar。SetSizes(矩形工具欄。Size(),CSize(30,20));
//創建壹個組合框用作地址欄;
如果(!m_wndAddress。Create(CBS_DROPDOWN | WS_CHILD,CRect(0,0,200,120),this,AFX_IDW_TOOLBAR + 1))
{ TRACE0("未能創建combobox \ n ");
return-1;}
//創建動畫控件對象,打開AVI資源IDR _ MFC AVI;
m_wndAnimate。Create(WS_CHILD | WS_VISIBLE,CRect(0,0,10,10),this,AFX _ IDW _ TOOLBAR+2);
m_wndAnimate。open(IDR _ MF cavi);
//添加工具欄、地址欄、動畫控件等。添加到CReBar對象;
m_wndReBar。AddBar(& amp;m _ wndToolBar);
m_wndReBar。AddBar(& amp;m_wndAnimate,NULL,NULL,RBBS _ fixed size | RBBS _ fixed BMP);
海峽。LoadString(IDS _ ADDRESS);
m_wndReBar。AddBar(& amp;m_wndAddress,str,NULL,RBBS _ fixed BMP | RBBS _ BREAK);
//重新設置工具欄樣式,使其具有工具欄提示功能;
m_wndToolBar。SetBarStyle(m_wndToolBar。getbar style()| CBRS _工具提示| CBRS _飛越| CBRS _大小_固定);
//設置狀態欄;
如果(!m_wndStatusBar。創造(這個)||!m_wndStatusBar。SetIndicators(indicators,sizeof(indicators)/sizeof(UINT))
{ TRACE0("未能創建狀態欄\ n ");
return-1;}
......//第二部介紹的“收藏夾”菜單的壹部分;
返回0;
}
2)工具欄上的下拉菜單
當用戶點擊按鈕上的下拉箭頭時,會出現相應的菜單。為了實現這個功能,首先需要在CMainFrame.cpp文件的消息映射中添加壹個消息映射:on _ notify (TBN _下拉,AFX _ IDW _工具欄,ondrop down);在CmainFrame.h文件中添加消息映射函數聲明:AFX _ msg void on drop down(nmhdr * pnotifystruct,lresult * Presult);最後,添加以下代碼:
void CMainFrame::OnDropDown(NMHDR * pNotifyStruct,LRESULT* pResult)
{
nm toolbar * pNMToolBar =(nm toolbar *)pNotifyStruct;
CRect rect
//獲取下拉箭頭的位置;
m_wndToolBar。GetToolBarCtrl()。GetRect(pnm toolbar-& gt;項目& amprect);
rect . top = rect . bottom;
* client to screen(pnm toolbar-& gt;HDR . hwnd from & amp;直腸。top left());
if(pNMToolBar-& gt;iItem == ID_FONT_DROPDOWN)
//確定是否是下拉箭頭選擇字體;
{
CMenu菜單;
CMenu * pPopup
菜單。load menu(IDR _ FONT _ POPUP);
pPopup =菜單。get submenu(0);
ppop up-& gt;TrackPopupMenu(TPM _ left align | TPM _ left button,rect.left,rect.top + 1,AfxGetMainWnd());
}
else if(pNMToolBar-& gt;iItem == ID_FAVORITES_DROPDOWN)
{//確定是否為顯示收藏網頁的下拉箭頭;
CMenu * pPopup
ppop up = get menu()-& gt;get submenu(3);
ppop up-& gt;trackppopupmenu(TPM _ left align | TPM _ left button,rect.left,
rect.top + 1,AfxGetMainWnd());
}
* pResult = TBDDRET _ DEFAULT
}
3)工具欄上的動畫實現
為了美化程序的界面,在程序的復合工具欄上放置了壹個動畫控件,用於在適當的時候播放動畫片段,實現動畫效果。下面的代碼實現了動畫控件對象的創建,並打開了AVI資源IDR_MFCAVI:
m_wndAnimate。Create(WS_CHILD | WS_VISIBLE,CRect(0,0,10,10),this,AFX _ IDW _ TOOLBAR+2);
m_wndAnimate。open(IDR _ MF cavi);
CanimateCtrl類提供Play()、Seek()、Stop()和Close()等函數,用於播放視頻文件。它們使用起來非常簡單,這裏就不贅述了。
4)地址欄的操作
當用戶在地址欄中輸入壹個網頁的地址並按回車鍵後,瀏覽器會顯示該網頁的內容,並將該地址記錄在地址欄中。因為按回車鍵後對應的消息ID是IDOK,所以需要在CmainFrame類中添加壹個消息映射on _ command (idok,onnewaddrender)和壹個消息響應函數AFX _ msgvoid onnewaddrender()。功能實現代碼如下:
void CMainFrame::OnNewAddressEnter()
{
CString字符串;
//獲取地址欄中的字符串;
m_wndAddress。GetEditCtrl()-& gt;GetWindowText(str);
((CMfcieView *)GetActiveView())-& gt;Navigate2(str,0,NULL);//顯示網頁;
//將URL添加到地址欄對應的組合框中;
COMBOBOXEXITEM項;
item.mask = CBEIF _ TEXT
item . iitem =-1;
item . psztext =(LPTSTR)(LPCTSTR)str;
m_wndAddress。insert item(& amp;項);
}
同樣的,CmainFrame類中的地址欄(ID: AFX _ IDW _工具欄+1)也要添加消息映射on _ CBN _ selen dok(AFX _ IDW _工具欄+1)和消息響應函數OnNewAddress,來處理用戶從地址欄組合框中選擇URL的操作。
void CMainFrame::OnNewAddress()
{
CString字符串;
m_wndAddress。GetLBText(m_wndAddress。GetCurSel(),str);
((CMFCIEView *)GetActiveView())-& gt;Navigate2(str,0,NULL);
}
2、實現收藏菜單
壹般IE的用戶都有壹個習慣,就是把自己喜歡的網站保存下來,以備日後快速登錄。為了使我們的瀏覽器能夠顯示IE收集的網站,程序中設置了壹個“收藏夾”菜單。通過RegOpenKey()、RegQueryValueEx()等函數操作Windows註冊表中的HKEY _當前_用戶\ \軟件\ \微軟\ \ Windows \ \當前版本\ \資源管理器\ \用戶Shell文件夾,在菜單上顯示喜歡的網站。為此,示例中定義了兩個函數,實現代碼如下:
TCHAR GetDir() //獲取存儲用戶喜愛網站的目錄;
{
TCHAR SZ[MAX _ PATH];
TCHAR SZ PATH[MAX _ PATH];
HKEY hKey;
DWORD dwSize
CMenu * pMenu
//獲取“收藏夾”菜單,刪除空白子菜單項;
pMenu = get menu()-& gt;get submenu(3);
while(pMenu->;DeleteMenu(0,MF _ by position));
//從註冊表中找出收藏夾所在的位置。
if(RegOpenKey(HKEY當前用戶,_T("軟件\\微軟\ \視窗\ \當前版本\ \資源管理器\ \
用戶外殼文件夾”)、& amphKey)!=錯誤_成功)
{
TRACE0("找不到收藏夾\ n ");
返回0;
}
dwSize = sizeof(SZ);
RegQueryValueEx(hKey,_T("Favorites "),NULL,NULL,(LPBYTE)sz,& ampdwSize);
ExpandEnvironmentStrings(sz,szPath,MAX _ PATH);
RegCloseKey(hKey);
返回szPath
}
int CMainFrame::BuildFavoritesMenu(LPCTSTR PSZ path,int nStartPos,CMenu* pMenu)
{
CString strPath(PSZ path);
CString strPath2
CString字符串;
WIN32 _ FIND _ DATA wfd
手柄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,& ampWFD);
如果(h!=無效句柄值)
{
nEndPos = nStartPos
做
{
if((WFD . dwfile attributes & amp;
(文件屬性目錄|文件屬性隱藏|文件屬性系統))==0)
{
str = wfd.cFileName
如果(字符串。Right(4) == _T("。網址"))
{/*URL文件的格式與INI文件類似,所以我們可以使用GetPrivateProfileString()來獲取我們需要的信息。*/
* GetPrivateProfileString(_ T(" internet shortcut "),T("URL "),
_T(" "),buf,INTERNET_MAX_PATH_LENGTH,
strpath 2+str);
str = str。左側(字符串。GetLength()-4);
//判斷是否重復過;
for(nPos = nstart pos;nPos & lt。nEndPos++ NPO)
{
如果(字符串。compare nocase(astrFavorites[nPos])& lt;0)
打破;
}
astrFavorites。InsertAt(nPos,str);//添加字符串;
m_astrFavoriteURLs。InsertAt(nPos,buf);//保留對應的地址。
++ nend pos;
}
}
} while(FindNextFile(h,& ampWFD));
FindClose(h);
//將找到的項目添加到菜單中;
for(nPos = nstart pos;nPos & lt。nEndPos++ NPO)
{
pMenu->;AppendMenu(MF _ STRING | MF _ ENABLED,0xe00 + nPos,astrFavorites[nPos]);
}
//搜索子目錄
nLastDir = 0;
h = FindFirstFile(strPath,& ampWFD);
斷言(h!=無效句柄值);
做
{
if(WFD . dwfile attributes & amp;文件_屬性_目錄)
{//搜索目錄;
if(lstrcmp(wfd.cFileName,_T(","))== 0 || lstrcmp(wfd.cFileName,_T(" .. ")) == 0)
繼續;
for(nPos = 0;nPos & lt。nLastDir++ NPO)
{
if(astrDirs[nPos]。CompareNoCase(wfd.cFileName)>0)
打破;
}
pSubMenu =新CMenu
pSubMenu-& gt;CreatePopupMenu();
//遞歸調用此函數。
nNewEndPos = BuildFavoritesMenu(strpath 2+WFD . cfilename,nEndPos,pSubMenu);
if(nNewEndPos!= nEndPos)
{
//插入子菜單;
nEndPos = nNewEndPos
pMenu->;InsertMenu(nPos,MF _ by position | MF _ POPUP | MF _ STRING,(UINT)pSubMenu-& gt;m_hMenu,WFD . cfilename);
pSubMenu-& gt;detach();
阿斯特迪爾。InsertAt(nPos,WFD . cfilename);
++ nLastDir;
}
刪除pSubMenu
}
} while(FindNextFile(h,& ampWFD));
FindClose(h);
}
返回nEndPos
}
3.顯示超文本
微軟ChtmView類的Navigate2函數可以顯示超文本文件,GoBack()和GoForward()等函數可以分別實現網頁瀏覽的後退和前進操作。以響應“收藏夾”菜單項為例,需要在程序的CmainFrame類中添加消息映射on _ command _ range (0xe00,0xfff,OnFavorite)和消息響應函數onfavorite,以響應ID為0xe00-0xfff的菜單點擊處理。具體實現代碼如下:
void CMainFrame::on favorite(UINT nID)
{
((CMFCIEView *)GetActiveView())-& gt;navigate 2(m _ astrFavoriteURLs[nID-0xe 00],0,NULL);
}
二、編程步驟
1.啟動Visual C++6.0生成壹個單文檔視圖結構的應用程序,將程序命名為“mfcie”。註意不要在生成項目的過程中選擇工具欄和狀態欄選項,項目的視圖類基類設置為ChtmlView;
2.根據以上描述,利用類向導在程序項目中添加相應的消息響應函數;
3.將AVI和位圖資源添加到程序的項目中;
4.添加代碼,編譯並運行程序。