程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 利用Visual C++打造自己的IE浏覽器

利用Visual C++打造自己的IE浏覽器

編輯:關於VC++

IE浏覽器作為微軟Windows系統捆綁銷售的一個浏覽工具,用來浏覽千姿百態的網頁,目前它已經占據了浏覽器市場的半壁江山,成為Windows用戶不可或缺的工具。首先,它的界面設計的很漂亮,如扁平按紐(按鈕上的圖像為灰色,當鼠標放在按鈕上時,按鈕突起,這種狀態稱為手柄,並且其上的圖像變得鮮艷醒目)、按鈕上的文字說明以及按鈕邊上的小黑三角形狀的下拉箭頭(單擊時顯示下拉菜單)、工具條上的地址輸入欄等,都體現了Windows2000的風格;其次,它的收藏欄可以收藏用戶喜愛的網絡地址,這一切都為IE的流行打下了堅實的基礎。說了那麼多,也許讀者朋友們感覺到IE實現起來一定非常困難,其實IE也是個"紙老虎",實現它的難點主要是在界面效果和顯示收藏夾上,筆者在本實例中有針對性的敘述了IE界面、收藏網頁的顯示、網頁的浏覽等功能的實現,仔細看過這篇文章後,相信讀者朋友們一定可以打造出一個屬於自己的浏覽器。本實例中的程序代碼編譯運行後的界面效果如圖一所示:

圖一、浏覽器的運行界面

一、實現方法

1、浏覽器的界面實現

首先啟動Visual C++6.0,生成一個名為mfcie單文檔項目,注意在此過程中不要選擇工具條和狀態條選項,這樣才能更方便我們在後續工作中用代碼實現Windwos2000風格的工具條、狀態條;在工具條中添加地址欄;項目的視圖類的基類設置為ChtmlView,該類的Navigate2()成員函數專門用來現實超文本格式的文檔。在主框架類CmainFrame中定義CStatusBar m_wndStatusBar(狀態條對象)、CToolBar m_wndToolBar(工具欄對象)、CReBar m_wndReBar(、CComboBoxEx m_wndAddress(擴展的組合框對象,用來作為地址欄)、CAnimateCtrl m_wndAnimate(動畫控件,用來在工具欄上顯示動畫)、圖像列表對象CImageList img(存放顯示在工具欄上的圖標)等對象。向當前項目AVI資源文件,ID標志IDR_MFCAVI,添加Bitmap(位圖)資源,ID標志分別為IDB_COLDTOOLBAR、IDB_HOTTOOLBAR,分別如下所示:

圖二、包含按鈕圖標的位圖

1)IE風格工具條

IE風格界面的實現主要在主框架類的CMainFrame::OnCreate()函數中實現,它的主要思想如下: CReBar對象用來作為工具條、地址欄、動畫控件的容器,CImageList對象然後分別裝載工具欄上按鈕的熱點圖像和正常狀態下顯示的圖像,並將該對象附給工具條對象,使之建立關聯。為了顯示扁平工具欄,需要用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 str; //字符串對象;
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndReBar.Create(this)) //創建CReBar對象;
{ TRACE0("Failed to create rebarn");
return -1; }
if (!m_wndToolBar.CreateEx(this)) //使用CreateEx()函數創建工具條對象;
{ TRACE0("Failed to create toolbarn");
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 comboboxn");
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 barn");
return -1; }
…….//實現"Favorites"菜單的部分,該部分在第二部分介紹;
return 0;
}

2)工具條上的下拉菜單

當用戶點擊按鈕上的下拉箭頭時,將出現相應的菜單,為了實現這個功能,首先需要在CMainFrame.cpp文件的消息映射中添加消息映射:ON_NOTIFY(TBN_DROPDOWN, AFX_IDW_TOOLBAR, OnDropDown);在CmainFrame.h文件中添加消息映射函數聲明:afx_msg void OnDropDown(NMHDR* pNotifyStruct, LRESULT* pResult);最後添加下面的代碼:

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;
}

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_MFCAVI);

CanimateCtrl類提供了Play()、Seek()、Stop()、Close()等函數用來為播放視頻文件服務,它們使用起來都非常簡單,這裡就不再贅述了。

4)地址欄的操作

