目 录
摘 要 2
1设计题目与要求 2
2系统设计 2
2.1总体设计 2
2.2详细设计 2
2.2.1用户界面设计 3
2.2.2多标签模块设计 6
2.2.3浏览模块设计 6
2.2.4操作按钮模块设计 9
2.2.5页面缩放模块设计 10
2.2.6状态栏模块设计 11
2.2.7收藏夹模块设计 13
2.2.8窗体关闭模块设计 13
2.3系统平台、语言和工具 14
3调试过程及操作说明 14
3.1启动 Web 浏览器 14
3.2浏览网页 14
3.3修改界面样式及查看帮助 16
3.4退出程序 16
4开发中遇到的问题及解决方案 18
4.1无法获取到正确的网页标题 18
4.2多文档模式开发中获取活动窗口的问题 18
4.3页面缩放的问题 19
5目前未解决的问题 19
5.1浏览器状态无法正常显示 19
5.2标签切换时地址栏内容未切换 19
5.3标签切换时网页标题丢失 20
6自我评价与总结 20
参考文献 21
本科毕业论文评分表 22
1设计题目与要求
设计题目:基于VC++的WEB浏览器的实现设计要求:①能实现浏览器外观界面的设计
②能实现网页的浏览、后退、前进、刷新等基本功能
③实现其它附加功能(不在要求范围之内)
④界面良好,功能完善
2系统设计
2.1总体设计
本次毕业设计所实现的 Web 浏览器首先要实现设计要求中的功能,要有友好的界面,能正常的浏览网页,能实现后退、前进、刷新等基本功能。
此外,在要求的功能之上,对 Web 浏览器的功能进行了扩充,能实现网页保存、打印网页、在网页上查找、选中全部内容、标签式多窗口浏览、关闭浏览器提示、页面缩放、网页加载进度显示、浏览器状态以及界面样式更换等功能。
2.2详细设计
本 Web 浏览器具有较多的功能,因而采用了模块化的设计思想,将每个功能做成了相应的模块,便于开发。另外由于 Web 浏览器的自身性质,本次开发采用了 MFC 的多文档(MDI) 模式,使用 App—MainFrame—ChildFrame—View 的模式开发。
// MainFrm.cpp : CMainFrame 类的实现
//
#include "stdafx.h"
#include "WebBrowser.h"
#include "ChildFrm.h"
#include "MainFrm.h"
#include "CloseDlg.h"
#define WM_NEWURL WM_USER+104
#define ID_STATUSBAR_PROGRESS 9999
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMainFrame
IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWndEx)
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx)
ON_WM_CREATE()
// 全局帮助命令
ON_COMMAND(ID_HELP_FINDER, &CMDIFrameWndEx::OnHelpFinder)
ON_COMMAND(ID_HELP, &CMDIFrameWndEx::OnHelp)
ON_COMMAND(ID_CONTEXT_HELP, &CMDIFrameWndEx::OnContextHelp)
ON_COMMAND(ID_DEFAULT_HELP, &CMDIFrameWndEx::OnHelpFinder)
ON_COMMAND(ID_WINDOW_MANAGER, &CMainFrame::OnWindowManager)
ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnApplicationLook)
ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnUpdateApplicationLook)
ON_UPDATE_COMMAND_UI(ID_EDIT_BACK,&CMainFrame::ButtonEnable)
ON_UPDATE_COMMAND_UI(ID_EDIT_FORWARD,&CMainFrame::ButtonEnable)
ON_UPDATE_COMMAND_UI(ID_STATUSBAR_PANE1,&CMainFrame::ButtonEnable)
ON_COMMAND(ID_VIEW_CAPTION_BAR, &CMainFrame::OnViewCaptionBar)
ON_UPDATE_COMMAND_UI(ID_VIEW_CAPTION_BAR, &CMainFrame::OnUpdateViewCaptionBar)
ON_COMMAND(ID_TOOLS_OPTIONS, &CMainFrame::OnOptions)
ON_COMMAND(ID_ADDR, &CMainFrame::OnAddr)
ON_MESSAGE(WM_NEWURL, &CMainFrame::OnNewUrl)
ON_COMMAND(ID_BUTTON18, &CMainFrame::OnZoom)
ON_WM_CLOSE()
ON_COMMAND(ID_BUTTON_SYSTEM, &CMainFrame::OnButtonSystem)
END_MESSAGE_MAP()
// CMainFrame 构造/析构
CMainFrame::CMainFrame()
{
// TODO: 在此添加成员初始化代码
theApp.m_nAppLook = theApp.GetInt(_T("ApplicationLook"), ID_VIEW_APPLOOK_OFF_2007_BLUE);
isBack=isForward=FALSE;
}
CMainFrame::~CMainFrame()
{
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIFrameWndEx::OnCreate(lpCreateStruct) == -1)
return -1;
BOOL bNameValid;
// 基于持久值设置视觉管理器和样式
OnApplicationLook(theApp.m_nAppLook);
CMDITabInfo mdiTabParams;
mdiTabParams.m_style = CMFCTabCtrl::STYLE_3D_ONENOTE; // 其他可用样式...
mdiTabParams.m_bActiveTabCloseButton = TRUE; // 设置为 FALSE 会将关闭按钮放置在选项卡区域的右侧
mdiTabParams.m_bTabIcons = TRUE; // 设置为 TRUE 将在 MDI 选项卡上启用文档图标
mdiTabParams.m_bAutoColor = TRUE; // 设置为 FALSE 将禁用 MDI 选项卡的自动着色
mdiTabParams.m_bDocumentMenu = TRUE; // 在选项卡区域的右边缘启用文档菜单
mdiTabParams.m_bEnableTabSwap = TRUE;
EnableMDITabbedGroups(TRUE, mdiTabParams);
m_wndRibbonBar.Create(this);
m_wndRibbonBar.LoadFromResource(IDR_RIBBON);
if (!m_wndStatusBar.Create(this))
{
TRACE0("未能创建状态栏\n");
return -1; // 未能创建
}
CString strTitlePane1;
CString strTitlePane2;
bNameValid = strTitlePane1.LoadString(IDS_STATUS_PANE1);
ASSERT(bNameValid);
bNameValid = strTitlePane2.LoadString(IDS_STATUS_PANE2);
ASSERT(bNameValid);
StatusBar=new CMFCRibbonLabel(strTitlePane1,FALSE);
ProgressBar=new CMFCRibbonProgressBar(ID_STATUSBAR_PROGRESS,160);
m_wndStatusBar.AddDynamicElement(StatusBar);
m_wndStatusBar.AddExtendedElement(ProgressBar,L"进度");
m_wndStatusBar.AddSeparator();
m_wndStatusBar.AddExtendedElement(new CMFCRibbonStatusBarPane(ID_STATUSBAR_PANE2, strTitlePane2, TRUE), strTitlePane2);
// 启用 Visual Studio 2005 样式停靠窗口行为
CDockingManager::SetDockingMode(DT_SMART);
// 启用 Visual Studio 2005 样式停靠窗口自动隐藏行为
EnableAutoHidePanes(CBRS_ALIGN_ANY);
// 创建标题栏:
if (!CreateCaptionBar())
{
TRACE0("未能创建标题栏\n");
return -1; // 未能创建
}
// 启用增强的窗口管理对话框
EnableWindowsDialog(ID_WINDOW_MANAGER, ID_WINDOW_MANAGER, TRUE);
// 将文档名和应用程序名称在窗口标题栏上的顺序进行交换。这
// 将改进任务栏的可用性,因为显示的文档名带有缩略图。
ModifyStyle(0, FWS_PREFIXTITLE);
return 0;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CMDIFrameWndEx::PreCreateWindow(cs) )
return FALSE;
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式
return TRUE;
}
BOOL CMainFrame::CreateCaptionBar()
{
if (!m_wndCaptionBar.Create(WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, this, ID_VIEW_CAPTION_BAR, -1, TRUE))
{
TRACE0("未能创建标题栏\n");
return FALSE;
}
BOOL bNameValid;
CString strTemp, strTemp2;
bNameValid = strTemp.LoadString(IDS_CAPTION_BUTTON);
ASSERT(bNameValid);
m_wndCaptionBar.SetButton(strTemp, ID_TOOLS_OPTIONS, CMFCCaptionBar::ALIGN_LEFT, FALSE);
bNameValid = strTemp.LoadString(IDS_CAPTION_BUTTON_TIP);
ASSERT(bNameValid);
m_wndCaptionBar.SetButtonToolTip(strTemp);
bNameValid = strTemp.LoadString(IDS_CAPTION_TEXT);
ASSERT(bNameValid);
m_wndCaptionBar.SetText(strTemp, CMFCCaptionBar::ALIGN_LEFT);
m_wndCaptionBar.SetBitmap(IDB_INFO, RGB(255, 255, 255), FALSE, CMFCCaptionBar::ALIGN_LEFT);
bNameValid = strTemp.LoadString(IDS_CAPTION_IMAGE_TIP);
ASSERT(bNameValid);
bNameValid = strTemp2.LoadString(IDS_CAPTION_IMAGE_TEXT);
ASSERT(bNameValid);
m_wndCaptionBar.SetImageToolTip(strTemp, strTemp2);
return TRUE;
}
// CMainFrame 诊断
#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
CMDIFrameWndEx::AssertValid();
}
void CMainFrame::Dump(CDumpContext& dc) const
{
CMDIFrameWndEx::Dump(dc);
}
#endif //_DEBUG
// CMainFrame 消息处理程序
void CMainFrame::OnWindowManager()
{
ShowWindowsDialog();
}
void CMainFrame::OnApplicationLook(UINT id)
{
CWaitCursor wait;
theApp.m_nAppLook = id;
switch (theApp.m_nAppLook)
{
case ID_VIEW_APPLOOK_WIN_2000:
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManager));
m_wndRibbonBar.SetWindows7Look(FALSE);
break;
case ID_VIEW_APPLOOK_OFF_XP:
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOfficeXP));
m_wndRibbonBar.SetWindows7Look(FALSE);
break;
case ID_VIEW_APPLOOK_WIN_XP:
CMFCVisualManagerWindows::m_b3DTabsXPTheme = TRUE;
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
m_wndRibbonBar.SetWindows7Look(FALSE);
break;
case ID_VIEW_APPLOOK_OFF_2003:
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2003));
CDockingManager::SetDockingMode(DT_SMART);
m_wndRibbonBar.SetWindows7Look(FALSE);
break;
case ID_VIEW_APPLOOK_VS_2005:
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005));
CDockingManager::SetDockingMode(DT_SMART);
m_wndRibbonBar.SetWindows7Look(FALSE);
break;
case ID_VIEW_APPLOOK_VS_2008:
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2008));
CDockingManager::SetDockingMode(DT_SMART);
m_wndRibbonBar.SetWindows7Look(FALSE);
break;
case ID_VIEW_APPLOOK_WINDOWS_7:
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows7));
CDockingManager::SetDockingMode(DT_SMART);
m_wndRibbonBar.SetWindows7Look(TRUE);
break;
default:
switch (theApp.m_nAppLook)
{
case ID_VIEW_APPLOOK_OFF_2007_BLUE:
CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue);
break;
case ID_VIEW_APPLOOK_OFF_2007_BLACK:
CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_ObsidianBlack);
break;
case ID_VIEW_APPLOOK_OFF_2007_SILVER:
CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Silver);
break;
case ID_VIEW_APPLOOK_OFF_2007_AQUA:
CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Aqua);
break;
}
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007));
CDockingManager::SetDockingMode(DT_SMART);
m_wndRibbonBar.SetWindows7Look(FALSE);
}
RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW | RDW_FRAME | RDW_ERASE);
theApp.WriteInt(_T("ApplicationLook"), theApp.m_nAppLook);
}
void CMainFrame::OnUpdateApplicationLook(CCmdUI* pCmdUI)
{
pCmdUI->SetRadio(theApp.m_nAppLook == pCmdUI->m_nID);
}
void CMainFrame::OnViewCaptionBar()
{
m_wndCaptionBar.ShowWindow(m_wndCaptionBar.IsVisible() ? SW_HIDE : SW_SHOW);
RecalcLayout(FALSE);
}
void CMainFrame::OnUpdateViewCaptionBar(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_wndCaptionBar.IsVisible());
}
void CMainFrame::OnOptions()
{
CMFCRibbonCustomizeDialog *pOptionsDlg = new CMFCRibbonCustomizeDialog(this, &m_wndRibbonBar);
ASSERT(pOptionsDlg != NULL);
pOptionsDlg->DoModal();
delete pOptionsDlg;
}
void CMainFrame::OnAddr()
{
CMFCRibbonEdit *pEdit=DYNAMIC_DOWNCAST(CMFCRibbonEdit, m_wndRibbonBar.FindByID(ID_ADDR)); //获取地址输入框
CString strUrl=pEdit->GetEditText(); //获取地址框文本
if(strUrl=="") //数据合法性判断
MessageBox(L"请输入要访问的网址!",L"提示",MB_ICONWARNING);
else
{
CChildFrame *pChildFrame=(CChildFrame*)GetActiveFrame();
CHtmlView *pBrowser=(CHtmlView*)pChildFrame->GetActiveView();
if(pBrowser->GetLocationURL()!=strUrl) pBrowser->Navigate(strUrl);
}
}
void CMainFrame::ChangeAddr(CString str)
{ //修改地址输入框文本
CMFCRibbonEdit *pEdit=DYNAMIC_DOWNCAST(CMFCRibbonEdit, m_wndRibbonBar.FindByID(ID_ADDR));
pEdit->SetEditText(str);
}
double CMainFrame::GetZoom()
{ //获取滑块的值
CMFCRibbonSlider *pSlider=DYNAMIC_DOWNCAST(CMFCRibbonSlider, m_wndRibbonBar.FindByID(ID_SLIDER2));
return (pSlider->GetPos())/10.0;
}
void CMainFrame::SetStatusText(LPCTSTR str)
{ //设置状态栏文本(有Bug)
CString tmp=str;
static BOOL isFinish=TRUE;
if(StatusBar&&!tmp.IsEmpty()&&isFinish) StatusBar->SetText(str);
isFinish=tmp.Find(L"完成",0);
}
void CMainFrame::SetProgress(long value,long max)
{ //设置进度条
if(ProgressBar)
{
ProgressBar->SetRange(0,max);
ProgressBar->SetPos(value);
}
}
afx_msg LRESULT CMainFrame::OnNewUrl(WPARAM wParam, LPARAM lParam)
{ //CHtmlView类打开了新窗口
LPDISPATCH* ppDispatch=(LPDISPATCH*)wParam;
SendMessage(WM_COMMAND, ID_FILE_NEW, 0);
CChildFrame* pChildFrame = (CChildFrame*)GetActiveFrame();
*ppDispatch=((CHtmlView*)pChildFrame->GetActiveView())->GetApplication();
return 0;
}
void CMainFrame::OnZoom()
{
}
void CMainFrame::OnClose()
{ //处理WM_CLOSE
CCloseDlg closeDlg;
UINT r=closeDlg.DoModal(); //打开关闭对话框
if(r==IDALL) CMDIFrameWndEx::OnClose();
else if(r==IDCUR) GetActiveFrame()->DestroyWindow();
}
void CMainFrame::SetButtonState(BOOL sForward,BOOL sBack)
{ //接收后退、前进按钮状态
isBack=sBack;
isForward=sForward;
}
void CMainFrame::ButtonEnable(CCmdUI *pCmdUI)
{ //设置按钮可用
if(pCmdUI->m_nID==ID_EDIT_FORWARD) pCmdUI->Enable(isForward);
else if(pCmdUI->m_nID==ID_EDIT_BACK) pCmdUI->Enable(isBack);
else pCmdUI->Enable(TRUE);
}
void CMainFrame::OnButtonSystem()
{ //打开系统信息
ShellAbout(this->m_hWnd,L"Crazy Urus 浏览器",L"Crazy Urus 浏览器\n\r作者:廖星(Crazy Urus)",AfxGetApp()->LoadIcon(IDR_MAINFRAME));
}