当前位置:首页 > 工业控制 > 电子设计自动化
[导读]前言 IE浏览器作为微软Windows系统捆绑销售的一个浏览工具,用来浏览千姿百态的网页,目前它已经占据了浏览器市场的半壁江山,成为Windows用户不可或缺的工具。首先,它的界面设计的很漂亮,如扁平按纽(按钮上的图像

前言

IE浏览器作为微软Windows系统捆绑销售的一个浏览工具,用来浏览千姿百态的网页,目前它已经占据了浏览器市场的半壁江山,成为Windows用户不可或缺的工具。首先,它的界面设计的很漂亮,如扁平按纽(按钮上的图像为灰色,当鼠标放在按钮上时,按钮突起,这种状态称为手柄,并且其上的图像变得鲜艳醒目)、按钮上的文字说明以及按钮边 上的小黑三角形状的下拉箭头(单击时显示下拉菜单)、工具条上的地址输入栏等,都体现了Windows2000的风格;其次,它的收藏栏可以收藏用户喜爱的网络地 址,这一切都为IE的流行打下了坚实的基础。说了那么多,也许读者朋友们感觉到IE实现起来一定非常困难,其实IE也是个"纸老虎",实现它的难点主要是 在界面效果和显示收藏夹上,笔者在本文中有针对性的叙述了IE界面、收藏网页的显示、网页的浏览等功能的实现,仔细看过这篇文章后,相信读者朋友们一定可以打造出一个属于自己的浏览器。本文中的代码在Windows2000、Visual C++6.0环境下编译通过,程序运行正常。程序运行界面如下:


图一、浏览器的运行界面

一、浏览器的界面实现

首先启动Visual C++6.0,生成一个名为MYIE单文档项目,注意在此过程中不要选择工具条和状态条选项,这样才能更方便我们在后续工作中用代码实现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 rebar ");

return -1;

}

if (!m_wndToolBar.CreateEx(this)) //使用CreateEx()函数创建工具条对象;

{

TRACE0("Failed to create toolbar ");

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 |

BSTYLE_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 | BSTYLE_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 ");

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| BRS_FLYBY | CBRS_SIZE_FIXED);

//设置状态条;

if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators) / sizeof(UINT)))

{

TRACE0("Failed to create status bar ");

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

((CMYIEView*)GetActiveView())->Navigate2(str, 0, NULL);

}

二、实现收藏菜单

一般IE的用户都有个习惯,那就是将自己喜欢的网址保存起来,以方便今后快速的登陆,为了使我们的浏览器能够显示IE收藏过的网址,程序中设置了一个"Favorites"菜单,通过RegOpenKey()、RegQueryValueEx()等函数操作Windows的注册表中的HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionExplorerUser 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("SoftwareMicrosoftWindowsCurrentVersionExplorerUser Shell Folders"), &hKey) != ERROR_SUCCESS)

{

TRACE0("Favorites folder not found ");

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;

}

三、显示超文本

微软ChtmView类的Navigate2函数可以实现超文本文件的显示,GoBack()、GoForward()等函数可以分别实现网页浏览的回退和前进操作。以响应"Favorite"菜单项为例,需要在程序的CmainFrame类中添加消息映射 ON_COMMAND_RANGE(0xe00, 0xfff, OnFavorite)和消息响应函数OnFavorite,来响应ID为0xe00-0xfff范围内的菜单单击处理,具体实现代码如下:

void CMainFrame.:OnFavorite(UINT nID)

{

((CMYIEView*)GetActiveView())->Navigate2(m_astrFavoriteURLs[nID-0xe00],0,NULL);

}

四、小结

上面的代码相对较多,对某些函数的使用不清楚的话,请参考MSDN,它包含了高级界面处理、注册表的操作等内容,也许刚开始看起来可能感到有些困难,但是如果读者朋友细细品味的话,一定可以学到一些东西,对今后程序的界面开发有所帮助。



来源:Etta0次

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