一、 简单浏览器的实现
MFC提供了一个类CHtmlView来实现简单的浏览器,这个浏览器采用的内核是IE内核。一个浏览器通常包括几个部分:HTTP控制,HTML解释器,HTML执行器和应用界面控制。下面简单介绍下CHtmlView这个类的一些函数:
GetLocationName:得到站点名称
GetOffline:判断是否离线
SetOffline:设置是否离线浏览
GetLocationURL:得到站点的URL
GetFullName:得到浏览器的完整路径名称
GetType:得到当前页面类型
Navigate:浏览当前URL文件
Navigate2: 浏览当前URL文件或者全路径表明的文件
GoBack:在历史记录的前一项
GoForward:后一项
GoHome:回到主页
GoSearch:搜索
Refresh:刷新
Stop:停止浏览
如何设计一个简单的浏览器,下面进行介绍:
新建一个MFC工程,从单文档,从CHTMLVIEW派生,那么MFC会自动给你完成很多初始化的工作。然后在工具栏上添加一些按钮:后退,前进,停止,刷性等,添加一个地址栏,这些都在OnCreate函数中创建。具体的代码如下:
CImageList img;
CString str;
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndReBar.Create(this))
{
AfxMessageBox("Error in create toolbar");
return -1; // fail to create
}
if (!m_wndToolBar.CreateEx(this))
{
AfxMessageBox("Error in create toolbar");
return -1; // fail to create
}
//设置工具栏属性
m_wndToolBar.GetToolBarCtrl().SetButtonWidth(20, 100);
m_wndToolBar.GetToolBarCtrl().SetExtendedStyle(TBSTYLE_EX_DRAWDDARROWS);
img.Create(IDB_BITMAP1, 22, 0, RGB(255, 0, 255));
m_wndToolBar.GetToolBarCtrl().SetHotImageList(&img);
img.Detach();
img.Create(IDB_BITMAP2, 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, 6);
//设置每个工具栏按钮
m_wndToolBar.SetButtonInfo(0, ID_GO_BACK, TBSTYLE_BUTTON, 0);
str.LoadString(IDS_GO_BACK);
m_wndToolBar.SetButtonText(0, str);
m_wndToolBar.SetButtonInfo(1, ID_GO_FORWARD, TBSTYLE_BUTTON, 1);
str.LoadString(IDS_GO_FORWARD);
m_wndToolBar.SetButtonText(1, str);
m_wndToolBar.SetButtonInfo(2, ID_GO_STOP, TBSTYLE_BUTTON, 2);
str.LoadString(IDS_GO_STOP);
m_wndToolBar.SetButtonText(2, str);
m_wndToolBar.SetButtonInfo(3, ID_GO_REFRESH, TBSTYLE_BUTTON, 3);
str.LoadString(IDS_REFRESH);
m_wndToolBar.SetButtonText(3, str);
m_wndToolBar.SetButtonInfo(4, ID_START_PAGE, TBSTYLE_BUTTON, 4);
str.LoadString(IDS_STARTPAGE);
m_wndToolBar.SetButtonText(4, str);
m_wndToolBar.SetButtonInfo(5, ID_GO_SERACH, TBSTYLE_BUTTON, 5);
str.LoadString(IDS_SEARCH);
m_wndToolBar.SetButtonText(5, 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))
{
AfxMessageBox("Failed to create combobox/n");
return -1; // fail to create
}
//添加工具条,地址条到rebar中
m_wndReBar.AddBar(&m_wndToolBar);
str.LoadString(IDS_ADDRESS);
m_wndReBar.AddBar(&m_wndAddress, str, NULL, RBBS_FIXEDBMP | RBBS_BREAK);
// 设定Rebar中的每个尺寸
REBARBANDINFO rbbi;
rbbi.cbSize = sizeof(rbbi);
rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_SIZE;
rbbi.cxMinChild = rectToolBar.Width();
rbbi.cyMinChild = rectToolBar.Height();
rbbi.cx = rbbi.cxIdeal = rectToolBar.Width() * 9;
m_wndReBar.GetReBarCtrl().SetBandInfo(0, &rbbi);
rbbi.cxMinChild = 0;
CRect rectAddress;
rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEALSIZE;
m_wndAddress.GetEditCtrl()->GetWindowRect(&rectAddress);
rbbi.cyMinChild = rectAddress.Height() + 10;
rbbi.cxIdeal = 200;
m_wndReBar.GetReBarCtrl().SetBandInfo(2, &rbbi);
m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_FIXED);
然后对每一个新建的按钮ID关联一个函数进行响应即可,调用Navigate函数,GoBack函数等。
二、 删除IE相关历史记录
IE的历史记录是由注册表来管理的和维护的,包括Cookies记录、Internet临时文件、地址栏历史记录等、上网密码历史记录和收藏夹历史记录等。
CSIDL解决了一些跨系统的问题,因为在不同的系统中文件夹存放的位置是不一样的,但是CSIDL提供了一种与操作系统无关的,表示特定文件夹路径和名字的方式。
CSIDL_COOKIES: cookies的文件系统路径
CSIDL_DESKTOPDIRECTORY: 桌面路径
CSIDL_NETWORK: 网上邻居的虚拟文件夹
CSIDL_RECENT: 最近使用的文档的文件系统路径
CSIDL_STRATUP: 开始程序组的文件系统路径
CSIDL_SYSTEM: 系统文件夹
CSIDL_WINDOWS: Windows目录
CSIDL_TEMPLATES: 临时文件夹
CSIDL_HISTORY: Internet历史记录
CSIDL_FAVORITES: 收藏夹文件路径
//浏览器地址栏历史地址的清除
SHDeleteKey(HKEY_CURRENT_USER, _T("Software//Microsoft//Internet Explorer//TypedURLs"));
// 清除自动密码历史记录
SHDeleteKey(HKEY_CURRENT_USER, _T("Software//Microsoft//Internet Explorer//IntelliForms"));
//清收藏夹中的内容
TCHAR szPath[MAX_PATH];
if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_FAVORITES, FALSE))
{ //得到目录,并清空
EmptyDirectory(szPath);
}
//清空Internet临时文件
TCHAR szPath[MAX_PATH];
DeleteUrlCache(File);//删除cache
if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_INTERNET_CACHE, FALSE))
{ //得到临时目录,并清空它.
EmptyDirectory(szPath);
}
//清空Internet cookies文件
TCHAR szPath[MAX_PATH];
DeleteUrlCache(Cookie);
if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_COOKIES, FALSE))
{//得到目录,并清空
EmptyDirectory(szPath);
}
//删除文档历史记录
TCHAR szPath[MAX_PATH];
if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_RECENT, FALSE))
{
EmptyDirectory(szPath);
}
SHDeleteKey(HKEY_CURRENT_USER,_T("Software//Microsoft//Windows//CurrentVersion//Explorer//RecentDocs"));
BOOL DeleteUrlCache(DEL_CACHE_TYPE type)
{
BOOL bRet = FALSE;
HANDLE hEntry;
LPINTERNET_CACHE_ENTRY_INFO lpCacheEntry = NULL;
DWORD dwEntrySize;
//delete the files
dwEntrySize = 0;
hEntry = FindFirstUrlCacheEntry(NULL, NULL, &dwEntrySize);
lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwEntrySize];
hEntry = FindFirstUrlCacheEntry(NULL, lpCacheEntry, &dwEntrySize);
if (!hEntry)
{
goto cleanup;
}
do
{
if (type == File && !(lpCacheEntry->CacheEntryType & COOKIE_CACHE_ENTRY))
{
DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName);
}
else if (type == Cookie && (lpCacheEntry->CacheEntryType & COOKIE_CACHE_ENTRY))
{
DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName);
}
dwEntrySize = 0;
FindNextUrlCacheEntry(hEntry, NULL, &dwEntrySize);
delete [] lpCacheEntry;
lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwEntrySize];
}
while (FindNextUrlCacheEntry(hEntry, lpCacheEntry, &dwEntrySize));
bRet = TRUE;
cleanup:
if (lpCacheEntry)
{
delete [] lpCacheEntry;
}
return bRet;
}
三、 将应用程序加入IE工具栏
IE工具栏在注册表里面也可以进行管理,要实现在IE工具栏上加入自己定义的图标,则需要向注册表中的IE工具栏的位置写入一些注册表项即可。
void AddToToolBar ()
{
CString valuename;
CString filename;
CString pathname;
HICON smalls;
HICON larges;
GetDlgItemText(IDC_EDIT1,pathname); //得到路径名
GetDlgItemText(IDC_EDIT2,filename); //得到文件名
//得到程序中所有图标资源ID
FindIconID(pathname);
//显示大图标和小图标
ExtractIconEx(LPCSTR(filename),0,&larges,&smalls,1);
m_BigIconButton.SetIcon(larges);
m_SmallIconButton.SetIcon(smalls);
filename.TrimRight(".exe");
if(filename.IsEmpty())
{
AfxMessageBox("请首先选择添加的程序");
return;
}
//生成GUID,该GUID作为键名
UUID Uuid;
UCHAR * stringUuid;
UuidCreate(&Uuid);
UuidToString(&Uuid,&stringUuid);
valuename=stringUuid;
RpcStringFree(&stringUuid);
valuename=CString("{")+valuename+"}";
//写注册表
AddEventSource(valuename,pathname,filename);
}
Void AddEventSource(CString keyname,CString pathname,CString filename)
{
HKEY hk;
CString buffer;
CString CLSID="{1FBA04EE-3024-11D2-8F1F-0000F87ABD16}";
if (RegCreateKey(HKEY_LOCAL_MACHINE,
"Software//Microsoft//Internet Explorer//Extensions//"+keyname,&hk)!=ERROR_SUCCESS)
{
AfxMessageBox("Cannot Create Key !");
return;
}
// button text
buffer="ButtonText";
if (RegSetValueEx(hk, // subkey handle
buffer, // value name
0, // must be zero
REG_SZ, // value type
(CONST BYTE *)((LPCSTR)filename), // pointer to value data
filename.GetLength())!=ERROR_SUCCESS) // length of value data
{
AfxMessageBox("Cannot Set Value");
}
//CLSID
if (RegSetValueEx(hk, // subkey handle
"CLSID", // value name
0, // must be zero
REG_SZ, // value type
(CONST BYTE *)((LPCSTR)CLSID), // pointer to value data
CLSID.GetLength())!=ERROR_SUCCESS) // length of value data
{
AfxMessageBox("Cannot Set Value");
}
// Default visible
buffer="Yes";
if (RegSetValueEx(hk, // subkey handle
"Default visible", // value name
0, // must be zero
REG_SZ, // value type
(CONST BYTE *)((LPCSTR)buffer), // pointer to value data
buffer.GetLength())!=ERROR_SUCCESS) // length of value data
{
AfxMessageBox("Cannot Set Value !");
}
// Exec
if (RegSetValueEx(hk, // subkey handle
"Exec", // value name
0, // must be zero
REG_SZ, // value type
(CONST BYTE *)((LPCSTR)pathname), // pointer to value data
pathname.GetLength())!=ERROR_SUCCESS) // length of value data
{
AfxMessageBox("Cannot Set Value !");
}
// HotIcon
CString hotIconPath;
if(g_IconIDList.GetSize()!=0)
hotIconPath = pathname + g_IconIDList[g_IconIDList.GetSize()-1];
else
hotIconPath=pathname;
if (RegSetValueEx(hk, // subkey handle
"HotIcon", // value name
0, // must be zero
REG_SZ, // value type
(CONST BYTE *)((LPCSTR)hotIconPath), // pointer to value data
hotIconPath.GetLength())!=ERROR_SUCCESS) // length of value data
{
AfxMessageBox("Cannot Set Value !");
}
// Icon
CString iconPath;
if(g_IconIDList.GetSize()!=0)
iconPath=pathname+g_IconIDList[0];
else
iconPath=pathname;
if (RegSetValueEx(hk, // subkey handle
"Icon", // value name
0, // must be zero
REG_SZ, // value type
(CONST BYTE *)((LPCSTR)iconPath), // pointer to value data
iconPath.GetLength())!=ERROR_SUCCESS) // length of value data
{
AfxMessageBox("Cannot Set Value !");
}
// MenuStatusBar
if (RegSetValueEx(hk, // subkey handle
"MenuStatusBar", // value name
0, // must be zero
REG_SZ, // value type
(CONST BYTE *)((LPCSTR)filename), // pointer to value data
filename.GetLength())!=ERROR_SUCCESS) // length of value data
{
AfxMessageBox("Cannot Set Value !");
}
// MenuText
if (RegSetValueEx(hk, // subkey handle
"MenuText", // value name
0, // must be zero
REG_SZ, // value type
(CONST BYTE *)((LPCSTR)filename), // pointer to value data
filename.GetLength())!=ERROR_SUCCESS) // length of value data
AfxMessageBox("Cannot Set Value !");
RegCloseKey(hk);
}
四、 超级链接的实现
成员变量和成员函数:
COLORREF m_InitColor; //文本初始颜色
COLORREF m_VisitedColor; //文本被访问过后的颜色
COLORREF m_CoverColor; //鼠标悬浮在文本上方时的颜色
BOOL m_bAboveControl; // 是否鼠标移到控件上
BOOL m_bVisited; // 是否被访问
BOOL m_bUnderLine; // 是否有下划线
CString m_sURL; // URL或者应用程序的位置
CFont m_Font; // 设定字体
HCURSOR m_hLinkCursor; // 光标
void SetAttribute(CString url="www.xici.net",COLORREF InitColor=RGB(0,0,255), COLORREF VisitedColor=RGB(255,0,0), COLORREF CoverColor=RGB(125,125,0),BOOL bUnderLine=TRUE);
BOOL OpenUsingShellExecute();
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
五、 禁止IE的弹出窗口
六、 禁止浏览某些网站
上面两节由于涉及到COM和ATL的相关知识,在这里不进行介绍。
七、 IE收藏夹
首先调用Shell API函数SHGetSpecialFolder,其中CSIDL为CSIDL_FAVORITES,得到了收藏夹的路径,然后扫描该路径下的所有文件,得到一个文件列表,然后在程序中对文件进行响应。
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[400];
CStringArray astrFavorites;
CStringArray astrDirs;
CMenu* pSubMenu;
// 确定有'//'字符
if(strPath[strPath.GetLength() - 1] != _T('//'))
strPath += _T('//');
strPath2 = strPath;
strPath += "*.*";.
// 首先扫描.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"))
{
// 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, 400,
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;
}