分类: C/C++
2008-02-15 10:16:02
在 VCKBASE 混了这么久竟然没有写出一篇文章,想想很是惭愧,每当在这里看到一篇好文,这种感觉尤甚,总结我在程序员加油站中的一些技术点写了这个文章(虽然程序员加油站还要继续开发,但是由于时间关系不知道什么时候能完成),如果有时间我还会写一些文章的,我的写作水平可能很差,希望读者能够包涵。
程序原理:
一、在IE菜单中加入菜单项
在注册表HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt项下建立一个新项,项的名称即为出现在菜单中的标题
将新建项的默认值设定为一个URL地址,当用户点击菜单项后,IE就会调用URL指向的页面中的脚本。
二、如何控制菜单项在合适的时候显示
下面再介绍一下上面注册项中Contexts项的作用,通过该项可以制定菜单项在右键点击IE中的什么对象时出现,它可以为以下值的“或”组合
对象 | 值 |
缺省 | 0x1 |
图片 | 0x2 |
控件 | 0x4 |
表单域 | 0x8 |
选择文本 | 0x10 |
锚点 | 0x20 |
超链接 | 0x22 |
例如上面我们希望菜单项在用户点击图片或者超链接时出现,那么我们就将值设置为
dword:00000022
既在点击图片 或者 锚点时出现菜单。一个锚点是页面中描述一个超链接的对象。如果不设置Contexts 项,则菜单项会在点击任何对象时出现在右键菜单中。
注:
一二部分我引用了《如何在IE右键菜单中添加菜单项以及如何添加IE任务栏按钮》这篇文章的部分内容,详细内容请看:
http://www.csdn.net/develop/read_article.asp?id=3621
三、编辑点击菜单项执行的script脚本
这个脚本的文件名和1中的链接文件一致这个是我用的脚本:
//看到网海拾贝中这样用四、在注册表中加入
实现如下:
STDMETHODIMP Ctesta::GetHtmlText() { //保存网页内容的目录 char chFilePath[MAX_PATH]; DWORD Number = 0; CRegistry reg; reg.Open(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\程序员加油站\\"); BOOL ret = reg.ReadDWORD("ArticleNumber",&Number); if(!ret) return S_FALSE; //读取保存网页文件的目录 ret = reg.ReadString("ArticlePath",chFilePath); if(!ret) return S_FALSE; //取得当前活动窗口的窗口句柄 HWND hWnd = GetActiveWindow(); CoInitialize( NULL ); //显式装载 MSAA 判断是否被安装 HINSTANCE hInst = ::LoadLibrary( _T("OLEACC.DLL") ); if ( hInst != NULL ) { if ( hWnd != NULL ) { HWND hWndChild=NULL; // 取得当前窗口的IE子窗口指针 ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild ); if ( hWndChild ) { //定义IE文档 CComPtr在取得选取网页内容之后,需要对HTML内容进行重新编辑以获得正确的显示,CheckData函数便是做这个工作的这个函数对HTML内容中图像信息的地址进行编辑,如果图像保存在本地则使用本地图像,如果图像没有下载保持原样。pHTMLDoc; LRESULT lRes; //由于WM_HTML_GETOBJECT非Windows标准消息,所以需要RegisterWindowMessage UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") ); ::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes ); LPFNOBJECTFROMLRESULT pfObjectFromLresult = (LPFNOBJECTFROMLRESULT)::GetProcAddress( hInst, _T("ObjectFromLresult") ); if ( pfObjectFromLresult != NULL ) { HRESULT hr; //获取网页的IHTMLDocument2接口 hr = (*pfObjectFromLresult)( lRes, IID_IHTMLDocument, 0, (void**)&pHTMLDoc ); if ( SUCCEEDED(hr) ) { CComPtr pSelObj; CComPtr pTxtRange; //根据IHTMLDocument2指针取得IHTMLSelectionObject接口指针 pHTMLDoc->get_selection(&pSelObj); //再获得IHTMLTxtRange指针 hr = pSelObj->createRange((IDispatch**)&pTxtRange); if(!CheckResult(hr,"pTxtRange")) return hr; //选择所有被选择的内容 pTxtRange->select(); BSTR bstrTxt,bstrTxt1; char strPath[MAX_PATH]; char *strTxt = NULL; char*strTxt1 = NULL; //取得主站域名 CComPtr pLocation; pHTMLDoc->get_location(&pLocation); pLocation->get_hostname(&bstrTxt1); strTxt1 = _com_util::ConvertBSTRToString(bstrTxt1); sprintf(strPath,"http://%s",strTxt1); SaveCharToFile(strTxt1,debugpath); //取得选中的内容 pTxtRange->get_htmlText(&bstrTxt); strTxt = _com_util::ConvertBSTRToString(bstrTxt); //下载内容中的图片资源,并修改相应链接 std::string webpage; char chSavePath[MAX_PATH]; sprintf(chSavePath,"%s\\T%ld.htm",chFilePath,Number); CreateAllDirectory(chSavePath); //取得所有图片资源并保存网页 if(CheckData(strTxt,strPath,chFilePath,Number,webpage) == FALSE) SaveCharToFile(strTxt,chSavePath,TRUE); else SaveCharToFile(webpage.c_str(),chSavePath,TRUE); BOOL ret = reg.WriteDWORD("ArticleNumber",++Number); //释放内存 if(strTxt1) delete[] strTxt1; if(strTxt) delete[] strTxt; SysFreeString(bstrTxt1); // 用完释放 SysFreeString(bstrTxt); // 用完释放 } } } } // else Internet Explorer is not running ::FreeLibrary( hInst ); } // else Active Accessibility is not installed CoUninitialize(); return S_OK; }
BOOL CheckData(const LPCTSTR data, const LPCTSTR host, const LPCTSTR path, DWORD Number, std::string &outstring) { char chImgPath[1024];//图像路径 !:由于有些图像路径可能会很长所以申请内存多一点 char chImgSrc[MAX_PATH];//图像地址 char chDownLoadPath[MAX_PATH];//下载图像文件路径 char chWriteImgSrc[MAX_PATH];//图像文件路径 memset(chImgPath,0,1024); memset(chImgSrc,0,MAX_PATH); memset(chDownLoadPath,0,MAX_PATH); memset(chWriteImgSrc,0,MAX_PATH); char dirname[20];//根目录名 ltoa(Number,dirname,10); try{ //查找是否有"); if(p1 == NULL||p2 == NULL||p3 == NULL||p4 == NULL) return FALSE; //找到一个图像文件标记 //拷贝图像链接之前的文字 int n = p4-p1+1; strncpy(chImgPath,p1,n); outstring.append(data,p2-data+5); //提取图像链接 n = p3-p2-5; strncpy(chImgSrc,p2+5,n); if(FindString(chImgSrc,"http://") == NULL){ if(FindString(chImgSrc,"..")) strcpy(chImgSrc,&chImgSrc[2]); sprintf(chDownLoadPath,"%s%s",host,chImgSrc); sprintf(chWriteImgSrc,"%s//%s%s",path,dirname,chImgSrc); }else{ strcpy(chDownLoadPath,chImgSrc); const char *p5 = FindString(chImgSrc+7,"/"); sprintf(chWriteImgSrc,"%s\\%s%s",path,dirname,&chImgSrc[p5-chImgSrc]); } char Output[MAX_PATH]; sprintf(Output,"图像地址:%s\r\n存盘地址:%s\r\n主机地址:%s\r\n",chImgSrc,chWriteImgSrc,host); SaveCharToFile(Output,debugpath); n = strlen(chWriteImgSrc); for(int i=0;i其他几个辅助函数这里简单介绍,详细内容请参看源代码
函数:void SaveCharToFile 功能:将字符串保存为给定文件名 const LPCTSTR data,//[IN] 给定待保存的数据 const LPCTSTR saveFileName,//[IN]给定文件名 BOOL flag = FALSE//[IN]追加写入还是覆盖标志 函数:const char *FindString 功能:在给定字符串中查找给定字符串 const LPCTSTR source,//[IN] 给定源字符串的数据 const LPCTSTR key)//[IN]待查字符串 函数:void CreateAllDirectory 功能:创建给定路径的所有未建目录 const char* AllPath)//[IN] 需要创建的详细目录 例如 输入为:"d:\a\b\c\d"则在D盘下创建相应a,b,c,d相应目录好了,到此为止,我们已经做成一个取得网页选取内容的并保存在本地的程序,你可以举一反三,将它应用到更有趣更有用的领域。
这个程序是我研究了一周才写完的,其中取得domument的方法我觉得很笨,可我现在没有找到好办法,希望能够抛砖引玉,有更好的方法别忘了告诉我,我的Email:lgtest@sina.com欢迎来信讨论。