當用戶在地址欄上輸入網頁地址並按下回車鍵後,浏覽器將顯示該網頁的內容,並將在地址欄中記錄下該地址。因為回車鍵按下後對應的消息ID為IDOK,為此,需要在CmainFrame類中添加消息映射ON_COMMAND(IDOK, OnNewAddressEnter)和消息響應函數afx_msg void OnNewAddressEnter()。該函數實現代碼如下:

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);
}

同理,還要在CmainFrame類中為地址欄(ID 為AFX_IDW_TOOLBAR + 1)添加消息映射ON_CBN_SELENDOK(AFX_IDW_TOOLBAR + 1,OnNewAddress)和消息響應函數OnNewAddress,用來處理用戶從地址欄組合框中選擇網址的操作,該函數的實現代碼如下:

void CMainFrame::OnNewAddress()
{
CString str;
m_wndAddress.GetLBText(m_wndAddress.GetCurSel(), str);
((CMFCIEView*)GetActiveView())->Navigate2(str, 0, NULL);
}

2、實現收藏菜單

一般IE的用戶都有個習慣,那就是將自己喜歡的網址保存起來,以方便今後快速的登陸,為了使我們的浏覽器能夠顯示IE收藏過的網址,程序中設置了一個"Favorites"菜單,通過RegOpenKey()、RegQueryValueEx()等函數操作Windows的注冊表中的HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders項,將收藏的網址顯示到菜單上。為此,實例中定義了兩個函數,實現代碼如下所示:

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 foundn");
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;
}

3、顯示超文本

微軟ChtmView類的Navigate2函數可以實現超文本文件的顯示,GoBack()、GoForward()等函數可以分別實現網頁浏覽的回退和前進操作。以響應"Favorite"菜單項為例,需要在程序的CmainFrame類中添加消息映射ON_COMMAND_RANGE(0xe00, 0xfff, OnFavorite)和消息響應函數OnFavorite,來響應ID為0xe00-0xfff范圍內的菜單單擊處理,具體實現代碼如下:

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、 添加代碼,編譯運行程序。

三、程序代碼

//////////////////////////////////////////////
#if !defined(AFX_MAINFRM_H__47FF4081_CE1B_11D0_BEB6_00C04FC99F83__INCLUDED_)
#define AFX_MAINFRM_H__47FF4081_CE1B_11D0_BEB6_00C04FC99F83__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
class CMainFrame : public CFrameWnd
{
protected: // create from serialization only
CMainFrame();
DECLARE_DYNCREATE(CMainFrame)
// Attributes
public:
CStringArray m_astrFavoriteURLs;
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMainFrame)
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CMainFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
void SetAddress(LPCTSTR lpszUrl);
void StartAnimation();
int BuildFavoritesMenu(LPCTSTR pszPath, int nStartPos, CMenu* pMenu);
protected: // control bar embedded members
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar;
CReBar m_wndReBar;
// Generated message map functions
protected:
CComboBoxEx m_wndAddress;
CAnimateCtrl m_wndAnimate;
//{{AFX_MSG(CMainFrame)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
//}}AFX_MSG
afx_msg void DoNothing();
afx_msg void OnNewAddress();
afx_msg void OnNewAddressEnter();
afx_msg void OnFavorite(UINT nID);
afx_msg void OnDropDown(NMHDR* pNotifyStruct, LRESULT* pResult);
DECLARE_MESSAGE_MAP()
};
#endif
///////////////////// MainFrm.cpp : implementation of the CMainFrame class
#include "stdafx.h"
#include "mfcie.h"
#include <wininet.h>
#include "MainFrm.h"
#include "mfcieDoc.h"
#include "mfcieVw.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
//}}AFX_MSG_MAP
ON_CBN_SELENDOK(AFX_IDW_TOOLBAR + 1,OnNewAddress)
ON_COMMAND_RANGE(0xe00, 0xfff, OnFavorite)
ON_COMMAND(IDOK, OnNewAddressEnter)
ON_NOTIFY(TBN_DROPDOWN, AFX_IDW_TOOLBAR, OnDropDown)
ON_COMMAND(ID_FAVORITES_DROPDOWN, DoNothing)
ON_COMMAND(ID_FONT_DROPDOWN, DoNothing)
END_MESSAGE_MAP()
static UINT indicators[] =
{
ID_SEPARATOR, // status line indicator
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
CMainFrame::CMainFrame()
{
}
CMainFrame::~CMainFrame()
{
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
CImageList img;
CString str;
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndReBar.Create(this))
{
TRACE0("Failed to create rebarn");
return -1; // fail to create
}
if (!m_wndToolBar.CreateEx(this))
{
TRACE0("Failed to create toolbarn");
return -1; // fail to create
}
// set up toolbar properties
m_wndToolBar.GetToolBarCtrl().SetButtonWidth(50, 150);
m_wndToolBar.GetToolBarCtrl().SetExtendedStyle(TBSTYLE_EX_DRAWDDARROWS);
img.Create(IDB_HOTTOOLBAR, 22, 0, RGB(255, 0, 255));
m_wndToolBar.GetToolBarCtrl().SetHotImageList(&img);
img.Detach();
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);
m_wndToolBar.SetButtons(NULL, 9);
// set up each toolbar button
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;
// set up toolbar button sizes
m_wndToolBar.GetItemRect(0, &rectToolBar);
m_wndToolBar.SetSizes(rectToolBar.Size(), CSize(30,20));
// create a combo box for the address bar
if (!m_wndAddress.Create(CBS_DROPDOWN | WS_CHILD, CRect(0, 0, 100, 120),
this, AFX_IDW_TOOLBAR + 1))
{
TRACE0("Failed to create comboboxn");
return -1; // fail to create
}
// create the animation control
m_wndAnimate.Create(WS_CHILD | WS_VISIBLE, CRect(0, 0, 10, 10),
this, AFX_IDW_TOOLBAR + 2);
m_wndAnimate.Open(IDR_MFCAVI);
// add the toolbar, animation, and address bar to the rebar
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 barn");
return -1; // fail to create
}
// set up Favorites menu
TCHAR sz[MAX_PATH];
TCHAR szPath[MAX_PATH];
HKEY hKey;
DWORD dwSize;
CMenu* pMenu;
// first get rid of bogus submenu items.
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 foundn");
return 0;
}
dwSize = sizeof(sz);
RegQueryValueEx(hKey, _T("Favorites"), NULL, NULL, (LPBYTE)sz, &dwSize);
ExpandEnvironmentStrings(sz, szPath, MAX_PATH);
RegCloseKey(hKey);
BuildFavoritesMenu(szPath, 0, pMenu);
return 0;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
cs.lpszClass = AfxRegisterWndClass(0);
return CFrameWnd::PreCreateWindow(cs);
}
#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
CFrameWnd::AssertValid();
}
void CMainFrame::Dump(CDumpContext& dc) const
{
CFrameWnd::Dump(dc);
}
#endif //_DEBUG
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;
// make sure there’s a trailing backslash
if(strPath[strPath.GetLength() - 1] != _T(’\’))
strPath += _T(’\’);
strPath2 = strPath;
strPath += "*.*";
// now scan the directory, first for .URL files and then for subdirectories
// that may also contain .URL files
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"))
{
// an .URL file is formatted just like an .INI file, so we can
// use GetPrivateProfileString() to get the information we want
::GetPrivateProfileString(_T("InternetShortcut"),
_T("URL"), _T(""), buf, INTERNET_MAX_PATH_LENGTH, strPath2 + str);
str = str.Left(str.GetLength() - 4);
// scan through the array and perform an insertion sort
// to make sure the menu ends up in alphabetic order
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);
// Now add these items to the menu
for(nPos = nStartPos ; nPos < nEndPos ; ++nPos)
{
pMenu->AppendMenu(MF_STRING | MF_ENABLED, 0xe00 + nPos,
astrFavorites[nPos]);
}
// now that we’ve got all the .URL files, check the subdirectories for more
nLastDir = 0;
h = FindFirstFile(strPath, &wfd);
ASSERT(h != INVALID_HANDLE_VALUE);
do
{
if(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
// ignore the current and parent directory entries
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)
{
// only intert a submenu if there are in fact .URL files in the subdirectory
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);
}
void CMainFrame::SetAddress(LPCTSTR lpszUrl)
{
// This is called when the browser has completely loaded the new location,
// so make sure the text in the address bar is up to date and stop the
// animation.
m_wndAddress.SetWindowText(lpszUrl);
m_wndAnimate.Stop();
m_wndAnimate.Seek(0);
}
void CMainFrame::StartAnimation()
{
// Start the animation. This is called when the browser begins to
// navigate to a new location
m_wndAnimate.Play(0, -1, -1);
}
void CMainFrame::OnNewAddress()
{
// gets called when an item in the Address combo box is selected
// just navigate to the newly selected location.
CString str;
m_wndAddress.GetLBText(m_wndAddress.GetCurSel(), str);
((CMfcieView*)GetActiveView())->Navigate2(str, 0, NULL);
}
void CMainFrame::OnNewAddressEnter()
{
// gets called when an item is entered manually into the edit box portion
// of the Address combo box.
// navigate to the newly selected location and also add this address to the
// list of addresses in the combo box.
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::DoNothing()
{
// this is here only so that the toolbar buttons for the dropdown menus
// will have a callback, and thus will not be disabled.
}
void CMainFrame::OnDropDown(NMHDR* pNotifyStruct, LRESULT* pResult)
{
// this function handles the dropdown menus from the toolbar
NMTOOLBAR* pNMToolBar = (NMTOOLBAR*)pNotifyStruct;
CRect rect;
// translate the current toolbar item rectangle into screen coordinates
// so that we’ll know where to pop up the menu
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;
// the font popup is stored in a resource
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;
// for the favorties popup, just steal the menu from the main window
pPopup = GetMenu()->GetSubMenu(3);
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,
rect.left, rect.top + 1, AfxGetMainWnd());
}
*pResult = TBDDRET_DEFAULT;
}
///////////////////////////////////
#if !defined(AFX_MFCIEVIEW_H__47FF4085_CE1B_11D0_BEB6_00C04FC99F83__INCLUDED_)
#define AFX_MFCIEVIEW_H__47FF4085_CE1B_11D0_BEB6_00C04FC99F83__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
class CMfcieView : public CHtmlView
{
protected: // create from serialization only
CMfcieView();
DECLARE_DYNCREATE(CMfcieView)
// Attributes
public:
CMfcieDoc* GetDocument();
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMfcieView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
virtual void OnInitialUpdate();
//}}AFX_VIRTUAL
void OnTitleChange(LPCTSTR lpszText);
void OnDocumentComplete(LPCTSTR lpszUrl);
void OnBeforeNavigate2(LPCTSTR lpszURL, DWORD nFlags,
LPCTSTR lpszTargetFrameName, CByteArray& baPostedData,
LPCTSTR lpszHeaders, BOOL* pbCancel);
// Implementation
public:
virtual ~CMfcieView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
//{{AFX_MSG(CMfcieView)
afx_msg void OnGoBack();
afx_msg void OnGoForward();
afx_msg void OnGoSearchTheWeb();
afx_msg void OnGoStartPage();
afx_msg void OnViewStop();
afx_msg void OnViewRefresh();
afx_msg void OnHelpWebTutorial();
afx_msg void OnHelpOnlineSupport();
afx_msg void OnHelpMicrosoftOnTheWebFreeStuff();
afx_msg void OnHelpMicrosoftOnTheWebFrequentlyAskedQuestions();
afx_msg void OnHelpMicrosoftOnTheWebGetFasterInternetAccess();
afx_msg void OnHelpMicrosoftOnTheWebMicrosoftHomePage();
afx_msg void OnHelpMicrosoftOnTheWebSearchTheWeb();
afx_msg void OnHelpMicrosoftOnTheWebSendFeedback();
afx_msg void OnHelpMicrosoftOnTheWebInternetStartPage();
afx_msg void OnHelpMicrosoftOnTheWebBestOfTheWeb();
afx_msg void OnViewFontsLargest();
afx_msg void OnViewFontsLarge();
afx_msg void OnViewFontsMedium();
afx_msg void OnViewFontsSmall();
afx_msg void OnViewFontsSmallest();
afx_msg void OnFileOpen();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
#ifndef _DEBUG // debug version in mfcieView.cpp
inline CMfcieDoc* CMfcieView::GetDocument()
{ return (CMfcieDoc*)m_pDocument; }
#endif
#endif
////////////////////////////////////////////////
#include "stdafx.h"
#include "mfcie.h"
#include "MainFrm.h"
#include "mfcieDoc.h"
#include "mfcieVw.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
////////////////////////////////////// CMfcieView
IMPLEMENT_DYNCREATE(CMfcieView, CHtmlView)
BEGIN_MESSAGE_MAP(CMfcieView, CHtmlView)
//{{AFX_MSG_MAP(CMfcieView)
ON_COMMAND(ID_GO_BACK, OnGoBack)
ON_COMMAND(ID_GO_FORWARD, OnGoForward)
ON_COMMAND(ID_GO_SEARCH_THE_WEB, OnGoSearchTheWeb)
ON_COMMAND(ID_GO_START_PAGE, OnGoStartPage)
ON_COMMAND(ID_VIEW_STOP, OnViewStop)
ON_COMMAND(ID_VIEW_REFRESH, OnViewRefresh)
ON_COMMAND(ID_HELP_WEB_TUTORIAL, OnHelpWebTutorial)
ON_COMMAND(ID_HELP_ONLINE_SUPPORT, OnHelpOnlineSupport)
ON_COMMAND(ID_HELP_MICROSOFT_ON_THE_WEB_FREE_STUFF, OnHelpMicrosoftOnTheWebFreeStuff)
ON_COMMAND(ID_HELP_MICROSOFT_ON_THE_WEB_FREQUENTLY_ASKED_QUESTIONS, OnHelpMicrosoftOnTheWebFrequentlyAskedQuestions)
ON_COMMAND(ID_HELP_MICROSOFT_ON_THE_WEB_GET_FASTER_INTERNET_ACCESS, OnHelpMicrosoftOnTheWebGetFasterInternetAccess)
ON_COMMAND(ID_HELP_MICROSOFT_ON_THE_WEB_MICROSOFT_HOME_PAGE, OnHelpMicrosoftOnTheWebMicrosoftHomePage)
ON_COMMAND(ID_HELP_MICROSOFT_ON_THE_WEB_SEARCH_THE_WEB, OnHelpMicrosoftOnTheWebSearchTheWeb)
ON_COMMAND(ID_HELP_MICROSOFT_ON_THE_WEB_SEND_FEEDBACK, OnHelpMicrosoftOnTheWebSendFeedback)
ON_COMMAND(ID_HELP_MICROSOFT_ON_THE_WEB_INTERNET_START_PAGE, OnHelpMicrosoftOnTheWebInternetStartPage)
ON_COMMAND(ID_HELP_MICROSOFT_ON_THE_WEB_BEST_OF_THE_WEB, OnHelpMicrosoftOnTheWebBestOfTheWeb)
ON_COMMAND(ID_VIEW_FONTS_LARGEST, OnViewFontsLargest)
ON_COMMAND(ID_VIEW_FONTS_LARGE, OnViewFontsLarge)
ON_COMMAND(ID_VIEW_FONTS_MEDIUM, OnViewFontsMedium)
ON_COMMAND(ID_VIEW_FONTS_SMALL, OnViewFontsSmall)
ON_COMMAND(ID_VIEW_FONTS_SMALLEST, OnViewFontsSmallest)
ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CMfcieView::CMfcieView()
{
}
CMfcieView::~CMfcieView()
{
}
BOOL CMfcieView::PreCreateWindow(CREATESTRUCT& cs)
{
cs.lpszClass = AfxRegisterWndClass(0);
return CView::PreCreateWindow(cs);
}
void CMfcieView::OnDraw(CDC* pDC)
{
CMfcieDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
}
#ifdef _DEBUG
void CMfcieView::AssertValid() const
{
CView::AssertValid();
}
void CMfcieView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CMfcieDoc* CMfcieView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMfcieDoc)));
return (CMfcieDoc*)m_pDocument;
}
#endif //_DEBUG
void CMfcieView::OnTitleChange(LPCTSTR lpszText)
{
// this will change the main frame’s title bar
if (m_pDocument != NULL)
m_pDocument->SetTitle(lpszText);
}
void CMfcieView::OnDocumentComplete(LPCTSTR lpszUrl)
{
// make sure the main frame has the new URL. This call also stops the animation
((CMainFrame*)GetParentFrame())->SetAddress(lpszUrl);
}
void CMfcieView::OnInitialUpdate()
{
// Go to the home page initially
CHtmlView::OnInitialUpdate();
GoHome();
}
void CMfcieView::OnBeforeNavigate2(LPCTSTR /*lpszURL*/, DWORD /*nFlags*/,
LPCTSTR /*lpszTargetFrameName*/, CByteArray& /*baPostedData*/,
LPCTSTR /*lpszHeaders*/, BOOL* /*pbCancel*/)
{
// start the animation so that is plays while the new page is being loaded
((CMainFrame*)GetParentFrame())->StartAnimation();
}
// these are all simple one-liners to do simple controlling of the browser
void CMfcieView::OnGoBack()
{
GoBack();
}
void CMfcieView::OnGoForward()
{
GoForward();
}
void CMfcieView::OnGoSearchTheWeb()
{
GoSearch();
}
void CMfcieView::OnGoStartPage()
{
GoHome();
}
void CMfcieView::OnViewStop()
{
Stop();
}
void CMfcieView::OnViewRefresh()
{
Refresh();
}
// these all go to specific web pages, just like Internet Explorer’s help menu
void CMfcieView::OnHelpWebTutorial()
{
CString str;
str.LoadString(IDS_WEB_TUTORIAL);
Navigate2(str, 0, NULL);
}
void CMfcieView::OnHelpOnlineSupport()
{
CString str;
str.LoadString(IDS_ONLINE_SUPPORT);
Navigate2(str, 0, NULL);
}
void CMfcieView::OnHelpMicrosoftOnTheWebBestOfTheWeb()
{
CString str;
str.LoadString(IDS_BEST_OF_THE_WEB);
Navigate2(str, 0, NULL);
}
void CMfcieView::OnHelpMicrosoftOnTheWebFreeStuff()
{
CString str;
str.LoadString(IDS_FREE_STUFF);
Navigate2(str, 0, NULL);
}
void CMfcieView::OnHelpMicrosoftOnTheWebFrequentlyAskedQuestions()
{
CString str;
str.LoadString(IDS_FREQUENTLY_ASKED_QUESTIONS);
Navigate2(str, 0, NULL);
}
void CMfcieView::OnHelpMicrosoftOnTheWebGetFasterInternetAccess()
{
CString str;
str.LoadString(IDS_GET_FASTER_INTERNET_ACCESS);
Navigate2(str, 0, NULL);
}
void CMfcieView::OnHelpMicrosoftOnTheWebMicrosoftHomePage()
{
CString str;
str.LoadString(IDS_MICROSOFT_HOME_PAGE);
Navigate2(str, 0, NULL);
}
void CMfcieView::OnHelpMicrosoftOnTheWebSearchTheWeb()
{
CString str;
str.LoadString(IDS_SEARCH_THE_WEB);
Navigate2(str, 0, NULL);
}
void CMfcieView::OnHelpMicrosoftOnTheWebSendFeedback()
{
CString str;
str.LoadString(IDS_SEND_FEEDBACK);
Navigate2(str, 0, NULL);
}
void CMfcieView::OnHelpMicrosoftOnTheWebInternetStartPage()
{
CString str;
str.LoadString(IDS_INTERNET_START_PAGE);
Navigate2(str, 0, NULL);
}
// these functions control the font size. There is no explicit command in the
// CHtmlView class to do this, but we can do it by using the ExecWB() function.
void CMfcieView::OnViewFontsLargest()
{
COleVariant vaZoomFactor(4l);
ExecWB(OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER,
&vaZoomFactor, NULL);
}
void CMfcieView::OnViewFontsLarge()
{
COleVariant vaZoomFactor(3l);
ExecWB(OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER,
&vaZoomFactor, NULL);
}
void CMfcieView::OnViewFontsMedium()
{
COleVariant vaZoomFactor(2l);
ExecWB(OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER,
&vaZoomFactor, NULL);
}
void CMfcieView::OnViewFontsSmall()
{
COleVariant vaZoomFactor(1l);
ExecWB(OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER,
&vaZoomFactor, NULL);
}
void CMfcieView::OnViewFontsSmallest()
{
COleVariant vaZoomFactor(0l);
ExecWB(OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER,
&vaZoomFactor, NULL);
}
// This demonstrates how we can use the Navigate2() function to load local files
// including local HTML pages, GIFs, AIFF files, etc.
void CMfcieView::OnFileOpen()
{
CString str;
str.LoadString(IDS_FILETYPES);
CFileDialog fileDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, str);
if(fileDlg.DoModal() == IDOK)
Navigate2(fileDlg.GetPathName(), 0, NULL);
}

四、小結

上面的代碼相對較多,對某些函數的使用不清楚的話,請參考MSDN,它包含了高級界面處理、注冊表的操作等內容,也許剛開始看起來可能感到有些困難,但是如果讀者朋友細細品味的話,一定可以學到一些東西,對今後程序的界面開發有所幫助。

  1. 上一頁:
  2. 下一頁:
欄目導航
Copyright © 程式師世界 All Rights Reserved