﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-yehao's Blog-文章分类-Windows编程</title><link>http://www.cppblog.com/yehao/category/16709.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 11 Jul 2014 14:51:39 GMT</lastBuildDate><pubDate>Fri, 11 Jul 2014 14:51:39 GMT</pubDate><ttl>60</ttl><item><title>VC使用IPicture显示网上图片(通过URL指定)</title><link>http://www.cppblog.com/yehao/articles/207615.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Fri, 11 Jul 2014 07:36:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/207615.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/207615.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/207615.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/207615.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/207615.html</trackback:ping><description><![CDATA[<div>转自http://blog.csdn.net/wallimn/article/details/3068643<br /><br /><div dp-highlighter"="" style="width: 700.90625px; color: #333333; line-height: 26px;">/************************************************************/<br />VC IPicture<br />显示网络图片　显示远程图片　显示URL指定的图片　<br />通过HTTP下载显示图片 显示网上广告图片<br />上面是我罗列的关键字，我找这个文章换了好几种关键字写法，才找到，<br />为了方便它人，我把关键字全部写上。<br />/************************************************************/</div><div dp-highlighter"="" style="width: 700.90625px; color: #333333; line-height: 26px;">文章很不错，正好解决了我的问题。感谢作者。这是个用SDK（没有使用MFC）开发的程序。<br />如果对SDK开发方式不是很熟，只看ShowPic函数就以了。</div><div dp-highlighter"="" style="width: 700.90625px; color: #333333; line-height: 26px;">转载文章，原文地址：<a href="http://www.blogjava.net/Unmi/archive/2007/12/02/164605.html" style="color: #336699; text-decoration: none;">http://www.blogjava.net/Unmi/archive/2007/12/02/164605.html</a></div><div dp-highlighter"="" style="width: 700.90625px; color: #333333; line-height: 26px;"><div dp-highlighter"="" style="width: 693.890625px;"><ol><li style="line-height: 18px;">#include&nbsp;&lt;windows.h&gt;&nbsp;&nbsp;//&nbsp;Windows&nbsp;SDK&nbsp;要用到的&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">#include&nbsp;&lt;commdlg.h&gt;&nbsp;&nbsp;//&nbsp;打开文件的窗口要包含这个头文件&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;</li><li style="line-height: 18px;">//用到了&nbsp;IPicture&nbsp;接口，要包含下面两个&nbsp;头文件&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">#include&nbsp;&lt;ocidl.h&gt;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">#include&nbsp;&lt;olectl.h&gt;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;</li><li style="line-height: 18px;">//&nbsp;声明窗口函数的原型&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">LRESULT&nbsp;CALLBACK&nbsp;MainWndProc&nbsp;(HWND,&nbsp;UINT,&nbsp;WPARAM,&nbsp;LPARAM);&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;</li><li style="line-height: 18px;">//&nbsp;声明显示图片的函数原型&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">HRESULT&nbsp;ShowPic(char&nbsp;*lpstrFile,HWND&nbsp;hWnd)&nbsp;;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;</li><li style="line-height: 18px;">//图片文件名&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">char&nbsp;lpstrFile[MAX_PATH]="";&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;</li><li style="line-height: 18px;">int&nbsp;WINAPI&nbsp;WinMain&nbsp;(HINSTANCE&nbsp;hThisInstance,&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HINSTANCE&nbsp;hPrevInstance,&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPSTR&nbsp;lpszArgument,&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;nFunsterStil)&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">{&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;窗口类名&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;szClassName[&nbsp;]&nbsp;=&nbsp;"ShowPicture";&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;WNDCLASSEX&nbsp;windclass;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;//用描述主窗口的参数填充&nbsp;WNDCLASSEX&nbsp;结构&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;windclass.cbSize&nbsp;=&nbsp;sizeof(windclass);&nbsp;&nbsp;//结构大小&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;windclass.hInstance&nbsp;=&nbsp;hThisInstance;&nbsp;&nbsp;&nbsp;//实例句酚&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;windclass.lpszClassName&nbsp;=&nbsp;szClassName;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;windclass.lpfnWndProc&nbsp;=&nbsp;MainWndProc;&nbsp;&nbsp;&nbsp;//窗口函数指针&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;windclass.style&nbsp;=&nbsp;CS_DBLCLKS;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//捕获双击事件&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;windclass.cbSize&nbsp;=&nbsp;sizeof&nbsp;(WNDCLASSEX);&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;windclass.hIcon&nbsp;=&nbsp;LoadIcon&nbsp;(NULL,&nbsp;IDI_APPLICATION);&nbsp;//使用预定义图标&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;windclass.hIconSm&nbsp;=&nbsp;LoadIcon&nbsp;(NULL,&nbsp;IDI_APPLICATION);&nbsp;//使用预定义类的小图标&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;windclass.hCursor&nbsp;=&nbsp;LoadCursor&nbsp;(NULL,&nbsp;IDC_ARROW);&nbsp;//使用预定义光标&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;windclass.lpszMenuName&nbsp;=&nbsp;NULL;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//不指定主菜单&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;windclass.cbClsExtra&nbsp;=&nbsp;0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//没有额外的类内存&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;windclass.cbWndExtra&nbsp;=&nbsp;0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//没有额外的窗口内存&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;windclass.hbrBackground&nbsp;=&nbsp;(HBRUSH)&nbsp;COLOR_BACKGROUND;&nbsp;//使用预定义背景画刷&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;//注册这个窗口类，如果失败直接退出程序&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!RegisterClassEx&nbsp;(&amp;windclass))&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;//创建主窗口&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;HWND&nbsp;hWnd&nbsp;=&nbsp;CreateWindowEx&nbsp;(&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//dwExStyle,&nbsp;扩展样式&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;szClassName,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//lpClassName,&nbsp;类名&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"显示图片&nbsp;--&nbsp;鼠标双击浏览图片文件&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&nbsp;Author:Unmi",&nbsp;//lpWindowName,&nbsp;标题&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WS_OVERLAPPEDWINDOW,&nbsp;//dwStyle,&nbsp;窗口风格&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CW_USEDEFAULT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//X,&nbsp;初始&nbsp;X&nbsp;坐标&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CW_USEDEFAULT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//Y,&nbsp;初始&nbsp;YX&nbsp;坐标&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;640,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//nWidth,&nbsp;宽度&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;480,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//nHeight,&nbsp;高度&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HWND_DESKTOP,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//hWndParent,&nbsp;父窗口句柄&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//hMenu,&nbsp;菜单句柄&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hThisInstance,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//hInstance,&nbsp;程序实例句柄&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//lpParam,&nbsp;用户数据&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;//显示窗口，刷新窗口客户区&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;ShowWindow&nbsp;(hWnd,&nbsp;nFunsterStil);&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;从消息队列中取出消息，交给窗口函数处理&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;直到&nbsp;GetMessage&nbsp;取出的消息是&nbsp;WM_QUIT，即FALSE,则结束消息循环&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;MSG&nbsp;messages;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(GetMessage&nbsp;(&amp;messages,&nbsp;NULL,&nbsp;0,&nbsp;0))&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//转换键盘消息，把虚拟键转换为字符消息&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TranslateMessage(&amp;messages);&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//将消息发送到相应的窗口函数&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DispatchMessage(&amp;messages);&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;GetMessage&nbsp;返回&nbsp;FALSE,程序结束&nbsp;PostQuitMessage()&nbsp;发出这一消息&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;messages.wParam;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">}&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;</li><li style="line-height: 18px;">//&nbsp;窗口函数，消息由&nbsp;DispatchMessage&nbsp;派发&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">LRESULT&nbsp;CALLBACK&nbsp;MainWndProc&nbsp;(HWND&nbsp;hWnd,&nbsp;UINT&nbsp;message,&nbsp;WPARAM&nbsp;wParam,&nbsp;LPARAM&nbsp;lParam)&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">{&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;switch&nbsp;(message)&nbsp;//处理消息&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;WM_DESTROY:&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//向消息队列投递一个&nbsp;WM_QUIT&nbsp;消息，促使&nbsp;GetMessage&nbsp;函数返回0，结束消息循环&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PostQuitMessage&nbsp;(0);&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;WM_LBUTTONDBLCLK:&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OPENFILENAME&nbsp;file&nbsp;=&nbsp;{0};&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.lStructSize&nbsp;=&nbsp;sizeof(file);&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.lpstrTitle&nbsp;=&nbsp;"请选择一个图片文件";&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.lpstrFile&nbsp;=&nbsp;lpstrFile;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.nMaxFile&nbsp;=&nbsp;MAX_PATH;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.lpstrFilter&nbsp;=&nbsp;"Pictures(*.jpg,*.gif,*.bmp)/0*.jpg;*.gif;*.bmp/0/0";&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(::GetOpenFileName(&amp;file))&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//清除原来的图像&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HDC&nbsp;hdc=GetDC(hWnd);&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RECT&nbsp;rect;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;::GetWindowRect(hWnd,&amp;rect);&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;::FillRect(hdc,&amp;rect,(HBRUSH)&nbsp;COLOR_BACKGROUND);&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;::SendMessage(hWnd,WM_PAINT,NULL,NULL);&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;WM_PAINT:&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowPic(lpstrFile,hWnd);&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;default:&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//将我们不处理的消息交给系统&nbsp;做默认处理&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;DefWindowProc&nbsp;(hWnd,&nbsp;message,&nbsp;wParam,&nbsp;lParam);&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">}&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">//&nbsp;显示图片,&nbsp;lpstrImgUrl&nbsp;为图片URL地址，hWnd&nbsp;为窗口句柄&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">HRESULT&nbsp;Utils::ShowPic(char&nbsp;*lpstrImgUrl,HWND&nbsp;hWnd)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;HDC&nbsp;hDC_Temp=GetDC(hWnd);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;IPicture&nbsp;*pPic;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;IStream&nbsp;*pStm;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;BOOL&nbsp;bResult;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;dwFileSize,dwByteRead;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;//读取网页上图片文件，实际是个CHttpFile指针&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;CInternetSession&nbsp;session("HttpClient");&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;CFile*&nbsp;httpFile&nbsp;=&nbsp;(CFile*)session.OpenURL(lpstrImgUrl);&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(httpFile!=INVALID_HANDLE_VALUE)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dwFileSize=&nbsp;&nbsp;httpFile-&gt;GetLength();//获取文件字节数&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(dwFileSize==0xFFFFFFFF)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;E_FAIL;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;E_FAIL;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;//分配全局存储空间&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;HGLOBAL&nbsp;hGlobal&nbsp;=&nbsp;GlobalAlloc(GMEM_MOVEABLE,&nbsp;dwFileSize);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;LPVOID&nbsp;pvData&nbsp;=&nbsp;NULL;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(hGlobal&nbsp;==&nbsp;NULL)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;E_FAIL;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;((pvData&nbsp;=&nbsp;GlobalLock(hGlobal))&nbsp;==&nbsp;NULL)//锁定分配内存块&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;E_FAIL;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;//把文件读入内存缓冲区&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;dwByteRead&nbsp;=&nbsp;httpFile-&gt;Read(pvData,dwFileSize);&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;GlobalUnlock(hGlobal);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;CreateStreamOnHGlobal(hGlobal,&nbsp;TRUE,&nbsp;&amp;pStm);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;//装入图形文件&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;bResult=OleLoadPicture(pStm,dwFileSize,TRUE,IID_IPicture,(LPVOID*)&amp;pPic);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;if(FAILED(bResult))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;E_FAIL;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;OLE_XSIZE_HIMETRIC&nbsp;hmWidth;&nbsp;//图片的真实宽度,&nbsp;单位为英寸&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;OLE_YSIZE_HIMETRIC&nbsp;hmHeight;&nbsp;//图片的真实高度,&nbsp;单位为英寸&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;pPic-&gt;get_Width(&amp;hmWidth);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;pPic-&gt;get_Height(&amp;hmHeight);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;//转换hmWidth和hmHeight为pixels距离，1英寸=25.4毫米&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;nWidth&nbsp;=&nbsp;MulDiv(hmWidth,GetDeviceCaps(hDC_Temp,LOGPIXELSX),2540);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;nHeight&nbsp;=&nbsp;MulDiv(hmHeight,GetDeviceCaps(hDC_Temp,LOGPIXELSY),2540);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;//将图形输出到屏幕上（有点像BitBlt）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;bResult=pPic-&gt;Render(hDC_Temp,0,0,nWidth,nHeight,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0,hmHeight,hmWidth,-hmHeight,NULL);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;pPic-&gt;Release();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;httpFile-&gt;Close();//关闭打开的文件&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(SUCCEEDED(bResult))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;S_OK;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;E_FAIL;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">}&nbsp;&nbsp;&nbsp;</li></ol></div><p>补充说明：<br />　　原文的程序是使用ＳＤＫ方式开发的，可能会有些人不习惯，我使用ＭＦＣ方式验证调试了一下，效果还不错。如需要源码的，请到<a href="http://wallimn.ys168.com/" style="color: #336699; text-decoration: none;">http://wallimn.ys168.com</a>（我的网络硬盘）下载。<br />　　我的程序是个很简单的程序，没有考虑重绘、图片大小的处理等问题，仅体现编程思想及方法。</p></div></div><img src ="http://www.cppblog.com/yehao/aggbug/207615.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2014-07-11 15:36 <a href="http://www.cppblog.com/yehao/articles/207615.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UAC的前世今生</title><link>http://www.cppblog.com/yehao/articles/207116.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Tue, 27 May 2014 07:09:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/207116.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/207116.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/207116.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/207116.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/207116.html</trackback:ping><description><![CDATA[<div>http://www.xiangwangfeng.com/2010/10/20/uac%E7%9A%84%E5%89%8D%E4%B8%96%E4%BB%8A%E7%94%9F/<br /><h3>前言：</h3><p dir="ltr" style="margin: 0px 0px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 22px; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; background-color: #f7f7f7;">&nbsp;&nbsp;&nbsp;&nbsp; 当初弄这么个博客纯粹出于蛋疼，想体会体会自己买空间，建站的乐趣。现在差不多体会完了，不过也不能就这么关了吧？于是考虑着要定期整点东西，充实充实这个博客。按照我以往的表现来看，除了QQ空间目前还存活着，绝大多数我写过的博客都半途而废了，一来懒，二来也没那么多东西好写：人总不能每天都在伤春悲秋&#8212;-毕竟不是靠卖愁滋味赚钱的人，就算写出来也意义不大，过个个把月哪还记得当年在伤啥悲啥，就算记得，感受也不深，而且有时翻出来回味却发现当年的自己如此感性，闷骚&#8212;-燥得很，不如难得糊涂，忘了算了。</p><p dir="ltr" style="margin: 0px 0px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 22px; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; background-color: #f7f7f7;">&nbsp;&nbsp;&nbsp;&nbsp; 于是考虑整点技术性的东西(当然以学习笔记和某些蛋疼的技术点为主)，主要是我这人一般懒得记笔记，初中到现在唯一记笔记本的还是高三复习物理那会，主要原因是物理实在差得离谱。以至于记笔记给我的感觉很不好，而且很多东西一旦我理解了基本不会忘&#8212;-好记性不如烂笔头，但是好的理解力就不同了，记下的东西毕竟是死的。</p><p dir="ltr" style="margin: 0px 0px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 22px; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; background-color: #f7f7f7;">&nbsp;&nbsp;&nbsp;&nbsp; 言归正传，说这次的主题:UAC。这东西很是烦人，转到我手里的bug和问题，估计有5%与它有关，很是烦人，于是在这一篇日志里面详细记录一些我理解的UAC知识。</p><p dir="ltr" style="margin: 0px 0px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 22px; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; background-color: #f7f7f7;">&nbsp;</p><h2>UAC的基本概念</h2><ul style="margin: 0px 30px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; line-height: normal; background-color: #f7f7f7;"><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 22px;"><h5>什么是UAC</h5><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; UAC即User Account Control(用户帐号控制)，是微软从Windows Vista开始为提高安全性而引入的一项新技术。用户通过这项技术既可以以非管理员身份，也能够以管理员身份执行常见的任务，而不需要切换账户或者注销。在大多数的情况下，用户都是以标准用户的状态来执行日常任务，而只有当需要设置系统特定资源的操作的任务才会需要用户以管理员的身份执行，以此来确保进程对系统的&#8220;伤害&#8221;达到最低。</p></li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 22px;"><h5>为什么使用UAC</h5><p align="left" style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 简单地说使用UAC的理由很简单：保护系统资源和数据的安全。在XP时代，在系统安装完毕后任何新建的账户都会默认划入系统管理员组，于是用户有了安装，卸载，修改，删除系统任何地方任何数据的权限，而这正是万恶之源。而如果能够控制不同程序的权限，那么大部分的恶意软件和病毒就不能起作用了。</p><p align="left" style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; UAC正是基于这种思路进行设计的：严格控制进程所能获得的权限。让一个进程无时无刻都拥有管理员权限是无法容忍的：一个恶意程序如果被自动运行于我们的系统，且肆无忌惮地执行某些会进行系统资源读写操作的代码而不为我们所知晓那是多么恐怖的事。(XP正是这么做的)所以UAC的策略就是给予进程尽可能低的权限，如果程序需要管理员权限则需要知会当前用户。同时通过一系列的措施来保障程序的正确运行：</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;"></p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">1.在可行的情况下，进行操作的权限将从系统管理员调整为标准用户。(给予最低权限)</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">2.利用虚拟化技术在没有获得系统管理员权限的情况下协助程序运行。(例如对注册表访问的重定向，保证旧版本程序的兼容性)</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">3.对程序进行再处理，这样用户帐户控制功能就可以知道在什么情况下需要系统管理员权限。(可执行文件的UAC头，来控制和判断程序所需要的权限，默认是asInvoker或None)</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">4.确保在系统管理员权限下运行的程序和在标准用户权限下运行的程序是分离的(如UIPI)</p></li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 22px;"><h5>UAC带来的影响</h5><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 对普通用户而言，UAC的引入可能并没有带来多大的影响，更多的可能只是在启动特定程序的时候有时候会跳出提示通知用户以管理员身份运行，仅此而已。但是这个地方有个比较尴尬的问题：UAC(或者其他类似的安全措施)是基于如下假设的：</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 1.个人用户对于系统安全有一定的认识，能够分辨哪些程序是好的，哪些是坏的。但是实际上对于大多数网民来说，这个假设未必成立，即使恶意软件跳出提示要以管理员身份运行，他们往往也是点确定让它运行。那么UAC的意义又在哪呢？</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp; 2.企业用户可以对系统安全一无所知，但是考虑到企业内部会有IT部门帮忙进行安全属性配置和软硬件的安装，UAC对他们来说是很有效的：只需要分配给他们标准用户帐号进行日常任务处理既可。但现实情况却是： 如果企业用户安装软件或其他需要管理员权限的事务都需要知会IT，那整个沟通成本太高，不现实。更何况很多软件产品都有不兼容UAC的问题。(比如部分公司开发的程序为了&#8220;绕过&#8221;UAC，直接把程序设为必须以管理员帐户运行)</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 对于开发人员来说可能影响会更大。如何让自己新老程序兼容和适应UAC的规则是一个不大不小的课题。</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;</p><h2>开发所需要了解的UAC</h2></li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 22px;"><h5>UAC的基本实现原理</h5><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 在Windows中有两项比较重要的概念:ACL和Access Token。ACL即Access Control List(直译成:访问控制列表)，对于Wdinows中的所有资源来说都会有自己的ACL，这个列表决定了这个资源可以被具有哪些权限的用户/进程所访问。而Access Token即用户的访问令牌，这决定了用户对资源的访问属性。在Vista之前的系统中，如果用户使用了标准用户(如XP中所谓的受限用户)，用户就会得到一个和之相对应的Access Token，只能访问和修改有限的用户资源。但只要用户用了管理员组的帐号进行登入，用户就能够获取一个所谓的"Full Access Token"，即可以获取到对任意资源的访问权。这显然是多余而且不安全的，于是从Vista起的UAC就做了如下的调整：</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 1.如果用户是标准用户，那么还是和以前一样分配给用户一个标准的访问令牌。</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 2.而如果用户是以管理员用户登入，则有所不同：系统不再是和以前一样分配个万能的访问令牌，而是生成两份访问令牌：一个完整的管理员访问令牌和一份经&#8220;和谐&#8221;的标准用户令牌。在默认的情况下，管理员权限会被移除(或者说被保存到某个地方，等用户主动请求)，而用户只拿到了他所需要的标准用户访问权限，并通过它创建了Explorer.exe程序，并以其为父进程创建所有基于标准用户的进程。</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">具体的流程可参考如图(从MSDN上盗得):</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;"><a href="http://www.xiangwangfeng.com/wordpress/wp-content/uploads/2010/10/cc709628.3be4da3f-8384-466f-b1ff-2185844c139cen-usWS.10.png" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #4a630f; text-decoration: none; outline: none;"><img title="cc709628.3be4da3f-8384-466f-b1ff-2185844c139c(en-us,WS.10)" border="0" alt="cc709628.3be4da3f-8384-466f-b1ff-2185844c139c(en-us,WS.10)" src="http://www.xiangwangfeng.com/wordpress/wp-content/uploads/2010/10/cc709628.3be4da3f-8384-466f-b1ff-2185844c139cen-usWS.10_thumb.png" width="430" height="233" style="margin: 10px 0px; padding: 0px; border: 0px none; vertical-align: baseline; max-width: 99%; height: auto; display: inline; background-image: none;" /></a></p></li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 22px;"><h5>UAC影响到的资源</h5><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从上文我们已经可以知道UAC会使得我们的程序运行在一个尽可能低的权限下，而这个权限可能过低，而不在某些敏感资源的ACL允许范围。那么从技术角度来说，搞清楚哪些资源是所谓的敏感资源就很重要&#8212;-知己知彼，百战不殆。从<a href="http://zh.wikipedia.org/zh-cn/%E4%BD%BF%E7%94%A8%E8%80%85%E5%B8%B3%E6%88%B6%E6%8E%A7%E5%88%B6#.E9.9C.80.E8.A6.81.E6.8E.88.E6.AC.8A.E7.9A.84.E5.8B.95.E4.BD.9C" target="_blank" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #4a630f; text-decoration: none; outline: none;">Wiki</a>摘抄的需要UAC授权的操作:</p><ul style="margin: 0px 30px 22px; padding: 0px; border: 0px; vertical-align: baseline;"><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">配置Windows Update</li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">增加或删除用户帐户</li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">改变用户的帐户类型</li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">改变UAC设置</li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">安装ActiveX</li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">安装或移除程序</li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">安装设备驱动程序</li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">设置家长控制</li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">将文件移动或复制到Program Files或Windows目录</li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">查看其他用户文件夹</li></ul><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 基本上，只要有涉及到访问系统磁盘的根目录（例如C:），访问Windows目录，Windows系统目录，Program Files目录，访问Windows安全信息以及读写系统登录数据库（Registry）的程序访问动作，都会需要通过UAC的认证。</p></li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 22px;"><h5>UAC带来的程序启动选项的变化和注意事项</h5><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于普通用户来讲，UAC最直观的感受就是在很多程序图标多了个小盾，且双击后会出来个用户账户控制的窗口。而对于技术人员来说当然更需要关心真正的内幕：启动的时候进程做了提权的动作，获取了更高权限的用户令牌。(而这又可能导致这个进程的用户相关上下文直接改变，当然这是后话)在Vista以后的程序在默认情况下会有3种启动选项:asInvoker(None)，highestAvailable和requireAdministrator。其中highestAvailable最不为大家熟知：这种启动方式请求当前账户可以获取到的最高权限：如果本身是管理员组内成员，则可以得到完整的管理员访问令牌，呼风唤雨。而如果是标准用户则只能得到它这个用户能够得到的最高权限。(具体如何设置程序启动选项在下面的Tips中继续说)上一幅MSDN提供的开启UAC状态下程序启动的流程图：</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;"><a href="http://www.xiangwangfeng.com/wordpress/wp-content/uploads/2010/10/IC25707.png" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #4a630f; text-decoration: none; outline: none;"><img title="IC25707" border="0" alt="IC25707" src="http://www.xiangwangfeng.com/wordpress/wp-content/uploads/2010/10/IC25707_thumb.png" width="463" height="412" style="margin: 10px 0px; padding: 0px; border: 0px none; vertical-align: baseline; max-width: 99%; height: auto; display: inline; background-image: none;" /></a></p></li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 22px;"><h5>MS为支持UAC引入的新技术和注意事项</h5><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp; 为实现UAC的所有功能，微软可谓煞费苦心，整了很多新的技术和新概念出来。(虽然个人觉得这个技术对于一般用户来说还是很鸡肋)下面就罗列一部分我们平常开发中可能会碰到或者遇到的技术：</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp; 1.Installer Dection</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 这个技术最大的作用是为了兼容以前的以前版本系统中的程序(尤其是安装程序，顾名思义嘛)，在UAC下安装程序做的很多事情可能都是十恶不赦，需要最高权限的(如写注册表，写敏感文件目录)，而旧版本的程序压根没有做任何特殊处理(或者说是只是填充了一些默认信息)，所以一种行之有效的安装程序检测技术是很必要的，否则很多程序安装都不成功，更毋论运行了。</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp; MSDN上总结了一些<a href="http://msdn.microsoft.com/en-us/library/bb530410.aspx" target="_blank" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #4a630f; text-decoration: none; outline: none;">Installer Dection的原则</a>:</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp; 1.文件名包含关键字:"install&#8221;,&#8220;setup&#8221;,"update&#8221;等关键字</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp; 2.在版本资源的以下字段内包含关键字:Vendor,CompanyName,ProductName,File Description,Original Filename,Internal Name,Export Name。(这两条应该是最SB却又最有效的一个方法，当年闪电邮的UpdateExec没有做任何处理却一直要求能够以管理员权限运行的事让我迷茫了很久)</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp; 3.可执行文件的manifest文件中包含关键字</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp; 4.在链接到可执行文件的特定String Table中包含关键字 (这个我很迷茫，求解释)</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp; 5.链接到可执行文件的资源文件数据包含关键属性</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp; 6.可执行文件包含特定的字节序列(这个意思应该是用户在manifest中写入特定属性，然后链接到可执行文件中并填充了某个字段&#8212;-现在基本上所有的安装程序/需要提权的程序都是这么做的)</p></li></ul><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 22px; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; background-color: #f7f7f7;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.Virtualization(虚拟化)</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 22px; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; background-color: #f7f7f7;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这是一项比较扯同时也是为了保证兼容性设计出来的技术。简单地来说(这个只能简单来说了，具体的原理没有相应的参考资料)，就是对老程序所进行的&#8220;非法&#8221;的 访问系统敏感数据进行重定向，可以分为文件虚拟化和注册表虚拟化。当用户对一个需要管理员权限才能够访问的文件目录或者注册表项进行读写都会被重定向。</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 22px; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; background-color: #f7f7f7;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.xiangwangfeng.com/wordpress/wp-content/uploads/2010/10/IC18372.png" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #4a630f; text-decoration: none; outline: none;"><img title="IC18372" border="0" alt="IC18372" align="left" src="http://www.xiangwangfeng.com/wordpress/wp-content/uploads/2010/10/IC18372_thumb.png" width="267" height="246" style="margin: 10px 0px; padding: 0px; border: 0px none; vertical-align: baseline; max-width: 99%; height: auto; display: inline; float: left; background-image: none;" /></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 22px; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; background-color: #f7f7f7;">如左图，用户对%ProgramFiles%的读写会被定向到%LocalAppData%VirtualStore下，而对于HKLMSoftware的读写会被重定向到HKCUSoftwareClassesVirtualStore下。</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 22px; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; background-color: #f7f7f7;">&nbsp;&nbsp; 特别需要注意的是：因为在XP下养成的习惯，我们对于注册表的读写很多直接就是用KEY_ALL_ACCESS的选项，而到了Vista和Win7后，因为分配给用户的权限低了(即使管理员帐号登入拿到的权限也是经过&#8220;和谐&#8221;的，上文已经提到)，对注册表的访问需要按需设置，如果只是读取一些注册表项值就没必要设置ALL_ACCESS，大多时候READ甚至QUERY的权限就够了。</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 22px; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; background-color: #f7f7f7;">&nbsp;&nbsp;</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 22px; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; background-color: #f7f7f7;">&nbsp;</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 22px; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; background-color: #f7f7f7;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.UIPI</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 22px; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; background-color: #f7f7f7;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这是唯一一项纯粹是出于提高安全性而不是确保兼容性引进的新技术。UIPI即User Interface Privilege Isolation，直译过来就是用户界面特权隔离。在XP时代到处充斥着各种消息粉碎攻击，最典型的就是通过发送WM_CLOSE消息使得接收者退出或者发送WM_SETTEXT给其他窗口输入信息(QQ尾巴算是这种攻击的典型应用)。大多数程序对于这种攻击都是无能为了，很多程序(比如QQ，POPO之类的IM)往往只能自己对信息做特殊的过滤和判断来防范，很是繁琐。而UIPI的基本作用就是使进程可以拦截接受比自身进程MIC等级低的进程发来的消息。在UIPI开启的情况下，只要是低MIC等级的进程向高MIC等级的进程发送消息，所有高于WM_USER的消息都默认被拦截，而低于WM_USER的消息也只有部分能够被选择性地发送成功，一些比较危险的消息也是直接被拦截掉。</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 22px; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; background-color: #f7f7f7;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所谓MIC即Mandatory Integrity Control，全称为强制完整性控制，是微软对Vista以上的系统做的安全性拓展，主要基于<a href="http://en.wikipedia.org/wiki/Biba_model" target="_blank" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #4a630f; text-decoration: none; outline: none;">Biba模型</a>。其核心在于达到"no write up，no read down"的效果。(这个no read down貌似在Vista里面反映得不是很明显，或者是没怎么注意到吧)在Vista和Win7里,MIC共分为6级:不可用，低级，中级，高级，系统级别和手保护级别。一般我们的进程包括Explorer.exe是中级，通过管理员身份运行的进程为高级，而值得注意的是IE的MIC级别是低级别&#8212;-这个理由就很明显了，不赘述，娃哈哈。</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 22px; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; background-color: #f7f7f7;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 特别声明，<a href="http://www.cnblogs.com/lucc/" target="_blank" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #4a630f; text-decoration: none; outline: none;">某个贱人</a>碰到的问题就和UIPI有关，谁叫IE的MIC等级低呢，可怜的XX宝&#8230;&#8230;</p><ul style="margin: 0px 30px 22px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; color: #333333; font-family: Tahoma, Arial, Helvetica, sans-serif; line-height: normal; background-color: #f7f7f7;"><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 22px;"><h5>个人总结的一些关于UAC的Tips</h5><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp; 1.何时需要提高进程的权限?</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 答案是：在进程启动的时候。这个问题貌似很SB，却是很多bug会产生的根源。在程序运行的过程是不能再对当前进程进行提权的：如果程序执行过程中和操作系统说：哥要提权。这个时候系统是不会理你的，当然也没有相应的API提供。</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp; 2.如何设置一个程序的启动选项</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp; 一种比较简单的方法就是通过API启动某个进程的时候带上启动选项，比如ShellExecuteEx有个runas选项</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp; 而如果需要让一个程序一直以管理员身份启动的方法就很多了：上文提到的Installer Dection的原则大多可以满足这个需求，让系统认为你的程序是安装程序，给加上小盾盾。不过个人感觉前面的5项都不太靠谱。最标准的做法是在可执行文件中嵌入UAC头。在VS08之后的工程选项Manifest File设置里面有了对启动等级的设置。而05之前则需要自己建立一个manifest文件，并通过Mt.exe向目标进程插入manifest。详见<a href="http://msdn.microsoft.com/en-us/library/bb756929.aspx" target="_blank" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #4a630f; text-decoration: none; outline: none;">《Create and Embed an Application Manifest (UAC)》</a></p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 3.UAC对文件系统和窗口消息的影响</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 因为对HKLM等注册表项和系统文件目录的读写会被重定向，所以尽量不要在非管理权限进程中进行这方面的读写&#8212;-合理安排用户数据的存储，而不是像以前一样所有数据都存在程序目录下。(当然也有猥琐的方法可以绕开这个限制，但是不推荐)</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 启动一个需要提权的进程后需要注意这个进程的环境变量上下文：标准用户下以管理员身份启动某进程后，该进程的环境变量上下文是管理员身份相关的，而非当前标准用户的。(登入用户本身是管理员组成员不会有这个问题)</p><ul style="margin: 0px 30px 22px; padding: 0px; border: 0px; vertical-align: baseline;"><ul style="margin: 0px 30px 22px; padding: 0px; border: 0px; vertical-align: baseline;"><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; UIPI的存在使得对于进程间窗口消息传递的控制更严格了，稍不留神一个消息可能就被吃掉了，所以进程间通信最万不得已的情况还是尽量少使用窗口消息&#8212;-安全性和可靠性太差。(在管理员权限环境上下文中，拖曳消息会被UIPI给屏蔽掉&#8230;&#8230;)</p></ul><ul style="margin: 0px 30px 22px; padding: 0px; border: 0px; vertical-align: baseline;"><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 4.降权的需求和实现</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 降权的需求来自于更新程序：更新程序为保证能够正常运行往往是以管理员身份运行，但这样有个问题， 当更新成功后更新进程启动主程序会将自己的权限传递下去，这会带来两大麻烦：</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp; 1.主程序获得了不该有权限，</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 2.主程序的用户环境变量上下文可能被修改了。</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 第一项问题可能不大，而第二项就比较要命了：主程序在更新后读取的文件路径都会变成管理员相关的而非当前用户的(通过查看进程管理器可以发现主程序也变成了管理员进程)&nbsp;&nbsp;&nbsp;&nbsp;</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp; 推荐的做法是在程序启动更新程序进行更新的同时保证有一个当前用户权限下的监控程序存在，在更新完毕后通过监控程序来启动主程序。</p><p style="margin: 0px 0px 22px; padding: 0px; border: 0px; vertical-align: baseline;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当然也有比较猥琐的做法，可以参考<a href="http://www.codeproject.com/KB/vista-security/RunNonElevated.aspx?msg=2183024" target="_blank" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #4a630f; text-decoration: none; outline: none;">《High elevation can be bad for your application: How to start a non-elevated process at the end of the installation》</a>，基本原理还是通过一个已存在的当前用户权限的进程来启动主程序，不同的是采用了进程内代码注入的方法，比较巧妙，但不推荐。</p></ul></ul></li></ul></div><img src ="http://www.cppblog.com/yehao/aggbug/207116.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2014-05-27 15:09 <a href="http://www.cppblog.com/yehao/articles/207116.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WideCharToMultiByte和MultiByteToWideChar函数的用法</title><link>http://www.cppblog.com/yehao/articles/206917.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Mon, 12 May 2014 08:43:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/206917.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/206917.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/206917.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/206917.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/206917.html</trackback:ping><description><![CDATA[转自http://www.cnblogs.com/gakusei/articles/1585211.html<br /><br />为了支持Unicode编码，需要多字节与宽字节之间的相互转换。这两个系统函数在使用时需要指定代码页，在实际应用过程中遇到乱码问题，然后重新阅读《Windows核心编程》，总结出正确的用法。<br /><strong>WideCharToMultiByte的代码页用来标记与新转换的字符串相关的代码页。<br />MultiByteToWideChar的代码页用来标记与一个多字节字符串相关的代码页。<br /></strong>常用的代码页由CP_ACP和CP_UTF8两个。<br /><strong>使用CP_ACP代码页就实现了ANSI与Unicode之间的转换。<br />使用CP_UTF8代码页就实现了UTF-8与Unicode之间的转换。<br /></strong>下面是代码实现：<br /><strong>1.&nbsp; ANSI to Unicode<br /></strong>wstring ANSIToUnicode( const string&amp; str )<br />{<br />&nbsp;int&nbsp; len = 0;<br />&nbsp;len = str.length();<br />&nbsp;int&nbsp; unicodeLen = ::MultiByteToWideChar( CP_ACP,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str.c_str(),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -1,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 );&nbsp; <br />&nbsp;wchar_t *&nbsp; pUnicode;&nbsp; <br />&nbsp;pUnicode = new&nbsp; wchar_t[unicodeLen+1];&nbsp; <br />&nbsp;memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));&nbsp; <br />&nbsp;::MultiByteToWideChar( CP_ACP,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str.c_str(),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -1,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (LPWSTR)pUnicode,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unicodeLen );&nbsp; <br />&nbsp;wstring&nbsp; rt;&nbsp; <br />&nbsp;rt = ( wchar_t* )pUnicode;<br />&nbsp;delete&nbsp; pUnicode; <br />&nbsp;<br />&nbsp;return&nbsp; rt;&nbsp; <br />}<br /><strong>2.&nbsp; Unicode to ANSI</strong><br />string UnicodeToANSI( const wstring&amp; str )<br />{<br />&nbsp;char*&nbsp;&nbsp;&nbsp;&nbsp; pElementText;<br />&nbsp;int&nbsp;&nbsp;&nbsp; iTextLen;<br />&nbsp;// wide char to multi char<br />&nbsp;iTextLen = WideCharToMultiByte( CP_ACP,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str.c_str(),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -1,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0,<br />NULL,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL );<br />&nbsp;pElementText = new char[iTextLen + 1];<br />&nbsp;memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );<br />&nbsp;::WideCharToMultiByte( CP_ACP,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str.c_str(),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -1,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pElementText,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iTextLen,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL );<br />&nbsp;string strText;<br />&nbsp;strText = pElementText;<br />&nbsp;delete[] pElementText;<br />&nbsp;return strText;<br />}<br /><strong>3.&nbsp; UTF-8 to Unicode</strong><br />wstring UTF8ToUnicode( const string&amp; str )<br />{<br />&nbsp;int&nbsp; len = 0;<br />&nbsp;len = str.length();<br />&nbsp;int&nbsp; unicodeLen = ::MultiByteToWideChar( CP_UTF8,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str.c_str(),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -1,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 );&nbsp; <br />&nbsp;wchar_t *&nbsp; pUnicode;&nbsp; <br />&nbsp;pUnicode = new&nbsp; wchar_t[unicodeLen+1];&nbsp; <br />&nbsp;memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));&nbsp; <br />&nbsp;::MultiByteToWideChar( CP_UTF8,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str.c_str(),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -1,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (LPWSTR)pUnicode,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unicodeLen );&nbsp; <br />&nbsp;wstring&nbsp; rt;&nbsp; <br />&nbsp;rt = ( wchar_t* )pUnicode;<br />&nbsp;delete&nbsp; pUnicode; <br />&nbsp;<br />&nbsp;return&nbsp; rt;&nbsp; <br />}<br /><strong>4.&nbsp; Unicode to UTF-8</strong>&nbsp;&nbsp;&nbsp; <br />string UnicodeToUTF8( const wstring&amp; str )<br />{<br />&nbsp;char*&nbsp;&nbsp;&nbsp;&nbsp; pElementText;<br />&nbsp;int&nbsp;&nbsp;&nbsp; iTextLen;<br />&nbsp;// wide char to multi char<br />&nbsp;iTextLen = WideCharToMultiByte( CP_UTF8,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str.c_str(),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -1,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL );<br />&nbsp;pElementText = new char[iTextLen + 1];<br />&nbsp;memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );<br />&nbsp;::WideCharToMultiByte( CP_UTF8,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str.c_str(),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -1,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pElementText,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iTextLen,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL );<br />&nbsp;string strText;<br />&nbsp;strText = pElementText;<br />&nbsp;delete[] pElementText;<br />&nbsp;return strText;<br />}<img src ="http://www.cppblog.com/yehao/aggbug/206917.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2014-05-12 16:43 <a href="http://www.cppblog.com/yehao/articles/206917.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VS中无签名UTF8和带签名UTF8格式</title><link>http://www.cppblog.com/yehao/articles/206522.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Thu, 10 Apr 2014 02:55:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/206522.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/206522.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/206522.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/206522.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/206522.html</trackback:ping><description><![CDATA[<p>在VS中，使用高级保存选项功能的时候，我们将会发现UTF8有两种格式，一个是带签名的UTF8，一个是无签名的UTF8。</p>
<p>那么这两种的格式有什么区别呢？</p>
<p>带签名的UTF8：</p>
<p>带签名的UTF8，是在生成的文件中，在文件的开头使用UTF8标志，这样在下次使用编辑器编辑的时候，编辑器能准确的识别当前文件的编码格式，并做正确的解码。</p>
<p>无签名的UTF8：</p>
<p>相反，无签名的UTF8是在保存的时候，不再文件头部写入文件的编码格式。</p>
<p>那么文件编码需要消耗多少空间呢？ &#8212;&#8212; 答案是3个字节。</p>
<p>因此，在一般使用过程中，我们建议使用带签名的UTF8格式来保存文件。在硬盘如此廉价的今天，你不会省这3个字节吧？</p>
<p>=====================分割线=========================</p>
<p>补图：</p>
<p><a title="vs下面设置utf-8 bom" href="http://blog.useasp.net/images/blog_useasp_net/20130331/vs-utf8-bom.png" rel="lightbox"><img style="display: inline" class="lazy" alt="vs下面设置utf-8 bom" src="http://blog.useasp.net/images/blog_useasp_net/20130331/vs-utf8-bom.png" width="100%" data-original="/images/blog_useasp_net/20130331/vs-utf8-bom.png" /></a><noscript></noscript></p>
<p>=====================分割线=========================</p>
<p>再次补充，关于BOM的处理，此文还是有些欠考虑，但是只是非常简单的想处理掉手中出现的问题，并记录解决方案。这里谢谢choury的严谨提醒。</p>
<p>　　BOM(BYTE ORDER MARK)只是文件的一个可选项，有很多软件并未提供对BOM的支持，因此此类软件如果打开含有BOM数据的文件时，会将此数据作为数据内容本身进行处理。如果在程序中，可能会作为程序内容来解析，这样有些程序在迁移的时候就会出现问题。在涉及到程序多处多平台迁移的时候，一般建议慎重考虑是否启用带签名的UTF8 格式。那么如何确定自己的文件UTF-8格式是带BOM的呢？ </p>
<p>　　最简单的方法就是用二进制查看文件，看文件起始是否是<font face="">EF BB BF；其次，也可以用DW看看是否是包含签名BOM的。</font></p>
<p>　　如果你不想使用带签名BOM格式的UTF8文件格式保存文件，你可以将文件在二进制下用可见字符替换掉起始的三个字节，而后在普通的文本编辑中删除该可见字符即可。　&#8212;&#8212;　UltraEdit32 可以试试，如果你没有更好的工具的话。</p><img src ="http://www.cppblog.com/yehao/aggbug/206522.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2014-04-10 10:55 <a href="http://www.cppblog.com/yehao/articles/206522.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>NM_CUSTOMDRAW消息解释</title><link>http://www.cppblog.com/yehao/articles/206088.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Fri, 07 Mar 2014 06:27:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/206088.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/206088.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/206088.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/206088.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/206088.html</trackback:ping><description><![CDATA[<div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;">NM_CUSTOMDRAW消息解释</div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="background-color: #99ffcc;">common control 4.7版本介绍了一个新的特性叫做Custom Draw，这个名字显得模糊不清，让人有点摸不着头脑，而且MSDN里也只给出了一些如风的解释和例子，没有谁告诉你你想知道的，和究竟这个特性有什么好处。</span></div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="background-color: #99ffcc;">Custom draw可以被想象成一个轻量级的，容易使用的重绘方法（重绘方法还有几种，例如Owner Draw等）。这种容易来自于我们只需要处理一个消息（<span style="font-size: 12pt;"><span style="color: #990000; font-family: 'Courier New';">NM_CUSTOMDRAW</span></span>），就可以让Windows为你干活了，你就不用被逼去处理＂重绘过程＂中所有的脏活了。</span></div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="background-color: #99ffcc;">这篇文章的焦点是如何在一个LISTCTRL控件上使用Custom Draw消息。究其原因，一部分是因为我已经在我的工作上使用了Custom Draw有一段时间了，我很熟悉它。另一个原因是这个机制确实是非常好用，你只需要写很少量的代码就可以达到很好的效果。使用 Custom draw 来对控件外观编程甚至可以代替很多的古老方法。</span></div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="background-color: #99ffcc;">以下代码是在WIN98 和VC6 SP2的环境下写的，common controls DLL的版本是5.0。我已经对其在WinNT 4上进行了测试。系统要运行这些代码，它的common controls DLL的版本必须至少是4.71。但随着IE4 的发布，这已经不是问题了。(IE会夹带着这个DLL一起发布)</span><div>&nbsp;</div><strong><span style="font-size: 18px; color: #ff9900; background-color: #99ffcc;">Custom Draw 基础</span></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="background-color: #99ffcc;">我将会尽我所能把Custom Draw的处理描述清楚，而不是简单的引用MSDN的文档。这些例子都需要你的程序有一个ListCtrl在对话框上，并且这个ListCtrl处于Report和多列模式。</span><div>&nbsp;</div><strong><span style="font-size: 18px; color: #ff9900; background-color: #99ffcc;">Custom Draw 的消息映射入口</span></strong>&nbsp;&nbsp;&nbsp;&nbsp;</div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="background-color: #99ffcc;">Custom draw 是一个类似于回调的处理过程，Windows在绘制List Ctrl的某个时间点上通过 Notification 消息通知你的程序，你可以选择忽略所有的通知（这样你就会看到标准的ListCtrl），或者处理某部分的绘制（实现简单的效果），甚至整个的控件都由你来绘制（就象使用Owner-Drawing一样）。这个机制的真正卖点是：你只需要实现一些你需要的，其余的可以让Windows为你代劳。</span>&nbsp;</div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="background-color: #99ffcc;"><span style="font-size: 12px;">好了，现在你可以开始为你的ListCtrl添加Custom Draw去做一些个性化的事情了。你首先要有正确的Comm Ctrl Dll版本，然后Windows会为你发送</span><span style="font-size: 12pt;"><span style="color: #990000; font-family: 'Courier New';">NM_CUSTOMDRAW</span></span><span style="font-size: 12px;">消息，你只需要添加一个处理函数以便开始使用Custom draw。首先添加一个消息映射，象下面一样：</span></span></div><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="font-size: 12px; background-color: #99ffcc;">ON_NOTIFY ( NM_CUSTOMDRAW, IDC_MY_LIST, OnCustomdrawMyList )</span></p><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; text-indent: 2em;"><span style="font-size: 12px; background-color: #99ffcc;">处理函数的原形如下：</span></div><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="font-size: 12px; background-color: #99ffcc;">afx_msg&nbsp;<span style="font-family: 'Courier New';"><span style="color: #0000ff;">void</span>&nbsp;OnCustomdrawMyList ( NMHDR* pNMHDR, LRESULT* pResult );</span></span></p><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="background-color: #99ffcc;"><span style="font-size: 12px;">这就告诉ＭＦＣ你要处理从你的ListCtrl控件发出的</span><span style="font-size: 12pt;"><span style="color: #990000; font-family: 'Courier New';">WM_NOTIFY</span></span><span style="font-size: 12px;">消息，ID为</span><span style="font-size: 12pt;"><span style="color: #990000; font-family: 'Courier New';">IDC_MY_LIST</span></span><span style="font-size: 12px;">，通知码为</span><span style="font-size: 12pt;"><span style="color: #990000; font-family: 'Courier New';">NM_CUSTOMDRAW</span></span><span style="font-size: 12px;">，</span><span style="font-size: 12pt;"><span style="color: #990000; font-family: 'Courier New';">OnCustomdrawMyList</span></span><span style="font-size: 12px;">就是你的处理函数。</span></span></div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;">&nbsp;</div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="background-color: #99ffcc;"><span style="font-size: 12px;">如果你有一个从ClistCtr派生的类，你想为它添加custom draw，你就可以使用</span><span style="font-size: 12pt;"><span style="color: #990000; font-family: 'Courier New';">ON_NOTIFY_REFLECT</span></span><span style="font-size: 12px;">来代替。如下：</span></span></div><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="font-size: 12px; background-color: #99ffcc;">ON_NOTIFY_REFLECT ( NM_CUSTOMDRAW, OnCustomdraw )</span><span style="background-color: #99ffcc;">OnCustomdraw的原形和上面的函数一致，但它是声明在你的派生类里的。</span></p><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="background-color: #99ffcc;">Custom draw将控件的绘制分为两部分：擦除和绘画。Windows在每部分的开始和结束都会发送NM_CUSTOMDRAW消息。所以总共就有4个消息。但是实际上你的程序所收到消息可能就只有1个或者多于四个，这取决于你想要让WINDOWS怎么做。每次发送消息的时段被称作为一个&#8220;绘画段&#8221;。你必须紧紧抓住这个概念，因为它贯穿于整个&#8220;重绘&#8221;的过程。</span></div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;">&nbsp;</div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; text-indent: 2em;"><span style="background-color: #99ffcc;">所以，你将会在以下的时间点收到通知：</span></div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; text-indent: 2em;">&nbsp;</div><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="background-color: #99ffcc;">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;一个item被画之前&#8212;&#8212;&#8220;绘画前&#8221;段</span><span style="background-color: #99ffcc;">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;一个item被画之后&#8212;&#8212;&#8220;绘画后&#8221;段</span><span style="background-color: #99ffcc;">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;一个item被擦除之前&#8212;&#8212;&#8220;擦除前&#8221;段</span><span style="background-color: #99ffcc;">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;一个item被擦除之后&#8212;&#8212;&#8220;擦除后&#8221;段</span></p><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;">&nbsp;</div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="background-color: #99ffcc;">并不是所有的消息都是一样有用的，实际上，我不需要处理所有的消息，直到这篇文章完成之前，我还没使用过擦除前和擦除后的消息。所以，不要被这些消息吓到你。</span>&nbsp;</div><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><strong><span style="font-size: 18px; color: #ff9900; background-color: #99ffcc;">NM_CUSTOMDRAW Messages提供给你的信息：</span></strong>&nbsp;&nbsp;</p><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="background-color: #99ffcc;">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NM_CUSTOMDRAW消息将会给你提供以下的信息：</span><span style="background-color: #99ffcc;">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ListCtrl的句柄</span><span style="background-color: #99ffcc;">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ListCtrl的ID</span><span style="background-color: #99ffcc;">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;当前的&#8220;绘画段&#8221;</span><span style="background-color: #99ffcc;">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;绘画的DC，让你可以用它来画画</span><span style="background-color: #99ffcc;">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;正在被绘制的控件、item、subitem的RECT值</span><span style="background-color: #99ffcc;">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;正在被绘制的Item的Index值</span><span style="background-color: #99ffcc;">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;正在被绘制的SubItem的Index值</span><span style="background-color: #99ffcc;">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;正被绘制的Item的状态值（<span style="font-size: 10pt;">selected, grayed,</span><span style="font-size: 10pt;">等等</span>）</span><span style="background-color: #99ffcc;">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Item的LPARAM值，就是你使用<span style="font-size: 12pt;"><span style="color: #990000; font-family: 'Courier New';">CListCtrl::SetItemData</span></span>所设的那个值</span></p><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; text-indent: 2em;">&nbsp;</div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="background-color: #99ffcc;">上述所有的信息对你来说可能都很重要，这取决于你想实现什么效果，但最经常用到的就是&#8220;绘画段&#8221;、&#8220;绘画ＤＣ&#8221;、&#8220;Item Index&#8221;、&#8220;LPARAM&#8221;这几个值。</span>&nbsp;</div><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><strong><span style="font-size: 18px; color: #ff9900; background-color: #99ffcc;">一个简单的例子：</span></strong>&nbsp;&nbsp;&nbsp;&nbsp;</p><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="font-size: 10pt; color: black;"><span style="background-color: #99ffcc;">好了，经过上面的无聊的细节之后，我们是时候来看一些简单的代码了。第一个例子非常的简单，它只是改变了一下控件中文字的颜色。</span></span></div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;">&nbsp;</div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; text-indent: 2em;"><span style="font-size: 10pt; color: black;"><span style="background-color: #99ffcc;">处理的代码如下：</span></span></div><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; text-indent: 2em;"><span style="color: #0000ff;"><span style="font-size: 12px; font-family: 'Courier New'; background-color: #99ffcc;">void CPanel1::OnCustomdrawList ( NMHDR* pNMHDR, LRESULT* pResult )<br /><br />{<br /><br />&nbsp;NMLVCUSTOMDRAW* pLVCD = reinterpret_cast&lt;NMLVCUSTOMDRAW*&gt;( pNMHDR );</span></span></div><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="text-indent: 2em;"><span style="color: #0000ff;"><span style="font-size: 12px; font-family: 'Courier New'; background-color: #99ffcc;">&nbsp;&nbsp;&nbsp; // Take the default processing unless we set this to something else below.<br />&nbsp;&nbsp;&nbsp; *pResult = 0;</span></span></span><span style="font-size: 12px; font-family: 'Courier New'; background-color: #99ffcc;">&nbsp;&nbsp;&nbsp; // First thing - check the draw stage. If it's the control's prepaint<br />&nbsp;&nbsp;&nbsp; // stage, then tell Windows we want messages for every item.<br />&nbsp;&nbsp;&nbsp; if ( CDDS_PREPAINT == pLVCD-&gt;nmcd.dwDrawStage )<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *pResult = CDRF_NOTIFYITEMDRAW;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; else if ( CDDS_ITEMPREPAINT == pLVCD-&gt;nmcd.dwDrawStage )<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // This is the prepaint stage for an item. Here's where we set the<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // item's text color. Our return value will tell Windows to draw the<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // item itself, but it will use the new color we set here.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // We'll cycle the colors through red, green, and light blue.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COLORREF crText;</span><span style="font-size: 12px; font-family: 'Courier New'; background-color: #99ffcc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( (pLVCD-&gt;nmcd.dwItemSpec % 3) == 0 )<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; crText = #ff0000;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if ( (pLVCD-&gt;nmcd.dwItemSpec % 3) == 1 )<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; crText = #00ff00;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; crText = #8080ff;</span><span style="font-size: 12px; font-family: 'Courier New'; background-color: #99ffcc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Store the color back in the NMLVCUSTOMDRAW struct.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pLVCD-&gt;clrText = crText;</span><span style="font-size: 12px; font-family: 'Courier New'; background-color: #99ffcc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Tell Windows to paint the control itself.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *pResult = CDRF_DODEFAULT;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />}</span><span style="font-size: 12px; background-color: #99ffcc;">结果如下，你可以看到行和行间的颜色的交错显示，多酷，而这只需要两个if的判断就可以做到了。</span></p><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="background-color: #99ffcc;">有一件事情必须记住，在做任何的绘画之前，你都要检查正处身的&#8220;绘画段&#8221;，因为你的处理函数会接收到非常多的消息，而&#8220;绘画段&#8221;将决定你代码的行为。</span>&nbsp;</div><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><strong><span style="font-size: 18px; color: #ff9900; background-color: #99ffcc;">一个更小的简单例子：</span></strong>&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="font-size: 24px; background-color: #99ffcc;"><span style="font-weight: normal; font-size: 10pt; color: black;">下面的例子将演示怎么去处理</span><span style="font-weight: normal; font-size: 10pt; color: black;">subitem</span><span style="font-weight: normal; font-size: 10pt; color: black;">的绘画</span><span style="font-weight: normal; font-size: 10pt; color: black;">(</span><span style="font-weight: normal; font-size: 10pt; color: black;">其实</span><span style="font-weight: normal; font-size: 10pt; color: black;">subitem</span><span style="font-weight: normal; font-size: 10pt; color: black;">也就是列</span><span style="font-weight: normal; font-size: 10pt; color: black;">)</span></span></strong><span style="background-color: #99ffcc;"><span style="font-size: 10pt;">在</span><span style="font-size: 10pt;">ListCtrl</span><span style="font-size: 10pt;">控件绘画前处理</span><span style="font-size: 12pt; color: #990000;">NM_CUSTOMDRAW</span><span style="font-size: 10pt;">消息。</span></span><span style="background-color: #99ffcc;"><span style="font-size: 10pt;">告诉</span><span style="font-size: 10pt;">Windows</span><span style="font-size: 10pt;">我们想对每个</span><span style="font-size: 10pt;">Item</span><span style="font-size: 10pt;">处理</span><span style="font-size: 12pt; color: #990000;">NM_CUSTOMDRAW</span><span style="font-size: 10pt;">消息。</span></span><span style="background-color: #99ffcc;"><span style="font-size: 10pt;">当这些消息中的一个到来，告诉</span><span style="font-size: 10pt;">Windows</span><span style="font-size: 10pt;">我们想在每个</span><span style="font-size: 10pt;">SubItem</span><span style="font-size: 10pt;">的绘制前处理这个消息</span></span><span style="background-color: #99ffcc;"><span style="font-size: 10pt;">当这些消息到达，我们就为每个</span><span style="font-size: 10pt;">SubItem</span><span style="font-size: 10pt;">设置文字和背景的颜色。</span></span></p><div style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; text-indent: 2em;"><span style="background-color: #99ffcc;">这里需要注意两件事：</span>&nbsp;</div><p style="color: #444444; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px;"><span style="background-color: #99ffcc;">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: 12pt; color: #990000;">clrTextBk</span>的颜色只是针对每一列，在最后一列的右边那个区域颜色也还是和ListCtrl控件的背景颜色一致。</span><span style="background-color: #99ffcc;">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;当我重新看文档的时候，我注意到有一篇题目是&#8220;<span style="font-size: 12pt; color: #990000;">NM_CUSTOMDRAW</span><span style="font-size: 10pt; color: black;">(list view)</span>&#8221;的文章，它说你可以在最开始的<span style="font-size: 10pt; color: black;">custom draw</span><span style="font-size: 10pt; color: black;">消息中</span>返回<span style="font-size: 12pt; color: #990000;">CDRF_NOTIFYSUBITEMDRAW</span>就可以处理SubItem了，而不需要在<span style="font-size: 12pt; color: #990000;">CDDS_ITEMPREPAINT</span>绘画段中去指定<span style="font-size: 12pt; color: #990000;">CDRF_NOTIFYSUBITEMDRAW</span>。但是我试了一下，发现这种方法并不起作用，你还是需要处理<span style="font-size: 12pt; color: #990000;">CDDS_ITEMPREPAINT</span>段。</span></p><img src ="http://www.cppblog.com/yehao/aggbug/206088.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2014-03-07 14:27 <a href="http://www.cppblog.com/yehao/articles/206088.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>公用控件的消息分类 WM_NOTIFY详解</title><link>http://www.cppblog.com/yehao/articles/206086.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Fri, 07 Mar 2014 06:12:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/206086.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/206086.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/206086.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/206086.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/206086.html</trackback:ping><description><![CDATA[<div>http://hi.baidu.com/422053362/item/86b5bc088a8801006c9048eb</div><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;">公用控件分为三类消息，</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;">第一类消息：由应用程序发送给控件的消息，用于改变控件的属性或使用控件的功能</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;">用SendMessage or PostMessage as so on.</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;"><br />例如以下消息都是：</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;">ACM_OPEN<br />ACM_PLAY<br />ACM_STOP</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;"><br />SB_GETBORDERS<br />SB_GETICON<br />SB_GETPARTS<br />SB_GETRECT<br />SB_GETTEXT<br />SB_GETTEXTLENGTH<br />SB_GETTIPTEXT<br />SB_GETUNICODEFORMAT<br />SB_ISSIMPLE<br />SB_SETBKCOLOR<br />SB_SETICON<br />SB_SETMINHEIGHT<br />SB_SETPARTS<br />SB_SETTEXT<br />SB_SETTIPTEXT<br />SB_SETUNICODEFORMAT<br />SB_SIMPLE</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;"></p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;">TB_ADDBITMAP<br />TB_ADDBUTTONS<br />TB_ADDSTRING<br />TB_AUTOSIZE<br />TB_BUTTONCOUNT<br />TB_BUTTONSTRUCTSIZE<br />TB_CHANGEBITMAP<br />TB_CHECKBUTTON</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;">第二类消息：在控件上有event发生时，控件给父窗口发送的消息，包括：</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;">WM_NOTIFY：<br />WM_NOTIFYFORMAT：用来决定窗口 在WM_NOTIFY消息中是接收ANSI还是Unicode 结构体</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;">第三类消息：其实不能算独立的消息，而是通知码，英文叫Notification Messages，或者说是附加消息，一般是附加在第二类消息WM_NOTIFY或者WM_COMMAND消息的lParam上</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;">像以下这些消息：<br />NM_CHAR<br />NM_CUSTOMDRAW<br />NM_CLICK<br />NM_DBLCLK<br />NM_HOVER<br />NM_KEYDOWN<br />NM_KILLFOCUS<br />NM_NCHITTEST<br />NM_OUTOFMEMORY<br />NM_RCLICK<br />NM_RDBLCLK<br />NM_RELEASEDCAPTURE<br />NM_RETURN<br />NM_SETCURSOR<br />NM_SETFOCUS<br />NM_TOOLTIPSCREATED</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;"><br />ACN_START//附加在WM_COMMAND消息上<br />ACN_STOP//附加在WM_COMMAND消息上</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;"><br />NM_CLICK (status bar)<br />NM_DBLCLK (status bar)<br />NM_RCLICK (status bar)<br />NM_RDBLCLK (status bar)<br />SBN_SIMPLEMODECHANGE</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;"><br />TBN_BEGINADJUST<br />TBN_BEGINDRAG<br />TBN_CUSTHELP<br />TBN_DELETINGBUTTON<br />TBN_DRAGOUT<br />TBN_DROPDOWN<br />TBN_ENDADJUST<br />TBN_ENDDRAG<br />TBN_GETBUTTONINFO<br />TBN_GETDISPINFO<br />TBN_GETINFOTIP<br />TBN_GETOBJECT<br />TBN_HOTITEMCHANGE<br />TBN_QUERYDELETE<br />TBN_QUERYINSERT<br />TBN_RESET<br />TBN_TOOLBARCHANGE<br />TTN_GETDISPINFO<br />TTN_POP<br />TTN_SHOW</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;"></p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;"><br />下面主要讲述WM_NOTIFY消息</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;">其附加消息中，wParam是idCtrl；lParam是一个指针，指向NMHDR结构体 或者是 指向第一个成员是NMHDR结构体的结构体，上面说的第三类消息就附加在这里面</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;">下面的例子说明了一个问题：不同控件同样是发送WM_NOTIFY消息，但是lParam却可以指向不同的结构体</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;">case WM_NOTIFY:<br />&nbsp;&nbsp; phdr=(NMHDR*)lParam;//不管lParam是指向什么结构体，起始部分都是NMHDR<br />&nbsp;&nbsp; switch(phdr-&gt;code)//根据通知码的不同，从而知道指向什么结构体<br />&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; case TVN_BEGINDRAG://说明lParam指向的是一个NM_TREEVIEW结构体<br />&nbsp;&nbsp;&nbsp;&nbsp; ptree=(NM_TREEVIEW*)lParam;</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;">&nbsp;&nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp; case NM_CUSTOMDRAW://可以发送NM_CUSTOMDRAW通知码的控件很多<br />&nbsp;&nbsp;&nbsp;&nbsp; pcd=(NMCUSTOMDRAW*)lParam;<br />&nbsp;&nbsp;&nbsp;&nbsp; if(wParam==ID_HWNDTREE)//如果是TREEVIEW控件发送的<br />&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ptvcd=(NMTVCUSTOMDRAW*)lParam;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(ptvcd-&gt;nmcd.dwDrawStage==CDDS_PREPAINT)//Before the painting cycle begins<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //the control will send NM_CUSTOMDRAW notification messages to the parent,before and after drawing items&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return CDRF_NOTIFYITEMDRAW;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(ptvcd-&gt;nmcd.dwDrawStage==CDDS_ITEMPREPAINT)//Before an item is drawn<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newfont=(HFONT)GetStockObject(ANSI_FIXED_FONT);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SelectObject(ptvcd-&gt;nmcd.hdc,newfont);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ptvcd-&gt;clrText=#ff0000;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ptvcd-&gt;clrTextBk=#009632;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return CDRF_NEWFONT;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp; default:<br />&nbsp;&nbsp;&nbsp;&nbsp; break;</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: tahoma, helvetica, arial;">&nbsp;&nbsp; }<br />&nbsp;&nbsp; break;</p><img src ="http://www.cppblog.com/yehao/aggbug/206086.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2014-03-07 14:12 <a href="http://www.cppblog.com/yehao/articles/206086.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CDialogSK---一个支持皮肤化的对话框类</title><link>http://www.cppblog.com/yehao/articles/206071.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Thu, 06 Mar 2014 11:19:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/206071.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/206071.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/206071.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/206071.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/206071.html</trackback:ping><description><![CDATA[<div>http://blog.csdn.net/mythma/article/details/20971</div><p align="center" style="color: #333333; font-family: Arial; line-height: 26px;"><strong>CDialogSK---一个支持皮肤化的对话框类</strong></p><p style="color: #333333; font-family: Arial; line-height: 26px;"><strong>一、介绍</strong><br />该类从MFC的CDialog继承而来，支持如下特征：<br />1、运行于win2000或者winxp平台上，可以使用任何透明色以透视对话框的区域。<br />2、运行于win2000或者winxp平台上，可以使得整个对话框透明。<br />3、使用位图背景。位图可以来自资源文件、bmp或者HBITMAP<br />4、设置背景类型：标题、中心、伸缩；设置对话框的大小适合位图的大小<br />5、可以点击对话框的任何部分允许/禁止移动对话框</p><p style="color: #333333; font-family: Arial; line-height: 26px;"><strong>二、用法</strong><br />使用该类的方法如下：<br />1、往工程中加入文件CDialogSK.h和CDialog.cpp<br />2、在你的对话框类中包含CDialogSD.h<br />3、在你的对话框类中用CDialogSK代替所有的CDialog<br />4、如果要使用背景图片，找到对话框属性的类型选项，使得Style=Popup，</p><p style="color: #333333; font-family: Arial; line-height: 26px;">Border=None，并使Title Bar为未选择状态。<br />5、在你的对话框类的OnInitDialog的结尾处，加入CDialogSK属性方法的调用：<br />BOOL CSkinDialog_DemoDlg::OnInitDialog()<br />{<br />&nbsp;&nbsp;&nbsp; ...<br />&nbsp;&nbsp;&nbsp; EnableEasyMove();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 允许移动<br />&nbsp;&nbsp;&nbsp; SetBitmap (IDB_BACKGROUND);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置背景位图<br />&nbsp;&nbsp;&nbsp; SetStyle (LO_RESIZE);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 使对话框大小适合位图大小<br />&nbsp;&nbsp;&nbsp; SetTransparentColor(#00ff00);&nbsp;&nbsp;&nbsp; //设置透明色为绿色</p><p style="color: #333333; font-family: Arial; line-height: 26px;">&nbsp;&nbsp;&nbsp; return TRUE;<br />}<br />6、例如，假如你想生成一个圆形的对话框，可以创建一个图片，背景为绿，画一个蓝色的圆。然后，调用SetBitmap，参数为图像的路径，调用SetTransparentColor,参数为背景的颜色（绿色）。这样就看不到背景，得到一给圆形的窗口。</p><p style="color: #333333; font-family: Arial; line-height: 26px;"><strong>三、方法</strong><br />CDialogSK类提供如下的方法：<br />1、DWORD SetBitmap (HBITMAP hBitmap);<br />2、DWORD SetBitmap (int nBitmap);<br />3、DWORD SetBitmap (LPCTSTR lpszFileName);<br />4、void SetStyle (LayOutStyle style);<br />LO_DEFAULT, LO_TILE (标题图片), LO_CENTER (中心图片), LO_STRETCH (伸缩</p><p style="color: #333333; font-family: Arial; line-height: 26px;">图片以适合对话框大小), or LO_RESIZE (伸缩对话框适合图片).&nbsp;<br />5、void EnableEasyMove (BOOL pEnable = TRUE);<br />6、BOOL SetTransparent (BYTE bAlpha);<br />使整个对话框透明，范围为0（透明）-255（不透明）。只适合win2000及以上版</p><p style="color: #333333; font-family: Arial; line-height: 26px;">本<br />7、BOOL SetTransparentColor (COLORREF col, BOOL bTrans = TRUE);<br />指定透明色。只适合win2000及以上版本。</p><p style="color: #333333; font-family: Arial; line-height: 26px;"><em>CDialogSK类文件下载地址</em><a href="http://www.codeguru.com/code/legacy/dialog/CDialogSK_src.zip" style="color: #336699; text-decoration: none;"><em>http://www.codeguru.com/code/legacy/dialog/CDialogSK_src.zip</em></a></p><img src ="http://www.cppblog.com/yehao/aggbug/206071.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2014-03-06 19:19 <a href="http://www.cppblog.com/yehao/articles/206071.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何子类化（SubclassWindow）窗体</title><link>http://www.cppblog.com/yehao/articles/205881.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Fri, 21 Feb 2014 02:20:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/205881.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/205881.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/205881.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/205881.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/205881.html</trackback:ping><description><![CDATA[<p style="color: #333333; font-family: Arial; line-height: 26px; font-size: 9pt; text-indent: 18.75pt;"><strong style="font-size: 14px; text-indent: 0px; background-color: #ffffff;"><span style="font-size: x-small; font-family: 宋体; color: #ff6600;">转自</span></strong><a href="http://blog.csdn.net/yuntongsf/article/details/4443356">http://blog.csdn.net/yuntongsf/article/details/4443356</a><br /><strong style="font-size: 14px; text-indent: 0px; background-color: #ffffff;"><span style="font-size: x-small; font-family: 宋体; color: #ff6600;">窗口子类化的作用</span></strong><br />&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: small;"><span style="font-family: 宋体;">窗口子类化技术最大的特点就是能够截取</span>&nbsp;<span style="font-family: 'Times New Roman';">Windows&nbsp;</span><span style="font-family: 宋体;">的消息。一旦用户自定义的窗口函数截取了传向原窗口函数的消息，就可以对被截取的消息进行如下处理:</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 39.75pt; text-indent: -21pt;"><span style="font-family: 宋体;"><span style="font-size: small;">将其传给原来的窗口函数。这是对大多数消息应该采取的措施，因为子类通常只对原来的窗口特性作少量的改动</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 39.75pt; text-indent: -21pt;"><span style="font-family: 宋体;"><span style="font-size: small;">截取该消息，阻止其向原窗口函数发送。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 39.75pt; text-indent: -21pt;"><span style="font-family: 宋体;"><span style="font-size: small;">修改该消息，修改完毕以后再向原窗口函数发送。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 18.75pt;"><span style="font-size: small;"><span style="font-family: 'Times New Roman';">Windows SDK&nbsp;</span><span style="font-family: 宋体;">提供了一些设计好的窗口类，如</span>&nbsp;<span style="font-family: 'Times New Roman';">EDIT&nbsp;</span><span style="font-family: 宋体;">、</span>&nbsp;<span style="font-family: 'Times New Roman';">LISTBOX&nbsp;</span><span style="font-family: 宋体;">、</span>&nbsp;<span style="font-family: 'Times New Roman';">TREEVIEW&nbsp;</span><span style="font-family: 宋体;">等。通过截取这些通用窗口类的消息，用户程序可以为它们添加新的特性，改善其外观，扩充其功能。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 18.75pt;"><span style="font-size: small;"><span style="font-size: 10pt; font-family: 宋体;">子类化的优点主要体现在以下两个方面：首先，它不需要创建新的窗口类，不需要了解一个窗口的窗口过程。这在原来的窗口函数是由别人编写，而且创建过程不可见的情况下非常有用；其次，子类化比较容易实现，因为所有要做的工作仅仅就是写一个窗口函数</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px;">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px;"><strong><span style="font-size: 12pt; color: #ff6600;"><span style="font-family: 宋体;">在</span>&nbsp;<span style="font-family: 'Times New Roman';">VC&nbsp;</span><span style="font-family: 宋体;">中实现窗口子类化</span></span></strong></p><p style="color: #333333; font-family: Arial; line-height: 26px;"></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 18.75pt;"><span style="font-size: small;"><span style="font-family: 宋体;">上面介绍的子类化是从</span>&nbsp;<span style="font-family: 'Times New Roman';">Windows&nbsp;</span><span style="font-family: 宋体;">本身的窗口函数概念来讲的，实际上属于</span>&nbsp;<span style="font-family: 'Times New Roman';">SDK&nbsp;</span><span style="font-family: 宋体;">（</span>&nbsp;<span style="font-family: 'Times New Roman';">Software Development Kit&nbsp;</span><span style="font-family: 宋体;">）编程的范畴，在</span>&nbsp;<span style="font-family: 'Times New Roman';">MFC&nbsp;</span><span style="font-family: 宋体;">中情况有所不同。下面将分别描述在这两种情况下窗口子类化实现的方法。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 18.75pt;"><span style="font-size: small;"><strong></strong></span>&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 18.75pt;"><span style="font-size: small;"><strong><span style="font-family: 'Times New Roman';">VC&nbsp;</span></strong><strong><span style="font-family: 宋体;">中基于</span>&nbsp;<span style="font-family: 'Times New Roman';">SDK&nbsp;</span></strong><strong><span style="font-family: 宋体;">编程的窗口子类化</span></strong></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; font-size: 10pt; text-indent: 21pt;"><span style="font-size: small;"><span style="font-family: 'Times New Roman';">VC&nbsp;</span><span style="font-family: 宋体;">中基于</span>&nbsp;<span style="font-family: 'Times New Roman';">SDK&nbsp;</span><span style="font-family: 宋体;">编程的窗口子类化的基本步骤如下：</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 57pt; text-indent: -36pt;"><span style="font-family: 'Times New Roman';"><span style="font-size: small;">（1）&nbsp;<span style="font-size: 7pt; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></span><span style="font-family: 宋体;"><span style="font-size: small;">正常创建原始窗口，得到窗口的句柄。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 57pt; text-indent: -36pt;"><span style="font-family: 'Times New Roman';"><span style="font-size: small;">（2）&nbsp;<span style="font-size: 7pt; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></span><span style="font-size: small;"><span style="font-family: 宋体;">调用</span>&nbsp;<span style="font-family: 'Times New Roman';">GetWindowLong&nbsp;</span><span style="font-family: 宋体;">得到原来的窗口函数</span>&nbsp;<span style="font-family: 'Times New Roman';">OldWndProc&nbsp;</span><span style="font-family: 宋体;">。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 57pt; text-indent: -36pt;"><span style="font-family: 'Times New Roman';"><span style="font-size: small;">（3）&nbsp;<span style="font-size: 7pt; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></span><span style="font-size: small;"><span style="font-family: 宋体;">调用</span>&nbsp;<span style="font-family: 'Times New Roman';">SetWindowLong&nbsp;</span><span style="font-family: 宋体;">设置新的窗口函数</span>&nbsp;<span style="font-family: 'Times New Roman';">NewWndProc&nbsp;</span><span style="font-family: 宋体;">。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 21pt; font-size: 10pt;"><span style="font-family: 宋体;"><span style="font-size: small;">新的窗口函数的代码如下所示：</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 21pt;"><span style="font-size: small; font-family: 'Times New Roman';">LRESULT NewWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 21pt;"><span style="font-size: small; font-family: 'Times New Roman';">{</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 21pt;"><span style="font-size: small;"><span style="font-size: 10pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(message==WM_IcareIt)</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 21pt;"><span style="font-size: small;"><span style="font-size: 10pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 21pt;"><span style="font-size: small;"><span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;</span><span style="font-family: 宋体;">截取自己感兴趣的消息，作一些处理，达到改变特性的目的</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 21pt;"><span style="font-size: small;"><span style="font-family: 宋体;">&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: small; font-family: 'Times New Roman';">}</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 21pt;"><span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: small;"><span style="font-size: 10pt; font-family: 'Times New Roman';">//&nbsp;</span><span style="font-size: 10pt; font-family: 宋体;">必要时可以调用原来的窗口函数，使被子类化的窗口仍具有原来的很多特性</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 21pt;"><span style="font-size: small;"><span style="font-size: 10pt; font-family: 宋体;">&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: small; font-family: 'Times New Roman';">return CallWndowProc(OldWndProc,hWnd,message,wParam,lParam);</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 21pt;"><span style="font-size: small; font-family: 'Times New Roman';">}</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 21pt;"><span style="font-size: small;"><span style="font-family: 宋体;">值得注意的是，在调用旧的窗口函数时，不能直接用</span>&nbsp;<span style="font-family: 'Times New Roman';">OldWndProc(&#8230;)&nbsp;</span><span style="font-family: 宋体;">，而必须用函数</span>&nbsp;<span style="font-family: 'Times New Roman';">CallWndProc&nbsp;</span><span style="font-family: 宋体;">进行调用，否则会出现堆栈错误。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 18.75pt;"><span style="font-size: small;"><strong><span style="font-family: 'Times New Roman';">MFC&nbsp;</span></strong><strong><span style="font-family: 宋体;">编程中的窗口子类化</span></strong></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 18.75pt;"><span style="font-size: small;"><span style="font-family: 'Times New Roman';">MFC&nbsp;</span><span style="font-family: 宋体;">窗口实际上已经是被子类化的窗口。所有的</span>&nbsp;<span style="font-family: 'Times New Roman';">MFC&nbsp;</span><span style="font-family: 宋体;">窗口共享同一个</span>&nbsp;</span><span style="font-size: small;"><span style="font-family: 宋体;">窗口函数，由这个窗口函数根据窗口句柄，查找这个窗口对应的</span>&nbsp;<span style="font-family: 'Times New Roman';">CWnd&nbsp;</span><span style="font-family: 宋体;">派生类实例，再通过消息映射这个窗口类的消息处理函数。鉴于以上原因，在</span>&nbsp;<span style="font-family: 'Times New Roman';">MFC&nbsp;</span><span style="font-family: 宋体;">中要子类化一个窗口就比较容易了，因为你的任务只是编写一个新的</span>&nbsp;<span style="font-family: 'Times New Roman';">MFC&nbsp;</span><span style="font-family: 宋体;">窗口类而不需要写一个窗口函数。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 18.75pt;"><span style="font-size: small;"><span style="font-family: 宋体;">假如我们现在有一个对话框，里面有一个编辑控件，我们只希望在该控件中接受非数字字符输入，我们可以拦截</span><span style="font-family: 'Times New Roman';">WM_CHAR&nbsp;</span><span style="font-family: 宋体;">消息，在它的处理函数中忽略任何数字的输入。</span>&nbsp;<span style="font-family: 'Times New Roman';">MFC&nbsp;</span><span style="font-family: 宋体;">编程中窗口子类化的具体实现步骤在下一节笔者将用一个简单的实例来加以说明。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 18.75pt;">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px;"><strong><span style="font-size: small;"><span style="color: #ff6600;"><span style="font-family: 'Times New Roman';">VC&nbsp;</span><span style="font-family: 宋体;">中窗口子类化的应用举例</span></span></span></strong></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 18.7pt;"><span style="font-size: small;"><span style="font-family: 'Times New Roman';">MFC&nbsp;</span><span style="font-family: 宋体;">为广大编程者提供了很多功能丰富的窗口类，如果能在这些通用窗口类的基础上进行子类化的话，将会给编程者带来很多便利。下面举一个例子来说明</span>&nbsp;<span style="font-family: 'Times New Roman';">MFC&nbsp;</span><span style="font-family: 宋体;">编程中的子类化是多么的简单易行。该例完成上面提到的在编辑控件只接受非数字字符输入的功能。实现这个子类化的基本步骤和相关代码如下：</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 21pt;"><span style="font-size: small;"><span style="font-family: 宋体;">（</span>&nbsp;<span style="font-family: 'Times New Roman';">1&nbsp;</span><span style="font-family: 宋体;">）利用</span>&nbsp;<span style="font-family: 'Times New Roman';">AppWziard&nbsp;</span><span style="font-family: 宋体;">创建一个基于对话框的程序</span>&nbsp;<span style="font-family: 'Times New Roman';">SubClassing&nbsp;</span><span style="font-family: 宋体;">。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 21pt;"><span style="font-size: small;"><span style="font-family: 宋体;">（</span>&nbsp;<span style="font-family: 'Times New Roman';">2&nbsp;</span><span style="font-family: 宋体;">）对</span>&nbsp;<span style="font-family: 'Times New Roman';">MFC&nbsp;</span><span style="font-family: 宋体;">提供的标准的对话框中的控件进行修改，删除</span>&nbsp;<span style="font-family: 'Times New Roman';">MFC&nbsp;</span><span style="font-family: 宋体;">提供的静态文本控件，添加自己的一个编辑控件，设置新控件的</span>&nbsp;<span style="font-family: 'Times New Roman';">ID&nbsp;</span><span style="font-family: 宋体;">为</span>&nbsp;<span style="font-family: 'Times New Roman';">IDC_EDIT&nbsp;</span><span style="font-family: 宋体;">。合理布置对话框上各控件的位置，使程序界面布局合理、美观。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 21pt;"><span style="font-size: small;"><span style="font-family: 宋体;">（</span>&nbsp;<span style="font-family: 'Times New Roman';">3&nbsp;</span><span style="font-family: 宋体;">）用</span>&nbsp;<span style="font-family: 'Times New Roman';">ClassWizard&nbsp;</span><span style="font-family: 宋体;">从</span>&nbsp;<span style="font-family: 'Times New Roman';">CEdit&nbsp;</span><span style="font-family: 宋体;">类派生一个新的窗口类，新窗口的窗口类叫</span>&nbsp;<span style="font-family: 'Times New Roman';">CNoNumEdit&nbsp;</span><span style="font-family: 宋体;">。截取</span>&nbsp;<span style="font-family: 'Times New Roman';">CNoNumEdit&nbsp;</span><span style="font-family: 宋体;">类的</span><span style="font-family: 'Times New Roman';">WM_CHAR&nbsp;</span><span style="font-family: 宋体;">消息，在</span>&nbsp;<span style="font-family: 'Times New Roman';">OnChar&nbsp;</span><span style="font-family: 宋体;">函中完成忽略任何数字的输入的处理。实现代码如下：</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 21pt;"><span style="font-size: small;"><span style="font-size: 10pt; font-family: 'Times New Roman';">void CNoNumEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 21pt;"><span style="font-size: small;"><span style="font-size: 10pt; font-family: 'Times New Roman';">{</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; font-size: 10pt; text-indent: 21pt;"><span style="font-size: small;"><span style="font-size: 10pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TCHAR ch=nChar;</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 21pt;"><span style="font-size: small;"><span style="font-size: 10pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;if(ch&gt;=_T('0')&amp;&amp;ch&lt;=_T('9'))</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; font-size: 10pt; text-indent: 21pt;"><span style="font-size: small;"><span style="font-size: 10pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 21pt;"><span style="font-size: small;"><span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AfxMessageBox(("&nbsp;</span><span style="font-family: 宋体;">请不要输入数字！</span>&nbsp;<span style="font-family: 'Times New Roman';">"),MB_OK);</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 21pt;"><span style="font-size: small;"><span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;</span><span style="font-family: 宋体;">当输入数字字符时将被忽略，并显示警告信息</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 21pt;"><span style="font-size: small;"><span style="font-size: 10pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 21pt;"><span style="font-size: small;"><span style="font-size: 10pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; font-size: 10pt; text-indent: 21pt;"><span style="font-size: small;"><span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CEdit::OnChar(nChar, nRepCnt, nFlags);//&nbsp;</span><span style="font-family: 宋体;">输入为非数字字符时调用原处理函数</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; font-size: 10pt; text-indent: 21pt;"><span style="font-size: small; font-family: 'Times New Roman';">}</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; font-size: 10pt; text-indent: 21pt;"><span style="font-family: 'Times New Roman';">（&nbsp;</span><span style="font-size: small;"><span style="font-family: 'Times New Roman';">4&nbsp;</span><span style="font-family: 宋体;">）在对话框窗口类</span>&nbsp;<span style="font-family: 'Times New Roman';">CSubClassingDlg&nbsp;</span><span style="font-family: 宋体;">的定义中添加变量</span>&nbsp;<span style="font-family: 'Times New Roman';">CNoNumEdit ed&nbsp;</span><span style="font-family: 宋体;">。在</span>&nbsp;<span style="font-family: 'Times New Roman';">CSubClassingDlg::OnInitDialog()&nbsp;</span><span style="font-family: 宋体;">函数中调用</span>&nbsp;<span style="font-family: 'Times New Roman';">CWnd&nbsp;</span><span style="font-family: 宋体;">类的成员函数</span>&nbsp;<span style="font-family: 'Times New Roman';">SubClassWindow&nbsp;</span><span style="font-family: 宋体;">进行子类化。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; font-size: 10pt; text-indent: 21pt;"><span style="font-size: small;"><span style="font-size: 10pt; font-family: 'Times New Roman';">ed.SubclassWindow(GetDlgItem(IDC_EDIT)-&gt;m_hWnd);</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 21pt;"><span style="font-size: small;"><span style="font-family: 宋体;">（</span>&nbsp;<span style="font-family: 'Times New Roman';">5&nbsp;</span><span style="font-family: 宋体;">）</span>&nbsp;<span style="font-family: 'Times New Roman';">&nbsp;&nbsp;</span><span style="font-family: 宋体;">在对话框窗口类</span>&nbsp;<span style="font-family: 'Times New Roman';">CsubClassing&nbsp;</span><span style="font-family: 宋体;">的</span>&nbsp;<span style="font-family: 'Times New Roman';">OnDestroy&nbsp;</span><span style="font-family: 宋体;">中调用</span>&nbsp;<span style="font-family: 'Times New Roman';">ed.UnSubClassWindow()&nbsp;</span><span style="font-family: 宋体;">执行窗口类的反子类化。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-indent: 18.75pt;"><span style="font-family: 宋体;"><span style="font-size: small;">现在可以编译执行这个程序了，当用户输入数字字符时将会忽略该输入，并显示警告信息。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px;"><span style="font-family: 宋体;"><strong></strong></span>&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; font-size: 10pt; text-indent: 18.75pt;"><span style="font-size: small;"><span style="font-family: 宋体;">在</span>&nbsp;<span style="font-family: 'Times New Roman';">Windows&nbsp;</span><span style="font-family: 宋体;">编 程中，适当使用窗口子类化技术，可以很方便地达到改变一个窗口的特性的目的。当然子类化也存在其局限性。实际上，子类化的概念是针对一个已经创建的窗口来 谈的，所以修改窗口函数是在窗口创建之后进行的，在窗口创建期间的消息无法捕获，也就无法处理。另外有些窗口的特性与窗口类本身的属性有关。比如如果一个 窗口类没有</span>&nbsp;<span style="font-family: 'Times New Roman';">CS_DBLCLKS&nbsp;</span><span style="font-family: 宋体;">属性的话，那么要想通过子类化这些窗口达到处理</span>&nbsp;<span style="font-family: 'Times New Roman';">WM_LBUTTONDBLCLK&nbsp;</span><span style="font-family: 宋体;">消息的目的是无法实现的。对于子类化的以上局限性，可以通过超类化（</span>&nbsp;<span style="font-family: 'Times New Roman';">SuperClassing&nbsp;</span><span style="font-family: 宋体;">）技术消除。</span></span></p><img src ="http://www.cppblog.com/yehao/aggbug/205881.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2014-02-21 10:20 <a href="http://www.cppblog.com/yehao/articles/205881.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VS2010进行远程调试方法总结</title><link>http://www.cppblog.com/yehao/articles/205851.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Wed, 19 Feb 2014 07:39:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/205851.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/205851.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/205851.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/205851.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/205851.html</trackback:ping><description><![CDATA[<div style="color: #323e32; font-family: simsun; background-color: #2d220c;"><div></div></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"><div>转自<a href="http://blog.sina.com.cn/s/blog_a459dcf5010153o7.html">http://blog.sina.com.cn/s/blog_a459dcf5010153o7.html</a><br /><br />假设现在有A、B两台PC机。</div><div>VS2010安装在A机器上，也就是说A机器是开发使用的机器。</div><div>B机器是程序运行部署使用的机器，其IP为：192.168.1.129（局域网IP）</div><div>说明：如果B机器是外网IP下面方法照样适合，不过在使用的适合可能会出现无法附加到进程的错误。</div><div>如果出现无法附加到进程的错误、无法连接到设备<span style="word-wrap: normal; word-break: normal; line-height: 26px; font-family: Arial; background-color: #ffffff;">.</span>请按照步骤13进行设置。</div><div>&nbsp;<wbr></div><div>1、根据vs2010安装目录倒找Remote&nbsp;<wbr>Debugger文件夹。如下图：</div></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"></div><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s15.sinaimg.cn/orignal/a459dcf5tc1e35bf1d01e" target="_blank" style="text-decoration: none; color: #006760; font-family: simsun; background-color: #2d220c;"><img src="http://s15.sinaimg.cn/bmiddle/a459dcf5tc1e35bf1d01e&amp;690" real_src="http://s15.sinaimg.cn/bmiddle/a459dcf5tc1e35bf1d01e&amp;690" name="image_operate_17841339082561235" alt="VS2010进行远程调试方法总结" title="VS2010进行远程调试方法总结" action-data="http%3A%2F%2Fs15.sinaimg.cn%2Fbmiddle%2Fa459dcf5tc1e35bf1d01e%26690" action-type="show-slide" style="margin: 0px; padding: 0px; border: 0px; list-style: none;" /></a><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s15.sinaimg.cn/orignal/a459dcf5tc1e35bf1d01e" target="_blank" style="text-decoration: none; color: #006760;"></a><div>2、拷贝C:\Program&nbsp;<wbr>Files\Microsoft&nbsp;<wbr>Visual&nbsp;<wbr>Studio&nbsp;<wbr>10.0\Common7\IDE\Remote&nbsp;<wbr>Debugger目录到B机器上</div><div>3、运行B机器中Remote Debugger\x86下的msvsmon.exe文件如下图：（注意以管理员的程序运行msvsmon.exe）</div><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s10.sinaimg.cn/orignal/a459dcf5tc1e3988ca639" target="_blank" style="text-decoration: none; color: #006760;"><img src="http://s10.sinaimg.cn/bmiddle/a459dcf5tc1e3988ca639&amp;690" real_src="http://s10.sinaimg.cn/bmiddle/a459dcf5tc1e3988ca639&amp;690" name="image_operate_68701339083167069" alt="VS2010进行远程调试方法总结" title="VS2010进行远程调试方法总结" action-data="http%3A%2F%2Fs10.sinaimg.cn%2Fbmiddle%2Fa459dcf5tc1e3988ca639%26690" action-type="show-slide" style="margin: 0px; padding: 0px; border: 0px; list-style: none;" /></a><br /><br /><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s6.sinaimg.cn/orignal/a459dcf5t79c9ef9956b5" target="_blank" style="text-decoration: none; color: #006760;"></a></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s6.sinaimg.cn/orignal/a459dcf5t79c9ef9956b5" target="_blank" style="text-decoration: none; color: #006760;"></a><br /><div>4、在上图中选择Tools中的Options菜单项，如下图：</div><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s4.sinaimg.cn/orignal/a459dcf5tc1e35c01e043" target="_blank" style="text-decoration: none; color: #006760;"><img src="http://s4.sinaimg.cn/bmiddle/a459dcf5tc1e35c01e043&amp;690" real_src="http://s4.sinaimg.cn/bmiddle/a459dcf5tc1e35c01e043&amp;690" name="image_operate_26221339082488503" alt="VS2010进行远程调试方法总结" title="VS2010进行远程调试方法总结" action-data="http%3A%2F%2Fs4.sinaimg.cn%2Fbmiddle%2Fa459dcf5tc1e35c01e043%26690" action-type="show-slide" style="margin: 0px; padding: 0px; border: 0px; list-style: none;" /></a></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s4.sinaimg.cn/orignal/a459dcf5tc1e35c01e043" target="_blank" style="text-decoration: none; color: #006760;"></a><br /><br /><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s11.sinaimg.cn/orignal/a459dcf5tc1e35c0b47ca" target="_blank" style="text-decoration: none; color: #006760;"><img src="http://s11.sinaimg.cn/bmiddle/a459dcf5tc1e35c0b47ca&amp;690" real_src="http://s11.sinaimg.cn/bmiddle/a459dcf5tc1e35c0b47ca&amp;690" name="image_operate_32891339082508238" alt="VS2010进行远程调试方法总结" title="VS2010进行远程调试方法总结" style="margin: 0px; padding: 0px; border: 0px; list-style: none;" /></a></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s11.sinaimg.cn/orignal/a459dcf5tc1e35c0b47ca" target="_blank" style="text-decoration: none; color: #006760;"></a><div>5、在弹出的对话框中按照下列方式进行设置，如下图：</div><br /><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s8.sinaimg.cn/orignal/a459dcf5tc1e35c12ad67" target="_blank" style="text-decoration: none; color: #006760;"><img src="http://s8.sinaimg.cn/bmiddle/a459dcf5tc1e35c12ad67&amp;690" real_src="http://s8.sinaimg.cn/bmiddle/a459dcf5tc1e35c12ad67&amp;690" name="image_operate_88841339082508716" alt="VS2010进行远程调试方法总结" title="VS2010进行远程调试方法总结" style="margin: 0px; padding: 0px; border: 0px; list-style: none;" /></a></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s8.sinaimg.cn/orignal/a459dcf5tc1e35c12ad67" target="_blank" style="text-decoration: none; color: #006760;"></a><div>6、设置完成后点击OK按钮&nbsp;<wbr></div><br /><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s14.sinaimg.cn/orignal/a459dcf5tc1e35c247f3d" target="_blank" style="text-decoration: none; color: #006760;"></a><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s3.sinaimg.cn/orignal/a459dcf5tc1e392877ee2" target="_blank" style="text-decoration: none; color: #006760;"><img src="http://s3.sinaimg.cn/bmiddle/a459dcf5tc1e392877ee2&amp;690" real_src="http://s3.sinaimg.cn/bmiddle/a459dcf5tc1e392877ee2&amp;690" name="image_operate_47611339083123211" alt="VS2010进行远程调试方法总结" title="VS2010进行远程调试方法总结" action-data="http%3A%2F%2Fs3.sinaimg.cn%2Fbmiddle%2Fa459dcf5tc1e392877ee2%26690" action-type="show-slide" style="margin: 0px; padding: 0px; border: 0px; list-style: none;" /></a></div><br style="color: #323e32; font-family: simsun; background-color: #2d220c;" /><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"><span style="word-wrap: normal; word-break: normal; line-height: 19px; font-size: small;">到此需要调试的机器B已经设置完毕。</span></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"><div>&nbsp;<wbr></div><div>&nbsp;<wbr></div><div>&nbsp;<wbr></div><div>下面给出一个例子来演示如何在A机器上调试B机器中运行的程序。</div><div>&nbsp;<wbr></div><div>7、在B机器上运行test.exe如下图：</div><br /><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s6.sinaimg.cn/orignal/a459dcf5t79c9ef9edea5" target="_blank" style="text-decoration: none; color: #006760;"><img src="http://s6.sinaimg.cn/bmiddle/a459dcf5t79c9ef9edea5&amp;690" real_src="http://s6.sinaimg.cn/bmiddle/a459dcf5t79c9ef9edea5&amp;690" name="image_operate_95101339082512420" alt="VS2010进行远程调试方法总结" title="VS2010进行远程调试方法总结" action-data="http%3A%2F%2Fs6.sinaimg.cn%2Fbmiddle%2Fa459dcf5t79c9ef9edea5%26690" action-type="show-slide" style="margin: 0px; padding: 0px; border: 0px; list-style: none;" /></a></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s6.sinaimg.cn/orignal/a459dcf5t79c9ef9edea5" target="_blank" style="text-decoration: none; color: #006760;"></a><br /><br /><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s6.sinaimg.cn/orignal/a459dcf5tc1e35c2eef55" target="_blank" style="text-decoration: none; color: #006760;"><img src="http://s6.sinaimg.cn/bmiddle/a459dcf5tc1e35c2eef55&amp;690" real_src="http://s6.sinaimg.cn/bmiddle/a459dcf5tc1e35c2eef55&amp;690" name="image_operate_29601339082514553" alt="VS2010进行远程调试方法总结" title="VS2010进行远程调试方法总结" style="margin: 0px; padding: 0px; border: 0px; list-style: none;" /></a></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s6.sinaimg.cn/orignal/a459dcf5tc1e35c2eef55" target="_blank" style="text-decoration: none; color: #006760;"></a><div>8、在A机器上打开test.exe对应的源码(注意源码必须与test.exe保持一致，本文只给出调试方法，例子中代码无任何逻辑)，如下图：</div><br /><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s2.sinaimg.cn/orignal/a459dcf5tc1e35c4e3451" target="_blank" style="text-decoration: none; color: #006760;"><img src="http://s2.sinaimg.cn/bmiddle/a459dcf5tc1e35c4e3451&amp;690" real_src="http://s2.sinaimg.cn/bmiddle/a459dcf5tc1e35c4e3451&amp;690" name="image_operate_86431339082519830" alt="VS2010进行远程调试方法总结" title="VS2010进行远程调试方法总结" action-data="http%3A%2F%2Fs2.sinaimg.cn%2Fbmiddle%2Fa459dcf5tc1e35c4e3451%26690" action-type="show-slide" style="margin: 0px; padding: 0px; border: 0px; list-style: none;" /></a><br /></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"><div>9、在8中选择Debug菜单中的Attach to Process子菜单项，如下图：</div><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s6.sinaimg.cn/orignal/a459dcf5tc1e35c697735" target="_blank" style="text-decoration: none; color: #006760;"><img src="http://s6.sinaimg.cn/bmiddle/a459dcf5tc1e35c697735&amp;690" real_src="http://s6.sinaimg.cn/bmiddle/a459dcf5tc1e35c697735&amp;690" name="image_operate_21031339082521175" alt="VS2010进行远程调试方法总结" title="VS2010进行远程调试方法总结" action-data="http%3A%2F%2Fs6.sinaimg.cn%2Fbmiddle%2Fa459dcf5tc1e35c697735%26690" action-type="show-slide" style="margin: 0px; padding: 0px; border: 0px; list-style: none;" /></a></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s6.sinaimg.cn/orignal/a459dcf5tc1e35c697735" target="_blank" style="text-decoration: none; color: #006760;"></a><br /><div>弹出如下对话框：</div><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s11.sinaimg.cn/orignal/a459dcf5tc1e35c8eaaba" target="_blank" style="text-decoration: none; color: #006760;"><img src="http://s11.sinaimg.cn/bmiddle/a459dcf5tc1e35c8eaaba&amp;690" real_src="http://s11.sinaimg.cn/bmiddle/a459dcf5tc1e35c8eaaba&amp;690" name="image_operate_35261339082524254" alt="VS2010进行远程调试方法总结" title="VS2010进行远程调试方法总结" action-data="http%3A%2F%2Fs11.sinaimg.cn%2Fbmiddle%2Fa459dcf5tc1e35c8eaaba%26690" action-type="show-slide" style="margin: 0px; padding: 0px; border: 0px; list-style: none;" /></a><br /></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"><div>10、在Transport中选择：Remote(Native only with no authentication)选项，并在Qualifier中输入：192.168.1.129.如下图：</div><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s10.sinaimg.cn/orignal/a459dcf5t79c9efa98bd9" target="_blank" style="text-decoration: none; color: #006760;"><img src="http://s10.sinaimg.cn/bmiddle/a459dcf5t79c9efa98bd9&amp;690" real_src="http://s10.sinaimg.cn/bmiddle/a459dcf5t79c9efa98bd9&amp;690" name="image_operate_3671339082527007" alt="VS2010进行远程调试方法总结" title="VS2010进行远程调试方法总结" style="margin: 0px; padding: 0px; border: 0px; list-style: none;" /></a><br /></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;">11、在10的基础上点击Refresh按钮，就可以看到B机器上的进程列表了。在进程列表中找到我们需要调试的的进程test.exe并选中<br /><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s12.sinaimg.cn/orignal/a459dcf5tc1e35ca9b60b" target="_blank" style="text-decoration: none; color: #006760;"><img src="http://s12.sinaimg.cn/bmiddle/a459dcf5tc1e35ca9b60b&amp;690" real_src="http://s12.sinaimg.cn/bmiddle/a459dcf5tc1e35ca9b60b&amp;690" name="image_operate_88501339082529839" alt="VS2010进行远程调试方法总结" title="VS2010进行远程调试方法总结" style="margin: 0px; padding: 0px; border: 0px; list-style: none;" /></a><br /></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"><div>12、选择需要调试的进程后，单击Attach，就可以调试B机器上的程序。</div><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s15.sinaimg.cn/orignal/a459dcf5tc1e35cba7ace" target="_blank" style="text-decoration: none; color: #006760;"><img src="http://s15.sinaimg.cn/bmiddle/a459dcf5tc1e35cba7ace&amp;690" real_src="http://s15.sinaimg.cn/bmiddle/a459dcf5tc1e35cba7ace&amp;690" name="image_operate_31881339082533986" alt="VS2010进行远程调试方法总结" title="VS2010进行远程调试方法总结" action-data="http%3A%2F%2Fs15.sinaimg.cn%2Fbmiddle%2Fa459dcf5tc1e35cba7ace%26690" action-type="show-slide" style="margin: 0px; padding: 0px; border: 0px; list-style: none;" /></a></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"></div><div style="color: #323e32; font-family: simsun; background-color: #2d220c;"><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=a459dcf5010153o7&amp;url=http://s15.sinaimg.cn/orignal/a459dcf5tc1e35cba7ace" target="_blank" style="text-decoration: none; color: #006760;"></a><div>13、<span style="word-wrap: normal; word-break: normal; line-height: normal; font-size: 13px; font-family: 'segoe Ui', Verdana, Arial;">无法附加到进程解决方案：<br />（1）</span><span style="word-wrap: normal; word-break: normal; line-height: normal; font-size: 13px; font-family: 'segoe Ui', Verdana, Arial; color: #000000; orphans: 2; widows: 2;"><span style="word-wrap: normal; word-break: normal;">从<span style="word-wrap: normal; word-break: normal;">&#8220;开始&#8221;</span>菜单中，选择<span style="word-wrap: normal; word-break: normal;">&#8220;控制面板&#8221;</span>。<br />（2）在&#8220;控制面板&#8221;中双击<span style="word-wrap: normal; word-break: normal;">&#8220;管理工具&#8221;</span>。<br />（3）在&#8220;管理工具&#8221;窗口中双击<span style="word-wrap: normal; word-break: normal;">&#8220;本地安全策略&#8221;</span>。<br />（4）在&#8220;本地安全策略&#8221;窗口中，选择<span style="word-wrap: normal; word-break: normal;">&#8220;本地策略&#8221;</span>。</span></span></div><div><span style="word-wrap: normal; word-break: normal; line-height: normal; font-size: 13px; font-family: 'segoe Ui', Verdana, Arial; color: #000000; orphans: 2; widows: 2;"><span style="word-wrap: normal; word-break: normal;">（5）在<span style="word-wrap: normal; word-break: normal;">&#8220;策略&#8221;</span>列中，双击<span style="word-wrap: normal; word-break: normal;">&#8220;网络访问: 本地帐户的共享和安全模型&#8221;</span>。<br />（6）在<span style="word-wrap: normal; word-break: normal;">&#8220;网络访问: 本地帐户的共享和安全模型&#8221;</span>对话框中，将本地安全设置更改为<span style="word-wrap: normal; word-break: normal;">&#8220;传统型&#8221;</span>并单击<span style="word-wrap: normal; word-break: normal;">&#8220;确定&#8221;</span>。<br /><span style="word-wrap: normal; word-break: normal; line-height: 26px; font-size: 14px; font-family: Arial; color: #333333; background-color: #ffffff;">（7）开启服务TerminalService</span></span></span></div></div><img src ="http://www.cppblog.com/yehao/aggbug/205851.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2014-02-19 15:39 <a href="http://www.cppblog.com/yehao/articles/205851.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WMI常见问题及解决方法</title><link>http://www.cppblog.com/yehao/articles/204269.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Fri, 15 Nov 2013 08:33:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/204269.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/204269.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/204269.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/204269.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/204269.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一．	常见问题及解决方法&nbsp;1.	当通过WMI添加服务器、Microsoft .NET、Exchange服务器时，提示&#8220;验证失败。请确认用户名和密码&#8221;。&nbsp;解决方法: 请以&lt;domainname&gt;\&lt;username&gt;格式输入用户名&nbsp;注意： OpManger中对于本地WMI验证，不需要输入用户名和密码。&nbsp;2.	当以...&nbsp;&nbsp;<a href='http://www.cppblog.com/yehao/articles/204269.html'>阅读全文</a><img src ="http://www.cppblog.com/yehao/aggbug/204269.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2013-11-15 16:33 <a href="http://www.cppblog.com/yehao/articles/204269.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>挂钩注入DLL</title><link>http://www.cppblog.com/yehao/articles/204040.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Fri, 01 Nov 2013 02:52:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/204040.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/204040.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/204040.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/204040.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/204040.html</trackback:ping><description><![CDATA[<p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; margin-top: 10px !important; margin-bottom: 10px !important;">在windows核心编程中的第22章中提到了插入DLL和挂接API这个内容，刚开始看到并不是很明白，所以当时关于注入DLL ，我选取的是一个相对我自己而言比较容易理解的远程注入，在做毕设的过程中，我发现挂钩注入DLL其实是更加方便和强悍的一种方法，我也在网上搜索过很多例子，试图先寻找一个样板依葫芦画瓢，可是一直没有满意的，所以自己下定决心写了一个，发现也没那么难，仔细一点就好了，下面是原理和实现的过程。</p><p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; margin-top: 10px !important; margin-bottom: 10px !important;">众所周知，windows这个强大的消息是基于事件驱动的，事件驱动就会引发消息，所以在窗口接受到消息之前可以对其进行一些你想要的处理就会发生窗口处理消息之前先处理你所需要的操作，就达到了消息过滤的过程，这个主要基于windows的消息机制&#8212;&#8212;系统一旦发生操作就会引发消息，并将消息放到消息队列中，应用程序从消息队列中获取消息并发送到相应的窗口让钩子函数在这个函数&#8220;有机可趁&#8221;。消息过滤与我所要讲的挂钩注入DLL又有什么联系呢，主要是挂钩注入DLL中用到一个函数SetWindowsHookEx，这个函数大家网上一搜一堆解读，这边就不做赘述，其第一个参数就是消息钩子，也就是说，DLL所要注入的那个进程发送了某种消息给窗口后才会引发钩子钩住并注入DLL，这与消息过滤其实是一个意思。我这边主要做的是注入特定的进程，而不是全局钩子，其实全局钩子也很简单，只需要将上述函数的最后一个参数设为0，但这样会导致，但凡发送了相同消息给窗口的都会导致钩子钩住并注入DLL执行相应处理，这样我就不知道是不是我要的线程发送了这个消息，所以最后一个参数我传递了指定线程的ID。下面是实现的过程&#8212;&#8212;将自己写的Hooking.dll通过自己写的应用程序MyHook.exe注入到word进程，目前是在word进程已经存在，由于设置的是WH_CBT钩子，所以一旦word进程最大化或者成为活动窗口之类的就会发送相应的消息，导致相应的处理，这里我只是做简单的处理比如在桌面上建立一个小文件。</p><p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; margin-top: 10px !important; margin-bottom: 10px !important;">1.首先打开VS2008，创建一个工程，在该工程下面创建两个项目，一个是Hooking的DLL项目，一个是MyHook项目，是负责设置挂钩的</p><p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; margin-top: 10px !important; margin-bottom: 10px !important;">2.在该DLL中主要就是挂钩函数SetWindowsHookExW(WH_CBT, HookmProc, g_hinstDll, dwThread)和处理函数LRESULT CALLBACK HookmProc(int nCode, WPARAM wParam, LPARAM lParam)，之所以能将DLL注入到指定进程，就是因为，以dwThread为ID的指定进程向窗口发送与WH_CBT挂钩相关联的消息，导致其执行处理函数HookmProc，而处理函数又在以g_hinstDll为句柄的DLL中，所以必须先将DLL注入到指定进程才能执行该处理函数，处理函数这里只进行了简单的操作证明其注入成功了，例如创建一个桌面文件。这里的DLL的句柄参数就是就是挂钩函数所在的DLL ，但DLL并不执行挂钩函数，而是作为接口，由MyHook.exe调用</p><p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; margin-top: 10px !important; margin-bottom: 10px !important;">3.所以MyHook模块中主要就是加载Hooking.dll调用其接口函数SetHook，以指定被注入的线程的句柄为参数，在这之前，先要遍历系统进程找到WINWORD.EXE并将其线程句柄获得传入，这里用到了快照方法，这个也不做赘述，网上一堆。</p><p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; margin-top: 10px !important; margin-bottom: 10px !important;">4.由此，先启动word进程并将其窗口最小化，然后运行程序就会得到想要的效果，DLL被注入，再最大化word窗口，桌面就会出现小文件</p><p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; margin-top: 10px !important; margin-bottom: 10px !important;">5.总结一下，这中间遇到了一些问题，但都与挂钩注入DLL无关，还是自己的基础不牢。</p><div><span style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px;">下面要考虑的就是，加上监视word启动的代码，这样一旦word启动了就进行上述操作，不启动则不进行</span><span style="font-size: 12px;">Hooking.h:</span></div><div><span style="font-size: 12px;">#ifndef Hooking_H</span></div><div><span style="font-size: 12px;">#define Hooking_H</span></div><div><span style="font-size: 12px;">extern "C" _declspec(dllexport)BOOL WINAPI SetHook(DWORD dwThread);</span></div><div><span style="font-size: 12px;">#endif</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">Hooking.cpp:</span></div><div><span style="font-size: 12px;">#include "stdafx.h"</span></div><div><span style="font-size: 12px;">#include &lt;windows.h&gt;</span></div><div><span style="font-size: 12px;">#include &lt;stdio.h&gt;</span></div><div><span style="font-size: 12px;">#include "Hooking.h"</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">LRESULT CALLBACK HookmProc(int nCode, WPARAM wParam, LPARAM lParam);</span></div><div><span style="font-size: 12px;">HHOOK g_hHook = NULL;</span></div><div><span style="font-size: 12px;">HINSTANCE g_hinstDll = NULL;</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">BOOL WINAPI Typedef_eSetHook(DWORD dwThread)</span></div><div><span style="font-size: 12px;">{</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; g_hinstDll = GetModuleHandle(L"Hooking.dll");</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; g_hHook = SetWindowsHookExW(WH_CBT, HookmProc, g_hinstDll, dwThread);</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; if (NULL == g_hHook)</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; {</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; printf("sethook failed!");</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; }</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; return TRUE;</span></div><div><span style="font-size: 12px;">}</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">LRESULT CALLBACK HookmProc(int nCode, WPARAM wParam, LPARAM lParam)</span></div><div><span style="font-size: 12px;">{</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; CreateFileW(L"C:\\Users\\Administrator\\Desktop\\hook success.txt", GENERIC_READ|GENERIC_WRITE,&nbsp;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL);&nbsp;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; return(CallNextHookEx(g_hHook, nCode, wParam, lParam));</span></div><div><span style="font-size: 12px;">}</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">dllmian.cpp:</span></div><div><span style="font-size: 12px;">LRESULT CALLBACK HookmProc(int nCode, WPARAM wParam, LPARAM lParam);</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">BOOL APIENTRY DllMain( HMODULE hModule,</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DWORD &nbsp;ul_reason_for_call,</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;LPVOID lpReserved</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;)</span></div><div><span style="font-size: 12px;">{</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; switch (ul_reason_for_call)</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; {</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; case DLL_PROCESS_ATTACH:</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; {</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /*g_hCurrentMoudle = hModule;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; g_hHook = SetWindowsHookExW(WH_KEYBOARD, HookmProc, hModule, 0);*/</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //LoadDll();//1.找出感兴趣的进程 2.从证书中获取密钥 3.加载文件过滤DLL</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; }</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; case DLL_THREAD_ATTACH:</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; case DLL_THREAD_DETACH:</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; case DLL_PROCESS_DETACH:</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; break;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; }</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; return TRUE;</span></div><div><span style="font-size: 12px;">}</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">Hooking.def:</span></div><div><span style="font-size: 12px;">LIBRARY &nbsp; &nbsp;"Hooking"</span></div><div><span style="font-size: 12px;">EXPORTS</span></div><div><span style="font-size: 12px;">Typedef_eSetHook @1<br /><br /><br /></span><p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; background-color: #ffffff; margin-top: 10px !important; margin-bottom: 10px !important;">在windows核心编程中的第22章中提到了插入DLL和挂接API这个内容，刚开始看到并不是很明白，所以当时关于注入DLL ，我选取的是一个相对我自己而言比较容易理解的远程注入，在做毕设的过程中，我发现挂钩注入DLL其实是更加方便和强悍的一种方法，我也在网上搜索过很多例子，试图先寻找一个样板依葫芦画瓢，可是一直没有满意的，所以自己下定决心写了一个，发现也没那么难，仔细一点就好了，下面是原理和实现的过程。</p><p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; background-color: #ffffff; margin-top: 10px !important; margin-bottom: 10px !important;">众所周知，windows这个强大的消息是基于事件驱动的，事件驱动就会引发消息，所以在窗口接受到消息之前可以对其进行一些你想要的处理就会发生窗口处理消息之前先处理你所需要的操作，就达到了消息过滤的过程，这个主要基于windows的消息机制&#8212;&#8212;系统一旦发生操作就会引发消息，并将消息放到消息队列中，应用程序从消息队列中获取消息并发送到相应的窗口让钩子函数在这个函数&#8220;有机可趁&#8221;。消息过滤与我所要讲的挂钩注入DLL又有什么联系呢，主要是挂钩注入DLL中用到一个函数SetWindowsHookEx，这个函数大家网上一搜一堆解读，这边就不做赘述，其第一个参数就是消息钩子，也就是说，DLL所要注入的那个进程发送了某种消息给窗口后才会引发钩子钩住并注入DLL，这与消息过滤其实是一个意思。我这边主要做的是注入特定的进程，而不是全局钩子，其实全局钩子也很简单，只需要将上述函数的最后一个参数设为0，但这样会导致，但凡发送了相同消息给窗口的都会导致钩子钩住并注入DLL执行相应处理，这样我就不知道是不是我要的线程发送了这个消息，所以最后一个参数我传递了指定线程的ID。下面是实现的过程&#8212;&#8212;将自己写的Hooking.dll通过自己写的应用程序MyHook.exe注入到word进程，目前是在word进程已经存在，由于设置的是WH_CBT钩子，所以一旦word进程最大化或者成为活动窗口之类的就会发送相应的消息，导致相应的处理，这里我只是做简单的处理比如在桌面上建立一个小文件。</p><p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; background-color: #ffffff; margin-top: 10px !important; margin-bottom: 10px !important;">1.首先打开VS2008，创建一个工程，在该工程下面创建两个项目，一个是Hooking的DLL项目，一个是MyHook项目，是负责设置挂钩的</p><p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; background-color: #ffffff; margin-top: 10px !important; margin-bottom: 10px !important;">2.在该DLL中主要就是挂钩函数SetWindowsHookExW(WH_CBT, HookmProc, g_hinstDll, dwThread)和处理函数LRESULT CALLBACK HookmProc(int nCode, WPARAM wParam, LPARAM lParam)，之所以能将DLL注入到指定进程，就是因为，以dwThread为ID的指定进程向窗口发送与WH_CBT挂钩相关联的消息，导致其执行处理函数HookmProc，而处理函数又在以g_hinstDll为句柄的DLL中，所以必须先将DLL注入到指定进程才能执行该处理函数，处理函数这里只进行了简单的操作证明其注入成功了，例如创建一个桌面文件。这里的DLL的句柄参数就是就是挂钩函数所在的DLL ，但DLL并不执行挂钩函数，而是作为接口，由MyHook.exe调用</p><p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; background-color: #ffffff; margin-top: 10px !important; margin-bottom: 10px !important;">3.所以MyHook模块中主要就是加载Hooking.dll调用其接口函数SetHook，以指定被注入的线程的句柄为参数，在这之前，先要遍历系统进程找到WINWORD.EXE并将其线程句柄获得传入，这里用到了快照方法，这个也不做赘述，网上一堆。</p><p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; background-color: #ffffff; margin-top: 10px !important; margin-bottom: 10px !important;">4.由此，先启动word进程并将其窗口最小化，然后运行程序就会得到想要的效果，DLL被注入，再最大化word窗口，桌面就会出现小文件</p><p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; background-color: #ffffff; margin-top: 10px !important; margin-bottom: 10px !important;">5.总结一下，这中间遇到了一些问题，但都与挂钩注入DLL无关，还是自己的基础不牢。</p><p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; background-color: #ffffff; margin-top: 10px !important; margin-bottom: 10px !important;">下面要考虑的就是，加上监视word启动的代码，这样一旦word启动了就进行上述操作，不启动则不进行</p><span style="font-size: 12px;"><br /></span><div><span style="font-size: 12px;">MyHook.h:</span></div><div><span style="font-size: 12px;">#pragma once</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">typedef BOOL(WINAPI *Typedef_eSetHook)(DWORD);</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">extern Typedef_eSetHook SetHook;</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">MyHook.cpp:</span></div><div><span style="font-size: 12px;">#include &lt;Windows.h&gt;</span></div><div><span style="font-size: 12px;">#include &lt;TlHelp32.h&gt;</span></div><div><span style="font-size: 12px;">#include "stdio.h"</span></div><div><span style="font-size: 12px;">#include "MyHook.h"</span></div><div><span style="font-size: 12px;">#include &lt;conio.h&gt;</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">Typedef_eSetHook &nbsp;SetHook = NULL;</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">BOOL LoadNativeLibrary()</span></div><div><span style="font-size: 12px;">{</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; HMODULE hDll = LoadLibraryW(L"..\\Debug\\Hooking.dll");</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; if (hDll != NULL)</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; {</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; SetHook = (Typedef_eSetHook)GetProcAddress(hDll, MAKEINTRESOURCEA(1));</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; }</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; else</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; {</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; printf("LoadLibrary failed\n");</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; }</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; if(NULL == SetHook)</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; { &nbsp; &nbsp;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; printf("SetHook is null\n");</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; OutputDebugStringA("0x103200 no init func.");</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; }</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; return TRUE;</span></div><div><span style="font-size: 12px;">}</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">int main()</span></div><div><span style="font-size: 12px;">{</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; LoadNativeLibrary();</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; DWORD dwProcessID = 0;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, dwProcessID);</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; if (hSnapshot == NULL)</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; {</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; return 0;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; }</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; PROCESSENTRY32 processinfo = {0};</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; processinfo.dwSize = sizeof(processinfo);</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; Process32FirstW(hSnapshot, &amp;processinfo);</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; do&nbsp;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; {</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; if (0 == lstrcmpiW(processinfo.szExeFile, L"WINWORD.EXE"))</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; {</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dwProcessID = processinfo.th32ProcessID;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; }</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; } while (Process32NextW(hSnapshot, &amp;processinfo));</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; CloseHandle(hSnapshot);</span></div><div><span style="font-size: 12px;"><br /></span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; unsigned long pTID;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; _asm {&nbsp;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; mov eax, fs:[0x18]&nbsp;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; add eax, 36&nbsp;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mov [pTID], eax&nbsp;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; }&nbsp;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; DWORD threadID;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; HANDLE hProcess = OpenProcess(PROCESS_VM_READ, false, dwProcessID);&nbsp;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; ReadProcessMemory(hProcess, (const void *)pTID, &amp;threadID, 4, NULL);&nbsp;</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; SetHook(threadID);</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; printf("...");</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; getche();</span></div><div><span style="font-size: 12px;">&nbsp; &nbsp; return 0;</span></div><div><span style="font-size: 12px;">}<br /></span><p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; margin-top: 10px !important; margin-bottom: 10px !important;">其实一开始我主要是纠结于哪个函数放在哪个cpp还是dll里面，还有word干嘛了会让setwindowshook函数将dll注入到其进程。后来我想自己肯定要有一个应用程序去执行挂钩这个过程，本来想把setwindowshook这个函数也放在自己的应用程序里，后来想想最好把其和处理函数放在一起，然后处理函数必然要在dll里，于是就把setwindowshook函数也放在dll里，因为放在dll里他也不会执行，只要自己的应用程序去执行就行了，所以把setwindowshook这个函数封装起来作为接口传给自己的应用程序，应用程序一调用就进行挂钩了而且也把这个dll注入到了相应进程了。</p><p style="color: #7b7d62; font-family: verdana, Arial, helvetica, sans-seriff, ����; font-size: 13px; line-height: 19px; margin-top: 10px !important; margin-bottom: 10px !important;">以上肯定还有很多不完善和不正确的表述，也欢迎大家指出，谢谢！！！</p></div></div><img src ="http://www.cppblog.com/yehao/aggbug/204040.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2013-11-01 10:52 <a href="http://www.cppblog.com/yehao/articles/204040.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跟大家分享一下directUI的心得</title><link>http://www.cppblog.com/yehao/articles/203995.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Wed, 30 Oct 2013 04:23:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/203995.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/203995.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/203995.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/203995.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/203995.html</trackback:ping><description><![CDATA[<span style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">0. WPF, Windows Live, QQ 和 百度 hi 的界面其实并不神秘。大家都想学习而不得其门而入。我也经历了跟大家同样的历程。现在发现了一些门道，跟大家分享一下。&nbsp;</span><br style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;" /><span style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">1. 所谓 directUI 其实大部分不是真的用DirectX技术做的。其实他也是用的GDI和GDI+的函数绘制出来的。&nbsp;</span><br style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;" /><span style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">2. 那些看起来非常漂亮的界面效果在《Windows 图形编程》这本书里面基本都有描述如何实现。下载：</span><a href="http://download.csdn.net/source/170911" style="text-decoration: none; color: #0196e3; font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">http://download.csdn.net/source/170911</a>&nbsp;<br style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;" /><span style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">3. directUI上的按钮，滚动条，等等其他控件都是自己一笔一划画出来的。看起来一笔一画很复杂。说白了就是用各种画线的函数，还有画块的函数综合搭配起来实现我们想要的效果。 GDI+为我们提供了一些效果的函数，比如渐变填充等等。其实我建议大家学习一下photoshop里面的技法。这些技法其实都是我们可以自己用代码实现的算法。&nbsp;</span><br style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;" /><span style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">4. directUI上的消息分发也都是需要自己做的。也就不到一百个把。&nbsp;</span><br style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;" /><span style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">5. directUI的例子代码：</span><a href="http://www.viksoe.dk/code/windowless1.htm" style="text-decoration: none; color: #0196e3; font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">http://www.viksoe.dk/code/windowless1.htm</a>&nbsp;<br style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;" /><span style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">6. 在directUI的所有控件中，无窗口富文本编辑框比较特殊。他需要使用windowless richedit技术。涉及ITextService和ITextHost接口。在这里有例子：</span><a href="http://support.microsoft.com/kb/270161" style="text-decoration: none; color: #0196e3; font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">http://support.microsoft.com/kb/270161</a>&nbsp;<br style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;" /><span style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">7. 这一点我正在探索。在 windowsless richedit 中实现图像和其他复杂文档对象，也就是在windows live 和 QQ 中贴图这种操作，需要对OLE对象的编辑功能。这就需要CRichEditOleCallback 和 IRichEditOle 接口。在这里有例子：</span><a href="http://support.microsoft.com/kb/141549" style="text-decoration: none; color: #0196e3; font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">http://support.microsoft.com/kb/141549</a>&nbsp;<br style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;" /><span style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">8. WPF，Windows Live, QQ 和 百度hi他们都利用xml来控制控件的位置风格那些。其实他们都是为公司自己做的foundation库，为了考虑复用才这样做的。我们自己做的话可以不用xml。自己按照自己想做的样子写C++代码就行了。&nbsp;</span><br style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;" /><span style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">最后，做directUI是一个非常耗时的过程。大家可以以</span><a href="http://www.viksoe.dk/code/windowless1.htm" style="text-decoration: none; color: #0196e3; font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">http://www.viksoe.dk/code/windowless1.htm</a><span style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">为基础实现自己的directUI。能节约一些时间。&nbsp;</span><br style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;" /><span style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">另外付一个我的作品：</span><a href="http://boogu.me/" style="text-decoration: none; color: #0196e3; font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">http://boogu.me/</a><span style="font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 24px; text-indent: 26px;">&nbsp;。这就是用我上面所说的技术实现的。现在我正在实现在文字块中显示ole对象。</span><img src ="http://www.cppblog.com/yehao/aggbug/203995.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2013-10-30 12:23 <a href="http://www.cppblog.com/yehao/articles/203995.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DirectUI的初步分析</title><link>http://www.cppblog.com/yehao/articles/203994.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Wed, 30 Oct 2013 04:21:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/203994.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/203994.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/203994.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/203994.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/203994.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 最近由于项目的需要学习了一下DirectUI方面的东西,主要借鉴的是一个国外程序员写的代码(见引用一),看了后发现它更多的是探讨一种实现的可能性和思路,和实际应用还是有距离的,不过其实现还是很有意思的。在写此小结的时候又发现国内一个程序员将这个代码部分移植到WINCE下的代码(见引用二),因为平台的差异性要完全开发一个WINCE下的实际代码还是需要时间的。&nbsp;由于本人GUI开发做得少,工作...&nbsp;&nbsp;<a href='http://www.cppblog.com/yehao/articles/203994.html'>阅读全文</a><img src ="http://www.cppblog.com/yehao/aggbug/203994.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2013-10-30 12:21 <a href="http://www.cppblog.com/yehao/articles/203994.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC++实现透明位图显示</title><link>http://www.cppblog.com/yehao/articles/203950.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Mon, 28 Oct 2013 08:41:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/203950.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/203950.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/203950.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/203950.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/203950.html</trackback:ping><description><![CDATA[<div>http://express.ruanko.com/ruanko-express_17/webpage/tech3.html<br /><br /><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: 楷体_GB2312; background-color: #eeeeee;">摘要：通过描述位图内存和视频内存原理，通过五子棋棋子透明显示在棋盘上，说明VC++中位图操作和如何实现透明位图显示。</p><h2>1、实现原理</h2><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;">计算机视频系统核心是内存，位图操作涉及到视频内存和位图内存。每次以及每一个图形操作都会影响视频内存，位图内存为一块类似于视频内存的RAM区域，它代表一个容纳数据的内存地址，二者极为相识，区别在于位图内存看不到，而视频内存看的到。位图驻留在位图内存中，如果被移到视频内存，则将显示在监视器上。</p><h2>2、实现方法</h2><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;">绘制透明位图是指绘制某一位图中除指定颜色外的其余部分，我们称这种颜色为透明色。通过将位图的背景色指定为透明色，在绘制时，不绘制这部分背景，而仅绘制图像，这样就可以将位图中图像透明地绘制到窗口上。如下图1所示。</p><p align="center" style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;"><img src="http://express.ruanko.com/ruanko-express_17/images/tech3.1.jpg" width="444" height="121"  alt="" /><br /><span style="font-family: 楷体_GB2312; font-size: 12px;">图1 位图透明显示事例</span></p><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;">绘制透明位图的关键是创建一个掩码位图，掩码位图是一个单色位图，它是位图中图像的一个单色剪影。在Windows编程中，绘图都要用到设备描述表，需创建两个内存设备描述表：源位图设备描述表和掩码位图设备描述表。源位图设备描述表用来装入源位图，而掩码位图设备描述表用来装入掩码位图。使用BitBlt执行相应光栅操作，将源位图透明地绘制在目的位图上。</p><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;">在目的位图上实现源位图透明显示步骤：</p><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;">（1）首先，源位图与掩码位图进行SRCPAINT操作，即使用布尔OR操作将二者组合在一起；</p><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;">（2）其次，目的位图与掩码位图进行MERGEPAINT操作，即使用布尔OR操作将取反后的掩码位图与目的位图组合在一起；</p><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;">（3）最后，目的位图与源位图进行SRCAND操作，即使用布尔AND操作将二者组合在一起。</p><h2>3、位图透明显示流程</h2><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;">（1）将位图装载到CBitmap对象；</p><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;">（2）创建一个与视频设备描述表兼容的位图设备描述表；</p><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;">（3）将CBitmap对象选入最新创建的设备描述表中；</p><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;">（4）使用GetObject()填写BITMAP结构，以使了解位图大小；</p><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;">（5）源位图与掩码位图进行BitBlt()，使用SRCPAINT光栅操作码，将二者合在一起，此部处理源位图；</p><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;">（6）目的位图与掩码位图进行BitBlt()，使用MERGEPAINT光栅操作码，将二者合在一起；</p><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;">（7）目的位图与掩码位图进行BitBlt()，使用SRCAND光栅操作码，实现源位图透明显示。</p><h2>4、事例</h2><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;">以五子棋为例，实现棋子在棋盘透明显示，一般情况下，棋盘是带有背景色的，棋子为黑白色（或者其它透明颜色）矩形，当棋子粘贴到棋盘上时，去除四个拐角，形成圆形棋子被放置到棋盘上，同时保留自身颜色，棋子中透明颜色都被保持不变。</p><p style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;">下图2为掩码、棋子、棋盘的显示，经过BitBlt相应光栅操作后，图3就是白色棋子透明显示。</p><p align="center" style="text-indent: 2em; letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee;"><img src="http://express.ruanko.com/ruanko-express_17/images/tech3.2.jpg" width="498" height="414"  alt="" /></p><ol style="letter-spacing: 1px; line-height: 20px; font-family: Arial, Verdana, Helvetica, sans-serif; background-color: #eeeeee; list-style-type: none; margin-left: 0px;"><li>（1）定义位图和设备描述表变量</li><div style="width: 521.546875px; border: 1px dotted #d2d2d2; margin-top: 0px; margin-bottom: 1em; margin-left: 0px; font-size: 12px; background-color: #ffe0b3; font-family: Arial, Helvetica, sans-serif;"><pre>CBitmap m_ChessBoard_Bitmap;	//棋盘位图对象 CBitmap m_BlackChess_Bitmap;  	//黑棋子位图对象 CBitmap m_WhiteChess_Bitmap;  	//白棋子位图对象 CBitmap m_Mask_Bitmap;		//掩码的位图对象 CDC *pCurrent_DC;	        //当前窗口的DC指针 CDC m_BlackChess_DC;	        //粘贴黑棋子的DC CDC m_WhiteChess_DC;		//粘贴黑棋子的DC CDC m_Complex_DC;		//粘贴棋盘的DC CDC m_Mask_DC;			//粘贴掩码的DC </pre></div><li>（2）装载位图，将相应位图邦定到CBitmap</li><div style="width: 521.546875px; border: 1px dotted #d2d2d2; margin-top: 0px; margin-bottom: 1em; margin-left: 0px; font-size: 12px; background-color: #ffe0b3; font-family: Arial, Helvetica, sans-serif;"><pre>m_ChessBoard_Bitmap.LoadBitmap(IDB_BITMAP_ChessBoard);// 棋盘 m_BlackChess_Bitmap.LoadBitmap(IDB_BITMAP_BlackChess);// 黑棋子 m_WhiteChess_Bitmap.LoadBitmap(IDB_BITMAP_WhiteChess);// 白棋子 m_Mask_Bitmap.LoadBitmap(IDB_BITMAP_Mask);// 掩码 </pre></div><li>（3）获取位图结构</li><div style="width: 521.546875px; border: 1px dotted #d2d2d2; margin-top: 0px; margin-bottom: 1em; margin-left: 0px; font-size: 12px; background-color: #ffe0b3; font-family: Arial, Helvetica, sans-serif;">BITMAP m_ChessBoard_BITMAP;　　//棋盘的位图结构实例<br />BITMAP m_BlackChess_BITMAP;　　//黑棋的位图结构实例（黑棋与白棋一样）<br /><br />//将CBitmap对象的属性赋予BITMAP结构体实例<br />m_ChessBoard_Bitmap.GetBitmap(&amp;m_ChessBoard_BITMAP);<br />m_BlackChess_Bitmap.GetBitmap(&amp;m_BlackChess_BITMAP);</div><li>（4）创建与视频设备描述表兼容的位图设备描述表，将CBitmap对象选入最新创建的设备描述表中。</li><div style="width: 521.546875px; border: 1px dotted #d2d2d2; margin-top: 0px; margin-bottom: 1em; margin-left: 0px; font-size: 12px; background-color: #ffe0b3; font-family: Arial, Helvetica, sans-serif;"><pre>//为黑棋子DC申请一定的资源并绑定相应的棋子CBitmap对象 m_BlackChess_DC.CreateCompatibleDC(pCurrent_DC); m_BlackChess_DC.SelectObject(&amp;m_BlackChess_Bitmap);  //为白棋子DC申请一定的资源并绑定相应的棋子CBitmap对象 m_WhiteChess_DC.CreateCompatibleDC(pCurrent_DC); m_WhiteChess_DC.SelectObject(&amp;m_WhiteChess_Bitmap);  //为棋盘DC申请一定的资源并绑定相应的棋子CBitmap对象 m_Complex_DC.CreateCompatibleDC(pCurrent_DC); m_Complex_DC.SelectObject(&amp;m_ChessBoard_Bitmap);  //为掩码DC申请一定的资源并初始绑定相应的CBitmap对象 m_Mask_DC.CreateCompatibleDC(pCurrent_DC); m_Mask_DC.SelectObject(&amp;m_Mask_Bitmap); </pre></div><li>（5）设置白棋和黑棋为圆形的棋子，为将方形的棋子处理成圆形的棋子而将棋子图片与掩码图片进行混合操作。</li><div style="width: 521.546875px; border: 1px dotted #d2d2d2; margin-top: 0px; margin-bottom: 1em; margin-left: 0px; font-size: 12px; background-color: #ffe0b3; font-family: Arial, Helvetica, sans-serif;"><pre>m_BlackChess_DC.BitBlt(0, 0, m_BlackChess_BITMAP.bmWidth,  m_BlackChess_BITMAP.bmHeight,   &amp;m_Mask_DC, 0, 0, SRCPAINT); m_WhiteChess_DC.BitBlt(0, 0, m_BlackChess_BITMAP.bmWidth,  m_BlackChess_BITMAP.bmHeight,   &amp;m_Mask_DC, 0, 0, SRCPAINT); </pre></div><li>（6）将棋子放置到棋盘上，即在相应的位置取得白色圆形棋子</li><div style="width: 521.546875px; border: 1px dotted #d2d2d2; margin-top: 0px; margin-bottom: 1em; margin-left: 0px; font-size: 12px; background-color: #ffe0b3; font-family: Arial, Helvetica, sans-serif;"><pre>int m_ChessPicture_Size = m_BlackChess_BITMAP.bmWidth;// 棋子图片的宽度 //int Current_X为鼠标当前坐标点X坐标 // int Current_Y为鼠标当前坐标点Y坐标 m_Complex_DC.BitBlt(Current_X - m_ChessPicture_Size/2,  Current_Y &#8211; m_ChessPicture_Size/2, m_ChessPicture_Size, m_ChessPicture_Size, &amp;m_Mask_DC, 0, 0, MERGEPAINT); m_Complex_DC.BitBlt(Current_X - m_ChessPicture_Size/2,  Current_Y - m_ChessPicture_Size/2, m_ChessPicture_Size, m_ChessPicture_Size, &amp;m_WhiteChess_DC, 0, 0, SRCAND); </pre></div><li>（7）得到本窗口的客户区</li><div style="width: 521.546875px; border: 1px dotted #d2d2d2; margin-top: 0px; margin-bottom: 1em; margin-left: 0px; font-size: 12px; background-color: #ffe0b3; font-family: Arial, Helvetica, sans-serif;"><pre>CRect m_current_Wnd_Rect;		//当前窗口的客户端的矩形 GetClientRect(&amp;m_current_Wnd_Rect);	//得到本窗口的客户区 </pre></div><li>（8）在OnPaint()中，将棋盘绘制在窗口上显示</li><div style="width: 521.546875px; border: 1px dotted #d2d2d2; margin-top: 0px; margin-bottom: 1em; margin-left: 0px; font-size: 12px; background-color: #ffe0b3; font-family: Arial, Helvetica, sans-serif;"><pre>CPaintDC dc(this); // device context for painting	 //粘贴含有棋子的棋盘DC到该窗口上 dc.BitBlt(0, 0, m_current_Wnd_Rect.Width(), m_current_Wnd_Rect.Height(), &amp;m_Complex_DC, 0, 0,  SRCCOPY);</pre></div></ol></div><img src ="http://www.cppblog.com/yehao/aggbug/203950.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2013-10-28 16:41 <a href="http://www.cppblog.com/yehao/articles/203950.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用IE调试ActiveX控件的相关设置(无法启动调试信息,找不到Microsoft Internet Explorer的解决方法)</title><link>http://www.cppblog.com/yehao/articles/203052.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Fri, 06 Sep 2013 08:34:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/203052.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/203052.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/203052.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/203052.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/203052.html</trackback:ping><description><![CDATA[<p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px;">转自<a href="http://blog.csdn.net/uqapuqap/article/details/6744163">http://blog.csdn.net/uqapuqap/article/details/6744163</a><br />VS2010设置篇：</p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px;">&nbsp;&nbsp;&nbsp; 设置VS2010 通过IE8 调试ATL的ActiveX控件的步骤如下：</p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px;">（1）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;设置项目属性</p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px;">通过菜单项 &#8220;项目&#8212;》你的项目属性&#8221;如下图：<img src="http://hi.csdn.net/attachment/201109/2/0_1314964891gtFh.gif" alt="" style="border: none; max-width: 100%;" /></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px;">（2）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在弹出的属性页对话框中选中&#8220;配置属性&#8212;》调试&#8221;，在右边填入下列参数：</p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px;">命令&nbsp;&nbsp;&nbsp;&nbsp; ：C:/ProgramFiles/Internet Explorer/iexplore.exe（你的IE8执行文件位置）</p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px;">命令参数 ：$(InputDir)FileUploader.htm（其中FileUploader.htm更换成VS为你生成的Html文件名。</p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px;">附加&nbsp;&nbsp;&nbsp; ：否。（指示调试器不要附加现有IE进程，而是新建一个）</p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px;">其它选项采用默认值即可。结果如下图：<img src="http://hi.csdn.net/attachment/201109/2/0_1314964970J1g6.gif" alt="" style="border: none; max-width: 100%;" /></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px;">IE8设置篇：</p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px;">（1）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;设置IE8为单进程模式。</p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px;">运行gpedit.msc组策略管理器。在&#8220;计算机配置&#8212;》管理模板&#8212;》windows组件&#8212;》Internet Explore&#8221;中打开&#8220;选项卡进程增长&#8221;，设置为已启用，选项卡进程增长为0。应用之后IE8就进入单进程模式。这时VS只要直接按F5就能直接进入调试进程，激活断点。设置图如下：<img src="http://hi.csdn.net/attachment/201109/2/0_1314964976dTOd.gif" alt="" style="border: none; max-width: 100%;" /></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px;">（2）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 设置允许活动内容运行。</p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px;">在启动调试，网页经常会呈现如下提示框，每次都要确认，很麻烦。</p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px;">以下方法可以消除这个提示框。</p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px;">在IE中打开Internet 选项对话框，选择高级选项卡，勾选里面的&#8220;允许活动内容在我的计算机上运行&#8221;，重启IE就可以消除这个烦人的提示框。<img src="http://hi.csdn.net/attachment/201109/2/0_13149649803iw5.gif" alt="" style="border: none; max-width: 100%;" /></p><img src ="http://www.cppblog.com/yehao/aggbug/203052.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2013-09-06 16:34 <a href="http://www.cppblog.com/yehao/articles/203052.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SetProcessWorkingSetSize函数的骗局</title><link>http://www.cppblog.com/yehao/articles/200447.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Tue, 21 May 2013 12:02:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/200447.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/200447.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/200447.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/200447.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/200447.html</trackback:ping><description><![CDATA[<p>转<a href="http://blog.sina.com.cn/s/blog_49f8960e0100081x.html">http://blog.sina.com.cn/s/blog_49f8960e0100081x.html</a><br /><br />我实在不愿意提起这个话题.后来在网上看到几篇文章,深深感觉到,已经有程序员站出来,揭穿这个忽悠了千百万用户的诡计了...<br />附2篇文章的地址:<br /><a href="http://blog.csdn.net/biku/archive/2006/07/06/886038.aspx">http://blog.csdn.net/biku/archive/2006/07/06/886038.aspx</a><br /><a href="http://blog.csdn.net/zlt982001/archive/2005/08/28/466879.aspx">http://blog.csdn.net/zlt982001/archive/2005/08/28/466879.aspx</a><br />我这篇文章无非是归纳了几篇文章的内容,并深入的阐明恶意使用该技术带来的坏处.<br />请一味追求低内存软件的用户们注意了:什么才应该是选择软件的主要因素.</p>
<p>物理内存和虚拟内存</p>
<p>物理内存,在应用中,自然是顾名思义,物理上,真实的插在板子上的内存是多大就是多大了.看机器配置的时候,看的就是这个物理内存.</p>
<p>如果执行的程序很大或很多,就会导致物理内存消耗殆尽.为了解决这个问题,Windows中运用了虚拟内存技术,即拿出一部分硬盘空间来充当内存使用,当内存占用完时,电脑就会自动调用硬盘来充当内存,以缓解内存的紧张.</p>
<p>一个程序,不可避免地要用到虚拟内存,因为不频繁执行或者已经很久没有执行的代码,没有必要留在物理内存中,只会造成浪费;放在虚拟内存中,等执行这部分代码的时候,再调出来.<br />Windows 的任务管理器可以帮助我们看到进程的虚拟内存.调出任务管理器,点击菜单&#8220;查看&#8221;－&#8220;选择列&#8221;,在出现的窗口中,钩上&#8220;虚拟内存大小</p>
<p>一个程序到底应该使用多少虚拟内存呢?不一定,但是应该以恰到好处的符合虚拟内存原本作用为最好.<br />下面将揭穿表面看起来调用了大量图片、大量运行库的程序,为什么才&#8220;占用&#8221;不到 1 MB 的内存的诡计.</p>
<p>原来是 SetProcessWorkingSetSize<wbr> 函数</p>
<p>MSDN 对该函数的表述(翻译):使用这个函数来设置应用程序最小和最大的运行空间,只会保留需要的内存.当应用程序被闲置或系统内存太低时,操作系统会自动调用这个机制来设置应用程序的内存.应用程序也可以使用 VirtualLock 来锁住一定范围的内存不被系统释放;当你加大运行空间给应用程序,你能够得到的物理内存取决于系统,这会造成其他应用程序降低性能或系统总体降低性能,这也可能导致请求物理内存的操作失败,例如:建立进程,线程,内核池,就必须小心的使用该函数.</p>
<p>也就是说,该函数不是节省内存,而是强制把进程的物理内存搬到虚拟内存中.</p>
<p>另外有一些资料上说,该函数&#8220;将有可能导致缺页中断,严重影响性能&#8221;.<br />函数原型:<br />BOOL SetProcessWorkingSetSize<wbr>(<br />HANDLE hProcess,<br />SIZE_T dwMinimumWorkingSetSize,<br />SIZE_T dwMaximumWorkingSetSize<br />);<br />我们用 VB 来做这么一个简单的例子,是程序占用 300 KB 内存吧.</p>
<p>建立一个标准的 VB 工程,在 Form1 中放置一个 Timer1 ,把 Interval 属性设置为 1000 (即 1 秒).然后在代码编辑框中输入以下代码:</p>
<p>Private Declare Function SetProcessWorkingSetSize<wbr> Lib "kernel32" (ByVal hProcess As Long, ByVal dwMinimumWorkingSetSize As Long, ByVal dwMaximumWorkingSetSize As Long) As Long<br />Private Declare Function GetCurrentProcess Lib "kernel32" () As Long<br />Private Sub Timer1_Timer()<br />SetProcessWorkingSetSize<wbr> GetCurrentProcess(), 50000, 100000<br />End Sub<br />然后生成 工程1.exe,执行,调出任务管理器查看,发现内存占用才 320 KB.如果把定时器关闭,这进程的内存一般 4 MB左右.<br />必须定时执行该函数,否则虚拟内存会慢慢被调出来,恢复原来的内存大小.<br />如果要使一个本来需要占用大量内存的程序减低到几百 KB ,使用同样的方法即可.</p>
<p>诡计带来的危害</p>
<p>如果 SetProcessWorkingSetSize<wbr> 函数被正常使用,是非常有用处的.但是为了蒙骗用户的眼睛,每秒,甚至几十毫秒就把大量内存往虚拟内存里面压,就会带来无可预计的危害.看看这篇文章怎么说:&#8220;因为他只是暂时的将应用程序占用的内存移至虚拟内存,一旦,应用程序被激活或者有操作请求时,这些内存又会被重新占用.如果你强制使用该方法来设置程序占用的内存,那么可能在一定程度上反而会降低系统性能,因为系统需要频繁的进行内存和硬盘间的页面交换.&#8221;.</p>
<p>没错,如果你使用了这类软件,意味着你的硬盘将每秒将 I/O 大量数据;硬盘的磁针将拼命旋转...(当然硬盘磁针不可能不旋转^_^,只是选择得更厉害而已).</p>
<p>不是说 BT 很伤内存吗?不然,因为现在大多 BT 软件都有缓存技术.且看 Bitcomet 官方对缓存技术的说明:&#8220;传统BT高速下载时硬盘会响得很厉害,这是大量的随机读取造成的.... BitComet可以由用户设置缓存大小.... 可以明显地看出牺牲一小部分内存作缓存对硬盘的保护作用.&#8221;</p>
<p>是不是有种心寒的感觉?一类软件宁愿牺牲内存,也要减少保护硬盘;而另外一类软件,却为了欺骗用户,让CPU、硬盘更加奔波......</p>
<p>抓一个凶手</p>
<p>这类软件不少,我以其中一个桌面工具为例,揭穿它的假面具(不点名字了).运行该软件后,随意操作一下,然后打开进程管理器,把虚拟内存列调出来,找到该进程,如图3:</p>
<p>OK,20 MB 虚拟内存,而只有 632 KB 物理内存.细心的你会发现,大概每 1 秒,该行都有闪烁的感觉,没错,这正是每秒调用 SetProcessWorkingSetSize<wbr> 的结果.另外,我们打开 Norton Process Viewer ,查看该进程的 CPU 占用情况,如图4:</p>
<p>可以看到,就算没有操作该软件,但是每秒,都有 3% 的CPU占用起伏(虽然这并不能说明什么).另外,内存框中可以看到物理内存和虚拟内存的占用,两者相去甚远.此外,可以用 Hook API 技术来证明每秒调用 SetProcessWorkingSetSize<wbr> 的行为.</p>
<p>应该怎么做</p>
<p>这篇文章只想让用户了解软件占用资源的实际.而程序员应该把下功夫,真正从代码中减少内存的消耗,而不是一味忽悠用户.调用 SetProcessWorkingSetSize<wbr> 会带来某些好处,但是何时调用、如何调用应该符合两个要求:<br />1,在程序暂时不被使用的时候(例如最小化);<br />2,物理内存和虚拟内存应处于一个合适的比例(而不是 600 KB 比 20 MB 这么荒唐);<br />3,或者不调用,让 Windows 去处理.<br /></p><img src ="http://www.cppblog.com/yehao/aggbug/200447.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2013-05-21 20:02 <a href="http://www.cppblog.com/yehao/articles/200447.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mfc 在webbrowser控件中动态执行js代码</title><link>http://www.cppblog.com/yehao/articles/195984.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Tue, 04 Dec 2012 11:06:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/195984.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/195984.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/195984.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/195984.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/195984.html</trackback:ping><description><![CDATA[<ul style="padding: 5px; margin: 0px; width: 648px; color: #333333; font-family: Arial; line-height: 17px; ">void CBlogExplorerDlg::OnNavigateComplete2Explorer1(LPDISPATCH pDisp, VARIANT FAR* URL)&nbsp;<br style="padding: 0px; margin: 0px; " />{<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//添加NavigateComplete2这个消息事件，加入以下代码<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IHTMLDocument2&nbsp;&nbsp; *objDocument=NULL;<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IHTMLWindow2* pIHTMLWindow = NULL;<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;objDocument=(IHTMLDocument2 *)m_ie.GetDocument();<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(objDocument)<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;objDocument-&gt;get_parentWindow(&amp;pIHTMLWindow);<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(pIHTMLWindow)<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CString&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;js_str="window.alert=null;window.confirm=null;window.open = null;window.showModalDialog = null;window.onerror=function(){return true}";//这段js代码是禁止弹出一些对话框以及容错的<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VARIANT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pvarRet;<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pIHTMLWindow-&gt;execScript(CComBSTR(js_str), CComBSTR("JavaScript"), &amp;pvarRet);<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pIHTMLWindow-&gt;Release();<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;objDocument-&gt;Release();<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br style="padding: 0px; margin: 0px; " />}</ul><img src ="http://www.cppblog.com/yehao/aggbug/195984.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2012-12-04 19:06 <a href="http://www.cppblog.com/yehao/articles/195984.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mfc CWebBrowser2获取网页源代码</title><link>http://www.cppblog.com/yehao/articles/195983.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Tue, 04 Dec 2012 11:06:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/195983.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/195983.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/195983.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/195983.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/195983.html</trackback:ping><description><![CDATA[<ul style="padding: 5px; margin: 0px; width: 648px; color: #333333; font-family: Arial; line-height: 17px; "><a href="http://www.zhidao123.net/html/content/1/html_263.html">http://www.zhidao123.net/html/content/1/html_263.html</a>&nbsp;<br />IHTMLDocument2&nbsp;&nbsp; *objDocument=NULL;<br style="padding: 0px; margin: 0px; " />CComPtr&lt;IHTMLElement&gt; m_pBody;<br style="padding: 0px; margin: 0px; " />CComBSTR bstrHTMLText;<br style="padding: 0px; margin: 0px; " />objDocument=(IHTMLDocument2 *)m_ie.GetDocument();//m_ie是浏览器控件<br style="padding: 0px; margin: 0px; " />HRESULT hr=objDocument-&gt;get_body(&amp;m_pBody);<br style="padding: 0px; margin: 0px; " />if (FAILED(hr))<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br style="padding: 0px; margin: 0px; " /><br style="padding: 0px; margin: 0px; " />hr=m_pBody-&gt;get_outerHTML(&amp;bstrHTMLText);<br style="padding: 0px; margin: 0px; " />if (FAILED(hr))<br style="padding: 0px; margin: 0px; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br style="padding: 0px; margin: 0px; " />CString html=bstrHTMLText.m_str;//获取到的html代码<br /></ul><img src ="http://www.cppblog.com/yehao/aggbug/195983.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2012-12-04 19:06 <a href="http://www.cppblog.com/yehao/articles/195983.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MFC中画橡皮线,动态矩形,圆等方法</title><link>http://www.cppblog.com/yehao/articles/193803.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Wed, 24 Oct 2012 10:08:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/193803.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/193803.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/193803.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/193803.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/193803.html</trackback:ping><description><![CDATA[<p style="line-height: 25px; margin: 0px 0px 10px; padding: 0px; color: #7b5a31; font-family: Arial, Helvetica, simsun, u5b8bu4f53; background-color: #000000; ">1,首先在OnLButtonDown()中保存第一个点:</p><p style="line-height: 25px; margin: 0px 0px 10px; padding: 0px; color: #7b5a31; font-family: Arial, Helvetica, simsun, u5b8bu4f53; background-color: #000000; ">void CMyView::OnLButtonDown(UINT nFlags, CPoint point)&nbsp;<br />{<br />&nbsp;// TODO: Add your message handler code here and/or call default</p><p style="line-height: 25px; margin: 0px 0px 10px; padding: 0px; color: #7b5a31; font-family: Arial, Helvetica, simsun, u5b8bu4f53; background-color: #000000; ">&nbsp;if(Start==true)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //开始标志<br />&nbsp;{<br />&nbsp;&nbsp;CClientDC&nbsp;&nbsp; ClientDC(this);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;OnPrepareDC(&amp;ClientDC);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;ClientDC.DPtoLP(&amp;point);&nbsp;<br />&nbsp;&nbsp;<br />&nbsp;&nbsp;PointA=point;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //第一个点.<br />&nbsp;&nbsp;OldPoint=point;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//鼠标移动过程中的上一个点.<br />&nbsp;&nbsp;First=true;<br />&nbsp;}<br />&nbsp;CView::OnLButtonDown(nFlags, point);<br />}</p><p style="line-height: 25px; margin: 0px 0px 10px; padding: 0px; color: #7b5a31; font-family: Arial, Helvetica, simsun, u5b8bu4f53; background-color: #000000; ">2.其次,在void OnMouseMove(UINT nFlags, CPoint point) 中加入以下画图分支结构</p><p style="line-height: 25px; margin: 0px 0px 10px; padding: 0px; color: #7b5a31; font-family: Arial, Helvetica, simsun, u5b8bu4f53; background-color: #000000; "><br />void CMyView::OnMouseMove(UINT nFlags, CPoint point)&nbsp;<br />{<br />&nbsp;// TODO: Add your message handler code here and/or call default&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;if(First&amp;&amp;Start){&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;CClientDC&nbsp;&nbsp; ClientDC(this);//设备描述表&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;OnPrepareDC(&amp;ClientDC);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;ClientDC.DPtoLP(&amp;point);&nbsp;<br />&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;if(DrawStartWhat==0)<br />&nbsp;&nbsp;{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;ClientDC.SetROP2(R2_NOTXORPEN);//生成逆转当前屏幕颜色来画线的绘图方式以擦去之前画的线</p><p style="line-height: 25px; margin: 0px 0px 10px; padding: 0px; color: #7b5a31; font-family: Arial, Helvetica, simsun, u5b8bu4f53; background-color: #000000; ">&nbsp;&nbsp;&nbsp;ClientDC.MoveTo(PointA);//画反颜色线,就擦去了原来的颜色&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;ClientDC.LineTo(OldPoint);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;ClientDC.MoveTo(PointA);&nbsp;&nbsp; //画新的线,以下同理.<br />&nbsp;&nbsp;&nbsp;ClientDC.LineTo(point);&nbsp;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;else if(DrawStartWhat==1)<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;//love you!&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 很多人用的是R2_NOT,但是自我感这儿用R2_NOTXORPEN较好.</p><p style="line-height: 25px; margin: 0px 0px 10px; padding: 0px; color: #7b5a31; font-family: Arial, Helvetica, simsun, u5b8bu4f53; background-color: #000000; ">&nbsp;&nbsp;&nbsp;ClientDC.SetROP2(R2_NOTXORPEN);//生成逆转当前屏幕颜色来画线的绘图方式以擦去之前画的圆,&nbsp;<br />&nbsp;&nbsp;&nbsp;OldPoint.y=OldPoint.x-PointA.x+PointA.y;//画圆的坐标设定,注意它的斜率与PointA.y/PointA.x相同.<br />&nbsp;&nbsp;&nbsp;ClientDC.Ellipse(CRect(PointA,OldPoint));<br />&nbsp;&nbsp;&nbsp;OldPoint.x=point.x;<br />&nbsp;&nbsp;&nbsp;OldPoint.y=point.x-PointA.x+PointA.y;</p><p style="line-height: 25px; margin: 0px 0px 10px; padding: 0px; color: #7b5a31; font-family: Arial, Helvetica, simsun, u5b8bu4f53; background-color: #000000; ">&nbsp;&nbsp;&nbsp;ClientDC.Ellipse(CRect(PointA,OldPoint));<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;else if(DrawStartWhat==2)<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;ClientDC.SetROP2(R2_NOTXORPEN);//生成逆转当前屏幕颜色来画线的绘图方式以擦去之前画的椭圆<br />&nbsp;&nbsp;&nbsp;ClientDC.Ellipse(CRect(PointA,OldPoint));<br />&nbsp;&nbsp;&nbsp;ClientDC.Ellipse(CRect(PointA,point));<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;else if(DrawStartWhat==3)<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;ClientDC.SetROP2(R2_NOTXORPEN);//生成逆转当前屏幕颜色来画线的绘图方式以擦去之前画的矩形<br />&nbsp;&nbsp;&nbsp;ClientDC.Rectangle(CRect(PointA,OldPoint));<br />&nbsp;&nbsp;&nbsp;ClientDC.Rectangle(CRect(PointA,point));<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;OldPoint=point;&nbsp;&nbsp;<br />&nbsp;CView::OnMouseMove(nFlags, point);<br />}</p><p style="line-height: 25px; margin: 0px 0px 10px; padding: 0px; color: #7b5a31; font-family: Arial, Helvetica, simsun, u5b8bu4f53; background-color: #000000; ">3.最好在OnLButtonUP()中,回到初值,即可&gt;</p><p style="line-height: 25px; margin: 0px 0px 10px; padding: 0px; color: #7b5a31; font-family: Arial, Helvetica, simsun, u5b8bu4f53; background-color: #000000; ">void CMyView::OnLButtonUp(UINT nFlags, CPoint point)&nbsp;<br />{<br />&nbsp;// TODO: Add your message handler code here and/or call default<br />&nbsp;<br />&nbsp;if(First)<br />&nbsp;{&nbsp;<br />&nbsp;&nbsp;First=false;&nbsp;&nbsp;&nbsp;<br />&nbsp;}&nbsp;&nbsp;<br />&nbsp;CView::OnLButtonUp(nFlags, point);<br />}</p><img src ="http://www.cppblog.com/yehao/aggbug/193803.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2012-10-24 18:08 <a href="http://www.cppblog.com/yehao/articles/193803.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何对webbrowser和IE编程（十一）</title><link>http://www.cppblog.com/yehao/articles/191631.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Sat, 22 Sep 2012 13:59:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/191631.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/191631.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/191631.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/191631.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/191631.html</trackback:ping><description><![CDATA[<div style="color: #333333; font-family: Arial, Console, Verdana, 'Courier New'; border: 1px solid #cccccc; background-color: #eeeeee; float: left; min-width: 200px; padding: 4px 10px; "><p style="text-align: right; margin: 0px; "><span style="float: left; ">目录<a href="http://blog.csdn.net/shanhe/article/details/488338#" title="系统根据文章中H1到H6标签自动生成文章目录" style="color: #336699; text-decoration: none; ">(?)</a></span><a href="http://blog.csdn.net/shanhe/article/details/488338#" title="收起" style="color: #336699; text-decoration: none; ">[-]</a></p><ol style="margin-left: 14px; padding-left: 14px; line-height: 19px; "><li><a href="http://blog.csdn.net/shanhe/article/details/488338#t0" style="color: #336699; text-decoration: none; ">仅仅用于Internet Explorer的事件</a></li><li><a href="http://blog.csdn.net/shanhe/article/details/488338#t1" style="color: #336699; text-decoration: none; ">自ActiveX控件中控制Internet Explorer 事件</a></li></ol></div><div style="color: #333333; font-family: Arial, Console, Verdana, 'Courier New'; clear: both; "></div><div id="article_content" style="margin: 20px 0px 0px; line-height: 26px; font-family: Arial; color: #333333; "><h1><a name="t0" style="color: rgb(51, 102, 153); "></a>仅仅用于Internet Explorer的事件</h1><p>有些是仅仅可用于自动化&nbsp;Internet Explorer,:</p><p style="margin-left: 36pt; text-indent: -18pt; "><span style="font-size: 10pt; font-family: Symbol; ">&#183;<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman'; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><em>OnQuit</em></p><ul type="disc"><li><em>OnVisible</em></li><li><em>OnToolBar</em></li><li><em>OnMenuBar</em></li><li><em>OnStatusBar</em></li><li><em>OnFullScreen</em></li><li><em>OnTheaterMode</em></li></ul><p>大多数这些事件属于浏览器用户接口. 另外一些必须要先是或者关闭Internet Explorer才发生. 一些情形中，这些事件将在你宿主webbrowser空间的时候发生. 举例来讲,当你在你的应用程序设置<em>MenuBar</em>&nbsp;属性,尽管你的WebBrowser control 并没有菜单条,&nbsp;<em>OnMenuBar</em>&nbsp;事件将被激发, 但是如果你显示或者隐藏你的应用程序菜单条，<em>OnMenuBar</em>&nbsp;事件不会激发.为什么?因为你的菜单条由你控制，webbrowser对这些用户接口项一无所知. 很长时间以来，这些相互矛盾的功能是一些混乱的根源。</p><p>其中一个事件&#8212;<em>OnQuit</em>&#8212;将永远不会在你的应用程序中激发.举个例子, 察看表 Table 7-6. 注意到<em>OnQuit&nbsp;</em>事件当用户关闭 Internet Explorer 或者当<em>Quit&nbsp;</em>方法被调用时激发.如果你宿主改控件且用户关闭你的应用程序,&nbsp;&nbsp;<em>OnQuit&nbsp;</em>事件不会激发.它仅仅在你自动化Internet Explorer 且用户手动关闭浏览器时候发生.另外，如果你在宿主一个webbrowser控件时试图调用<em>Quit&nbsp;</em>方法,一个自动化错误将会发生.</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><h1><a name="t1" style="color: rgb(51, 102, 153); "></a>自ActiveX控件中控制Internet Explorer 事件</h1><p>通过&nbsp;<em>IWebBrowser2</em>&nbsp;接口你可以在利用vc++在ActiveX 控件中接受事件.</p><p>你可能疑惑为什么要在ActiveX控件中接受 Internet Explorer事件.之前介绍"<em>DocumentComplete</em>," 事件时候，我提到过你不可以在<em>DocumentComplete</em>&nbsp;event 事件被触发前安全存取文档.在Activex控件中获知<em>DocumentComplete</em>&nbsp;事件被触发的途径是ActiveX 控件接收 Internet Explorer并处理<em>&nbsp;DocumentComplete</em>&nbsp;事件.</p><p>除了你必须接收Internet Explorer 事件外, 你可以开发一个可导航的类浏览器的应用于公司intranet或者学校网络.你可以在ActiveX control中自动化Internet Explorer并接受其事件。.</p><p style="margin: 0cm 36pt 0pt; "><span style="font-family: 宋体; ">当你刷新一个页面</span>,&nbsp;<span style="font-family: 宋体; ">也许</span><em>DocumentComplete&nbsp;</em><span style="font-family: 宋体; ">事件并不激发</span>.&nbsp;<span style="font-family: 宋体; ">当</span><em>DocumentComplete&nbsp;</em><span style="font-family: 宋体; ">事件并未触发</span>,&nbsp;&nbsp;<em>ProgressChange&nbsp;</em><span style="font-family: 宋体; ">事件被用来控制以检测某页是否完成加载</span>.&nbsp;<span style="font-family: 宋体; ">载一个简单的</span>web<span style="font-family: 宋体; ">页或者没有嵌入帧时</span>&nbsp;<em>ProgressChange&nbsp;</em><span style="font-family: 宋体; ">工作的很好</span>.</p><p>记住&nbsp;<em>ProgressChange&nbsp;</em>右两个参数告诉你下载操作的进度.第一个参数当下在完成时候设定为<em>-1</em>, 者可以帮助你检测是否可做类打印等操作</p><p>让我们学习一个打印控active控件，为从Internet Explorer接收事件,你必须设置事件接收,意味着你必须通过<em>IWebBrowser2&nbsp;&nbsp;</em>接口以获得实现,如下实现:</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">protected:</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; CComPtr&lt;IWebBrowser2&gt; m_spWebBrowser;</pre></td></tr></tbody></table><p style="margin: 0cm 36pt 0pt; "><strong>.</strong></p><p>接下来覆盖<em>IOleObjectImpl 的SetClientSite</em>方法的实现.<em>&nbsp;SetClientSite 放</em>方法是在Internet Explorer通知气客户区的控件的时候被调用.你可用客户区的site指针 (<em>m_spClientSite</em>) 存取容器并且得到<em>IWebBrowser2&nbsp;</em>接口指针. 在<em>SetClientSite&nbsp;</em>实现中, 你必须首先调用其基类版本,就想如下：</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">IOleObjectImpl&lt;CPrintCtl&gt;::SetClientSite(pClientSite);</pre></td></tr></tbody></table><p>这些带吗看起来可能有些生疏, 但记住&nbsp;<em>IOleObjectImpl&nbsp;</em>是一个模版类. 为了调用它的方法, 你必须制定要求的模版参数以指示编译器哪一个类实例在调用<em>SetClientSite&nbsp;</em>方法时被使用. 现在讲残存的访问容器和<em>IWebBrowser2</em>接口指针的代码从Print方法迁移到<em>SetClientSite</em>&nbsp;方法Now move the remaining code&nbsp;<em>Print</em>&nbsp;方法将看起来如下:</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">STDMETHODIMP CPrintCtl::Print()</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; ATLASSERT(m_spWebBrowser);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; HRESULT hr = E_FAIL;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (m_spWebBrowser)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hr = m_spWebBrowser-&gt;ExecWB(OLECMDID_PRINT, </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OLECMDEXECOPT_PROMPTUSER, NULL, NULL);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; return hr;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><p>而&nbsp;<em>SetClientSite&nbsp;</em>方法将接收事件，<em>SetClientSite</em>&nbsp;讲看起来如下:</p><p style="margin: 0cm 36pt 0pt; "><strong><span style="font-family: 宋体; ">注意</span></strong></p><div align="center" style="margin: 0cm 36pt 0pt; text-align: center; "><hr align="center" width="100%" size="2" /></div><p style="margin: 0cm 36pt 0pt; "><span style="font-family: 宋体; ">你不能够再</span><em>FinalConstruct&nbsp;</em>m<span style="font-family: 宋体; ">方法中接收事件因为此时客户站点还未设定。</span></p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">STDMETHODIMP CPrintCtl::SetClientSite(IOleClientSite* pClientSite)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; HRESULT hr = IOleObjectImpl&lt;CPrintCtl&gt;::SetClientSite(pClientSite);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (!pClientSite)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return hr;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; CComPtr&lt;IOleContainer&gt; spContainer;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; m_spClientSite-&gt;GetContainer(&amp;spContainer);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; ATLASSERT(spContainer);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (SUCCEEDED(hr))</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Set up the event sink.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CComQIPtr&lt;IServiceProvider, &amp;IID_IServiceProvider&gt;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spServiceProvider(spContainer);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ATLASSERT(spServiceProvider);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (spServiceProvider)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spServiceProvider-&gt;QueryService(SID_SInternetExplorer,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IID_IWebBrowser2,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (void**)&amp;m_spWebBrowser);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ATLASSERT(m_spWebBrowser);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (m_spWebBrowser)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AtlAdvise(m_spWebBrowser, GetUnknown(),</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DIID_DWebBrowserEvents2, &amp;m_dwCookie);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; return hr;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><p>注意到在<em>AtlAdvise&nbsp;</em>调用时你必须建立protected 或者private&nbsp;<em>DWORD</em>的数据成员以掌握返回自<em>AtlAdvise</em>&nbsp;方法的cookie.<em>&nbsp;CprintCtl</em>&nbsp;类的构造函数初始化改成员为0.<em>&nbsp;</em>尽管我们注意到<em>CPrintCtl::SetClientSite</em>&nbsp;方法使用<em>IOleObjectImpl::SetClientSite</em>&nbsp;方法的返回值. 此方法并不检查已被调用的返回值因为<em>CPrintCtl::SetClientSi</em>将 反射客户站点的设定状态.</p><p>最好, 我们检查<em>pClientSite</em>&nbsp;的返回值，输入参数是<em>NULL</em>. 如果这样,我们当Internet Explorer 卸载这些控时, 他调用<em>SetClientSite</em>&nbsp;w设置为NULL. 或者告诉你已经从站点解除, 所以包含一个接口，&nbsp;<em>IWebBrowser2</em>&nbsp;容器不需要一定执行。.</p><p>因为当你完成任务时应当关闭任务的站点, 也包含某个控件被卸载时。检查<em>pClientSite&nbsp;</em>是否为NULL,以便放置<em>AtlUnadvise&nbsp;</em>方法. 记住<em>pClientSite</em>在控件被卸载时为&nbsp;<em>NULL</em>. 看起来如下:</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">if (!pClientSite)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; ATLASSERT(m_spWebBrowser);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (m_spWebBrowser)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AtlUnadvise(m_spWebBrowser, DIID_DWebBrowserEvents2, m_dwCookie);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; return hr;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><p>现在你可以使用<em>AtlAdvise</em>接收事件,让我们控制事件.为此你必须覆盖重写<em>IDispatchImpl 的Invoke&nbsp;</em>方法. 典型的,你将为你的时间建立一个单独的类因为 Internet Explorer 事件的DISPIDs 必须同你的控件的DISPIDs 不同.但在此你可以简单在&nbsp;<em>CPrintCtl&nbsp;&nbsp;</em>类中来实现.实现<em>Invoke&nbsp;</em>(入代码所示)以控制<em>ProgressChange</em>&nbsp;事件.在事件句柄, 如果progres的总数设定为&nbsp;<em>-1</em>,设定一个标志变量指示已被打印.</p><p style="margin: 0cm 36pt 0pt; ">&nbsp;</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">STDMETHODIMP CPrintCtl::Invoke(DISPID dispidMember, </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;REFIID riid, </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LCID lcid,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WORD wFlags, </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DISPPARAMS* pDispParams, </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VARIANT* pvarResult, </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EXCEPINFO* pExcepInfo,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UINT* puArgErr)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (riid != IID_NULL)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return DISP_E_UNKNOWNINTERFACE;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (!pDispParams)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return DISP_E_PARAMNOTOPTIONAL;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; switch (dispidMember)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // The parameters for this DISPID:</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // [0]: Maximum progress - VT_I4</pre><pre style="white-space: pre-wrap; word-wrap: break-word; "> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// [1]: Amount of total progress - VT_I4</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case DISPID_PROGRESSCHANGE:</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (pDispParams-&gt;cArgs != 0)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Make sure that you access the</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // correct data member of the rgvarg array.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // To do this, check the type of data to</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // make sure it is correct.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (pDispParams-&gt;cArgs &gt; 1</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp; pDispParams-&gt;rgvarg[1].vt == VT_I4</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp; pDispParams-&gt;rgvarg[0].vt == VT_I4)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (-1 == pDispParams-&gt;rgvarg[1].lVal)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_fCanBePrinted = TRUE;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default:</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Call the base class implementation of Invoke</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // so that IPrintCtl methods and properties will</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // work correctly.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IDispatchImpl&lt;IPrintCtl, &amp;IID_IPrintCtl, </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;LIBID_ATLPRINTLib&gt;::Invoke(dispidMember, riid, lcid,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wFlags, pDispParams,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pvarResult, pExcepInfo, puArgErr);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; return S_OK;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><p>在&nbsp;<em>ProgressChange&nbsp;</em>事件处理中，当<em>Progress&nbsp;</em>参数(<em>pDispParams-&gt;rgvarg[1].lVal</em>) 是<em>-1</em>, 我们设置一个变量告诉控件问打光在完成可以打印. FCanBePrinted 就是我们要设定的变量。</p><p>现在当用户试图调用<em>Print&nbsp;</em>方法打印文档,你可以检查变量以确定是否可打印. 此处为&nbsp;<em>Print&nbsp;</em>方法的代码:</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">STDMETHODIMP CPrintCtl::Print()</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (!m_fCanBePrinted)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ::MessageBox(NULL, _T("The page is not ready to be printed."),</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _T("PrintCtl"), MB_OK);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return E_FAIL;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; ATLASSERT(m_spWebBrowser);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; HRESULT hr = E_FAIL;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (m_spWebBrowser)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hr = m_spWebBrowser-&gt;ExecWB(OLECMDID_PRINT, </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OLECMDEXECOPT_PROMPTUSER, NULL, NULL);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; return hr;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table></div><img src ="http://www.cppblog.com/yehao/aggbug/191631.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2012-09-22 21:59 <a href="http://www.cppblog.com/yehao/articles/191631.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何对webbrowser和IE编程（十）</title><link>http://www.cppblog.com/yehao/articles/191629.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Sat, 22 Sep 2012 13:57:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/191629.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/191629.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/191629.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/191629.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/191629.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 目录(?)[-]由Internet Explorer 5激发事件BeforeNavigate2CommandStateChangeDocumentCompleteDownloadBeginDownloadCompleteNavigateComplete2NewWindow2ProgressChange事件发生序列由Internet Explorer 5激发事件如你所知，&nbsp;Internet...&nbsp;&nbsp;<a href='http://www.cppblog.com/yehao/articles/191629.html'>阅读全文</a><img src ="http://www.cppblog.com/yehao/aggbug/191629.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2012-09-22 21:57 <a href="http://www.cppblog.com/yehao/articles/191629.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何对webbrowser和IE编程（九）</title><link>http://www.cppblog.com/yehao/articles/191626.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Sat, 22 Sep 2012 13:48:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/191626.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/191626.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/191626.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/191626.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/191626.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 目录(?)[-]接收事件的途径Visual Basic 中接收事件C++中接收事件在ATL中接收事件在 MFC中接收事件在MFC中自动化一个COM 对象时接收事件在MFC中寄宿 ActiveX 控件时处理事件接收事件的途径依靠开发工具你创建客户应用程序,你可以接收事件通过不同的途径. 显然, 在Vb中接收事件同在VC中接收事件相比是如此不同和容易.在 C++ 应用中,你可以用不同的技术，通过使用 ...&nbsp;&nbsp;<a href='http://www.cppblog.com/yehao/articles/191626.html'>阅读全文</a><img src ="http://www.cppblog.com/yehao/aggbug/191626.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2012-09-22 21:48 <a href="http://www.cppblog.com/yehao/articles/191626.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何对webbrowser和IE编程（八）</title><link>http://www.cppblog.com/yehao/articles/191625.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Sat, 22 Sep 2012 13:46:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/191625.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/191625.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/191625.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/191625.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/191625.html</trackback:ping><description><![CDATA[<div style="color: #333333; font-family: Arial, Console, Verdana, 'Courier New'; border: 1px solid #cccccc; background-color: #eeeeee; float: left; min-width: 200px; padding: 4px 10px; "><p style="text-align: right; margin: 0px; "><span style="float: left; ">目录<a href="http://blog.csdn.net/shanhe/article/details/433277#" title="系统根据文章中H1到H6标签自动生成文章目录" style="color: #336699; text-decoration: none; ">(?)</a></span><a href="http://blog.csdn.net/shanhe/article/details/433277#" title="收起" style="color: #336699; text-decoration: none; ">[-]</a></p><ol style="margin-left: 14px; padding-left: 14px; line-height: 19px; "><li><a href="http://blog.csdn.net/shanhe/article/details/433277#t0" style="color: #336699; text-decoration: none; ">Internet Explorer 事件</a></li><li><a href="http://blog.csdn.net/shanhe/article/details/433277#t1" style="color: #336699; text-decoration: none; ">事件 和 引出的接口</a></li><ol><li><a href="http://blog.csdn.net/shanhe/article/details/433277#t2" style="color: #336699; text-decoration: none; ">IConnectionPointContainer</a></li><li><a href="http://blog.csdn.net/shanhe/article/details/433277#t3" style="color: #336699; text-decoration: none; ">IConnectionPoint</a></li></ol><li><a href="http://blog.csdn.net/shanhe/article/details/433277#t4" style="color: #336699; text-decoration: none; ">接收事件的途径</a></li><ol><li><a href="http://blog.csdn.net/shanhe/article/details/433277#t5" style="color: #336699; text-decoration: none; ">Visual Basic 中接收事件</a></li></ol></ol></div><div style="color: #333333; font-family: Arial, Console, Verdana, 'Courier New'; clear: both; "></div><div id="article_content" style="margin: 20px 0px 0px; line-height: 26px; font-family: Arial; color: #333333; "><h1><a name="t0" style="color: rgb(51, 102, 153); "></a>Internet Explorer 事件</h1><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p><em>IWebBrowser2&nbsp;</em>的属性和方法给了你确切的控制导航和用户接口的途径，但是如果你不能够检测到浏览器正在处理什么以及何时处理什么，你还是没有全面的控制它.因此，WebBrowser控件和Internet Explorer暴露出事件，通过此你可以必要时监视活动以及处理某些活动. 举例来说，假设你建立一个intranet应用程序, 你想限制用户用户访问某些web页.利用Internet Explorer的时间处理句柄,你可以指令应用程序在用户试图访问受限的URL时候取消导航完成。</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><h1><a name="t1" style="color: rgb(51, 102, 153); "></a>事件 和 引出的接口</h1><p>无论何时一个COM 对象需要客户应用程序一个事件发生了, COM 对象发送一个叫做事件的消息. 发送消息的处理过程会激发一个事件. 但如果事件没有任何监听者会如何？ 事件每次都发生吗? 显然, 客户应用程序监听这些事件并控制COM对象.如果一个客户应用想接收来自COM 对象的事件,它"advises" 实际的COM 对象的.</p><p>一个COM 对象为了通客户通信, 对象自身必须支持一个或者多个外引接口.一个 COM 对象支持的外引接口是作为可连接对象引用. 要成为一个可连接对象，COM对象必须实现<em>IConnectionPointContainer&nbsp;</em>接口。通过此接口，客户可认识到那些外引接口被服务器支持. 外引接口实际通过连接点由客户挂接入COM实现。实现外引接口的客户部分众所周知是通过事件接收槽（event sink）实现的.</p><p>单一的连接点由服务器支持每一个外引接口.每一个连接点能够操纵一种类型的外引接口且至少支持<em>IConnectionPoint</em>&nbsp;接口. 图7-1 描述了可连接的对象和它的客户之间的关系.</p><p><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></p><p><strong>Figure 7-1.</strong>&nbsp;<em>Connectable object and its client.</em></p><p>每一个服务器必须实现2个接口以便实现客户可以接收事件&#8212;<em>IConnectionPointContainer</em>&nbsp;和<em>IConnectionPoint</em>. 我们将先看看这些接口之后将检视实现事件的不同途径.</p><h2><a name="t2" style="color: rgb(51, 102, 153); "></a><em>IConnectionPointContainer</em></h2><p>每一个可连接对象实现了<em>IConnectionPointContainer</em>. 通过此接口, 试图接收事件的客户可找出关于可连接对象支持的不同的连接点. 通过调用<em>QueryInterface&nbsp;</em>using 客户可以获得服务器支持的任何接口的指针. (你可以使用任何接口指针调用<em>QueryInterface</em>, 因为全部 COM 接口继承自<em>IUnknown</em>.) 之后客户可以使用<em>IConnectionPointContainer</em>&nbsp;接口的2个方法中的之一获取可连接点。 如表7-1, 获得可连接点</p><p><strong>Table 7-1</strong>&nbsp;<em>Methods of the</em>&nbsp;IConnectionPointContainer<em>&nbsp;Interface</em></p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em><span style="font-family: 宋体; ">方法</span></em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p></td><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em><span style="font-family: 宋体; ">描述</span></em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>EnumConnectionPoints</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">列举可连接对象支持的全部可连接对象</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>FindConnectionPoint</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">让客户查询可连接对象关于它是否支持一个特殊接口。客户指定特殊的接口（可连接点）的接口标示</span>&nbsp;(IID)&nbsp;<span style="font-family: 宋体; ">。如果可连接对象支持此接口，返回</span><em>IConnectionPoint</em>&nbsp;<span style="font-family: 宋体; ">接口的指针。</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr></tbody></table><h2><a name="t3" style="color: rgb(51, 102, 153); "></a><em>IConnectionPoint</em></h2><p>一旦客户知道哪个连接点可被连接对象服务器支持, 客户就可建立同可连接对象的连接。客户通知可连接对象将要在全部事件中接收那些事件.当客户不再需要接收来自可连接对象的事件,客户解除对对象的通知. 表7-2 展示了&nbsp;<em>IConnectionPoint</em>&nbsp;接口可被客户连接的. (大多数时候,你将连接到仅仅表中头两个)</p><p><strong>Table 7-2</strong>&nbsp;<em>Methods of the&nbsp;</em>IConnectionPoint<em>&nbsp;Interface</em></p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em><span style="font-family: 宋体; ">方法</span></em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p></td><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em><span style="font-family: 宋体; ">描述</span></em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>Advise</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">在客户和可连接对象的某一个可连接点间建立连接。</span>&nbsp;<span style="font-family: 宋体; ">客户必须传递它的事件接收槽的</span><em>IUnknown</em>&nbsp;<span style="font-family: 宋体; ">接口。</span>&nbsp;<span style="font-family: 宋体; ">事件接收槽必须实现</span><em>IDispatch</em>&nbsp;<span style="font-family: 宋体; ">接口以接收事件。</span>&nbsp;<span style="font-family: 宋体; ">典型地</span>,<span style="font-family: 宋体; ">党课连接对象激发事件，可连接对象将调用</span>&nbsp;<em>IDispatch</em>&nbsp;<span style="font-family: 宋体; ">接口的</span><em>Invoke&nbsp;</em><span style="font-family: 宋体; ">方法。</span>&nbsp;<em>Advise</em><span style="font-family: 宋体; ">方法返回一个</span>&nbsp;cookie&nbsp;<span style="font-family: 宋体; ">，当客户中断连接时候，调用</span><em>Unadvise</em><span style="font-family: 宋体; ">方法时候需要携带此</span>cookie</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>Unadvise</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">中断连接</span>.</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>GetConnectionInterface</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">返回由连接点管理的外发接口的</span>IID .&nbsp;<em>GetConnectionInterface&nbsp;</em><span style="font-family: 宋体; ">方法让客户将</span><em>IConnectionPoint</em><span style="font-family: 宋体; ">翻译为一个</span>IID.</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>GetConnectionPointContainer</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">得到刻连接对象的</span><em>IConnectionPointContainer</em>&nbsp;<span style="font-family: 宋体; ">接口</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>EnumConnections</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">枚举刻连接对象的当前可连接点</span>.</p><p>&nbsp;</p><p>&nbsp;</p></td></tr></tbody></table><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><h1><a name="t4" style="color: rgb(51, 102, 153); "></a>接收事件的途径</h1><p>依靠开发工具你创建客户应用程序,你可以接收事件通过不同的途径. 显然, 在Vb中接收事件同在VC中接收事件相比是如此不同和容易.在 C++ 应用中,你可以用不同的技术，通过使用 ATL, MFC, 或者标准C++.</p><h2><a name="t5" style="color: rgb(51, 102, 153); "></a>Visual Basic 中接收事件</h2><p>Visual Basic是创建大多数类型应用的最轻松的工具, 所以我告诉你VB是处理事件最溶的工具时也不要惊奇. ATL 和 Visual Basic 示例我们同样的工作,但是ATL花费了我4个小时, 而 Visual Basic 例子仅仅只花20 分钟.别说我错了&#8212;我是ATL, 和 MFC， C++的忠实信徒,&nbsp;&nbsp;尤其是你建立一个接口的时候.但是 Visual Basic当建立客户应用程序从类似IE这样的服务器接收事件时是伟大的工具.</p><p>OK,如何从Visual Basic 应用程序中接收事件？当宿主WebBrowser 控件,你不必做任何特别的事. Visual Basic 在form上为WebBrowser 控件接收事件.你所需要做的全部事情就是未你要接收的任何事件创建一个事件处理句柄.</p><p>你象创建其他事件句柄一样创建句柄&nbsp;(例如<em>Form_Load</em>&nbsp;event). 从Procedure下拉列表框中选择你象控制的句柄, 在事件句柄中,加入任何你型在事件激发时执行的任何代码.</p><p>当自动化服务器时候接收事件, 例如在VB应用中的Internet Explorer,过程直截了当.首先设置对服务器的类型库的引用, 你可以访问Project/References 菜单.之后，采用<em>WithEvents</em>&nbsp;关键字声明服务器对象的变量.举例, 如果你自动化Internet Explorer, 你将声明变量如下:</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">Dim WithEvents InternetExplorer1 As InternetExplorer</pre></td></tr></tbody></table><p>下一步，采用new或者其他 关键字创建实例变量 ，如下：:</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">Set InternetExplorer1 = CreateObject("InternetExplorer.Application.1")</pre></td></tr></tbody></table><p>或者:</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">Set InternetExplorer1 = New InternetExplorer</pre></td></tr></tbody></table><p>当你采用以上途径生成实例接收事件, Visual Basic 自动为你初始化和管理事件接收.你不必担心连接点问题，VB为你处理它们.</p><p>在你输入建立服务器的代码之后,你插入符合服务器事件的方法调用.&nbsp;&nbsp;&nbsp;举例来说, 如果你想控制由IE激活的<em>DownloadBegin</em>&nbsp;event, 你应当声明类似如下的方法声明:</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">Private Sub InternetExplorer1_DownloadBegin()</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; ' Insert your best Visual Basic code here.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">End Sub</pre></td></tr></tbody></table><p>当你不再想接收来自服务器的事件，简单设置变量为<em>Nothing</em>:</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">Set InternetExplorer1 = Nothing</pre></td></tr></tbody></table></div><img src ="http://www.cppblog.com/yehao/aggbug/191625.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2012-09-22 21:46 <a href="http://www.cppblog.com/yehao/articles/191625.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何对webbrowser和IE编程（七）</title><link>http://www.cppblog.com/yehao/articles/191624.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Sat, 22 Sep 2012 13:46:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/191624.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/191624.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/191624.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/191624.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/191624.html</trackback:ping><description><![CDATA[<div style="color: #333333; font-family: Arial, Console, Verdana, 'Courier New'; border: 1px solid #cccccc; background-color: #eeeeee; float: left; min-width: 200px; padding: 4px 10px; "><p style="text-align: right; margin: 0px; "><span style="float: left; ">目录<a href="http://blog.csdn.net/shanhe/article/details/427559#" title="系统根据文章中H1到H6标签自动生成文章目录" style="color: #336699; text-decoration: none; ">(?)</a></span><a href="http://blog.csdn.net/shanhe/article/details/427559#" title="收起" style="color: #336699; text-decoration: none; ">[-]</a></p><ol style="margin-left: 14px; padding-left: 14px; line-height: 19px; "><li><a href="http://blog.csdn.net/shanhe/article/details/427559#t0" style="color: #336699; text-decoration: none; ">加入高级功能</a></li><ol><li><a href="http://blog.csdn.net/shanhe/article/details/427559#t1" style="color: #336699; text-decoration: none; ">从ActiveX 控件中访问Internet Explorer 的IWebBrowser2</a></li><ol><li><a href="http://blog.csdn.net/shanhe/article/details/427559#t2" style="color: #336699; text-decoration: none; ">利用一个控件打印web页</a></li><li><a href="http://blog.csdn.net/shanhe/article/details/427559#t3" style="color: #336699; text-decoration: none; ">PrintCtl.htm</a></li></ol><li><a href="http://blog.csdn.net/shanhe/article/details/427559#t4" style="color: #336699; text-decoration: none; ">当宿主WebBrowser控件的时候存取帧的IWebBrowser2 接口</a></li><li><a href="http://blog.csdn.net/shanhe/article/details/427559#t5" style="color: #336699; text-decoration: none; ">调用 查找, 察看源码, 以及 Internet 选项</a></li></ol><li><a href="http://blog.csdn.net/shanhe/article/details/427559#t6" style="color: #336699; text-decoration: none; ">分发WebBrowser 控件</a></li></ol></div><div style="color: #333333; font-family: Arial, Console, Verdana, 'Courier New'; clear: both; "></div><div id="article_content" style="margin: 20px 0px 0px; line-height: 26px; font-family: Arial; color: #333333; "><h1><a name="t0" style="color: rgb(51, 102, 153); "></a>加入高级功能</h1><p>本节将展示如何加入高级功能到你的应用程序或者ActiveX控件.将展示如何从一个ActiveX控件中访问Internet Explorer的&nbsp;<em>IWebBrowser2</em>，以及如何从一个Web页面的frame中获得<em>WebBrowser</em>&nbsp;对象。将会展示实现一些并非容易实现的功能.本节有一定难度.所有代码采用C++ 和COM实现,你应当有一定坚实的基础才可以完成本节的理解</p><h2><a name="t1" style="color: rgb(51, 102, 153); "></a>从ActiveX 控件中访问Internet Explorer 的<em>IWebBrowser2</em></h2><p>在Activx控件中访问<em>IWebBrowser2&nbsp;</em>接口提供了用户定制浏览器的能力，虽然以此作为自己的控件功能不大光明,且你只能够在VC编写的activeX控件中访问。（尽管可以在VB写的控件中访问document和window控件,但是你不可以直接访问<em>WebBrowser&nbsp;</em>自身） .</p><p>存取&nbsp;&nbsp;<em>IWebBrowser2&nbsp;</em>接口经过四个步骤：</p><p style="margin-left: 36pt; text-indent: -18pt; ">1.<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman'; ">&nbsp;&nbsp;&nbsp;&nbsp;</span>在类文件中包含&nbsp;ExDisp.h .</p><p style="margin: 0cm 0cm 0pt 36pt; text-indent: -18pt; ">2.<span style="font-size: 7pt; line-height: normal; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-family: 宋体; ">调用控件的站点的</span><em>IOleClientSite::GetContainer</em>&nbsp;<span style="font-family: 宋体; ">方法，该方法返回由</span>Internet Explorer.<span style="font-family: 宋体; ">实现的</span><em>IOleContainer&nbsp;</em><span style="font-family: 宋体; ">接口的指针。</span></p><p style="margin: 0cm 0cm 0pt 36pt; text-indent: -18pt; ">3.<span style="font-size: 7pt; line-height: normal; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-family: 宋体; ">如果步骤</span>2<span style="font-family: 宋体; ">成功，用</span><em>&nbsp;IOleContainer</em>&nbsp;<span style="font-family: 宋体; ">指针查询</span><em>IServiceProvider</em>&nbsp;<span style="font-family: 宋体; ">接口。</span>.</p><p style="margin: 0cm 0cm 0pt 36pt; text-indent: -18pt; ">4.<span style="font-size: 7pt; line-height: normal; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-family: 宋体; ">如果步骤</span>3&nbsp;<span style="font-family: 宋体; ">成功</span>,&nbsp;<span style="font-family: 宋体; ">调用</span><em>IServiceProvider&nbsp;</em><span style="font-family: 宋体; ">的方法</span><em>QueryService</em>&nbsp;<span style="font-family: 宋体; ">的到</span>&nbsp;<em>IWebBrowser2</em>&nbsp;<span style="font-family: 宋体; ">接口。</span></p><p style="margin-left: 36pt; "><em>QueryService</em>&nbsp;方法携带3个参数. 第一个参数指定你想访问的服务。为得到<em>IWebBrowser2</em>指针, 需要指定<em>SID_SInternetExplorer</em>&nbsp;或者<em>SID_SWebBrowserApp&nbsp;</em>来指定要访问的服务. (现阶段，他们全部定义为<em>IID_IWebBrowserApp.</em>) 第二个参数指定你想接收的接口的ID。此参数你应当指定为<em>IID_IWebBrowser2</em>. 最后，第三个参数你需要指定哪一个变量接收返回的接口指针。</p><p>Call any method or property of&nbsp;<em>IWebBrowser2.&nbsp;</em>当完成后，确信你已经释放掉你获取的接口指针.以下为代码参数.</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">////////////////////////////////////////////////////////</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">// Begin Step 1</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">#include &lt;ExDisp.h&gt;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">#include &lt;shlguid.h&gt;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">// End Step 1</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">////////////////////////////////////////////////////////</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">CSomeClass::SomeMethod(){</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">////////////////////////////////////////////////////////</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">// Begin Step 2</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">IOleContainer* pContainer;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">// m_pClientSite is a pointer to IOleClientSite.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">// This is the client site for your control.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">//</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">HRESULT hr = m_pClientSite-&gt;GetContainer(&amp;pContainer);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">if (FAILED(hr))</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; return hr;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">// End Step 2</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">////////////////////////////////////////////////////////</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">////////////////////////////////////////////////////////</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">// Begin Step 3</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">IServiceProvider* pServiceProvider;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">hr = pContainer-&gt;QueryInterface(IID_IServiceProvider,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (void**)&amp;pServiceProvider);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">pContainer-&gt;Release();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">if (FAILED(hr))</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; return hr;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">// End Step 3</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">////////////////////////////////////////////////////////</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">////////////////////////////////////////////////////////</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">// Begin Step 4</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">IWebBrowser2* pWebBrowser;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">hr = pServiceProvider-&gt;QueryService(SID_SWebBrowserApp,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IID_IWebBrowser2,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (void**)&amp;pWebBrowser);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">pServiceProvider-&gt;Release();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">if (FAILED(hr))</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; return hr;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">// End Step 4</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">////////////////////////////////////////////////////////</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">////////////////////////////////////////////////////////</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">// Begin Step 5</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">// Call some IWebBrowser2 methods and/or properties.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">// End Step 5</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">////////////////////////////////////////////////////////</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><h3><a name="t2" style="color: rgb(51, 102, 153); "></a>利用一个控件打印web页</h3><p>早于5的Internet Explorer,通常用于ActiveX中 访问<em>IWebBrowser2&nbsp;</em>接口以提供打印web页面的功能。尽管ie5允许你直接在web页的script中使用&nbsp;<em>window.print</em>, 但是建立一个提供打印web页的功能的示范还是比较好教您使用<em>IWebBrowser2</em>接口的入门教程.在此之前，必要知道如何使用ATL建立一个activeX控件以实现打印功能. 关于此点，我将认为您已经知道如何使用ATL创建一个控件.</p><p>启动Visual C++, 新建 ATL DLL工程. 你可将工程命名为&nbsp;<em>AtlPrint</em>. 下一步, 使用Wizard增加一个Lite Control 到你的工程。 你可以命名你的控件为<em>PrintCtl</em>. 为<em>IPrintCtl&nbsp;</em>接口添加一个方法<em>Print</em>. 之后你将在脚本中使用此方法打印当前Web page.</p><p>在实现<em>Print</em>&nbsp;方法前，首先包含ExDisp.h 和 shlguid.h 头文件到PrintCtl.cpp 实现文件.</p><p>下一步使用之前给出的获取<em>IWebBrowser2</em>&nbsp;接口的方法获得接口并调用<em>ExecWB</em>&nbsp;以实现打印当前Web页. 你可以使用ATL 智能接口指针类&#8212;<em>CComPtr&nbsp;</em>以及&nbsp;<em>CComQIPtr&#8212;</em>以实现查询接口处理引用次数等艰苦的工作.此处为智能指针示勇代码:</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">STDMETHODIMP CPrintCtl::Print()</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; HRESULT hr = E_FAIL;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (m_spClientSite)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CComPtr&lt;IOleContainer&gt; spContainer;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hr = m_spClientSite-&gt;GetContainer(&amp;spContainer);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ATLASSERT(SUCCEEDED(hr));</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (SUCCEEDED(hr))</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CComQIPtr&lt;IServiceProvider, &amp;IID_IServiceProvider&gt;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spServiceProvider(spContainer);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ATLASSERT(spServiceProvider);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!spServiceProvider)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;hr = E_FAIL;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CComPtr&lt;IWebBrowser2&gt; spWebBrowser;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hr = spServiceProvider-&gt;QueryService(SID_SInternetExplorer,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IID_IWebBrowser2,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(void**)&amp;spWebBrowser);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ATLASSERT(SUCCEEDED(hr));</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (SUCCEEDED(hr))</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spWebBrowser-&gt;ExecWB(OLECMDID_PRINT, </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OLECMDEXECOPT_PROMPTUSER,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL, NULL);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; return hr;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><p>现在编译ATL ActiveX control. 为测试打印功能，你必须加入一些script. Listing 6-2 展示了这部分代码：</p><p><strong>Listing 6-2.</strong></p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><h3><a name="t3" style="color: rgb(51, 102, 153); "></a>PrintCtl.htm</h3><pre style="white-space: pre-wrap; word-wrap: break-word; ">&lt;HTML&gt;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&lt;HEAD&gt;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; &lt;TITLE&gt;ATL 3.0 test page for object PrintCtl&lt;/TITLE&gt;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; &lt;SCRIPT LANGUAGE="VBS"&gt;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sub btnPrint_onclick</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PrintCtl.Print</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End Sub</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; &lt;/SCRIPT&gt;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&lt;/HEAD&gt;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&lt;BODY&gt;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; &lt;OBJECT ID="PrintCtl"</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CLASSID="CLSID:320B04E4-B55B-11D2-A9BA-444553540001"&gt;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; &lt;/OBJECT&gt;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; &lt;P&gt;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; &lt;BUTTON ID="btnPrint"&gt;Print Page&lt;/BUTTON&gt;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&lt;/BODY&gt;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&lt;/HTML&gt;</pre></td></tr></tbody></table><h2><a name="t4" style="color: rgb(51, 102, 153); "></a>当宿主WebBrowser控件的时候存取帧的<em>IWebBrowser2 接口</em></h2><p>如果一个Web 页包含了多帧，每一帧都包含了一个<em>WebBrowser&nbsp;</em>对象。 当宿主WebBrowser 控件, 你将可被允许从应用程序访问<em>WebBrowser&nbsp;</em>以控制帧.此控允许你控制以在帧中导航, 刷新, 以及诸如此类。一旦你拥有了一个帧中的&nbsp;<em>WebBrowser&nbsp;</em>对象的<em>IWebrowser2&nbsp;</em>接口指针, 你可以掉用<em>IWebrowser2&nbsp;</em>接口的任何方法和属性。</p><p>在VC++中你可以访问一个帧中的<em>WebBrowser</em>. VB中,你可在帧中存取<em>document&nbsp;</em>, 你可以访问<em>WebBrowser&nbsp;</em>但是不可以访问装载于WebBrowser窗口中的HTML文档对象的&nbsp;<em>IoleContainer&nbsp;</em>接口. 存取&nbsp;<em>IOleContainer&nbsp;</em>要求访问帧的&nbsp;<em>WebBrowser&nbsp;</em>对象. 本节讲述VC++d的标准技术细节，即WebBrowser 控件的宿主能访问在包含的WebBrowser控件装载的web页面的帧窗口的WebBrowser对象模型.</p><p>下面的代码展示如何访问web页面的每一个帧的WebBrowser对象以刷新每一帧的内容.其中重要的片断用于用HTML&nbsp;<em>document&nbsp;</em>对象的<em>IOleContainer::EnumObjects</em>&nbsp;&nbsp;方法枚举页面中的embeddings(嵌入)对象. 每一个嵌入对象表现为一个控件. 利用<em>IWebBrowser2</em>&nbsp;接口查询每一个控件对象,此代码可检测到控件是否是一个子帧.如果为获得&nbsp;<em>IWebBrowser2&nbsp;</em>而成功调用<em>QueryInterface</em>, 其结果为帧中的WebBrowser对象的引用. (数据成员<em>m_webBrowser</em>&nbsp;是<em>CWebBrowser2&nbsp;</em>类型的&#8212;MFC 包装类)</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">// Get the IDispatch of the document.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">//</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">LPDISPATCH lpDisp = NULL;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">lpDisp = m_webBrowser.GetDocument();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">if (lpDisp)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; IOleContainer* pContainer;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // Get the container.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; HRESULT hr = lpDisp-&gt;QueryInterface(IID_IOleContainer,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (void**)&amp;pContainer);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; lpDisp-&gt;Release();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (FAILED(hr))</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return hr;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // Get an enumerator for the frames.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; IEnumUnknown* pEnumerator;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; hr = pContainer-&gt;EnumObjects(OLECONTF_EMBEDDINGS, &amp;pEnumerator);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; pContainer-&gt;Release();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (FAILED(hr))</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return hr;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; IUnknown* pUnk;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; ULONG uFetched;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // Enumerate and refresh all the frames.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; for (UINT i = 0; S_OK == pEnumerator-&gt;Next(1, &amp;pUnk, &amp;uFetched); i++)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // QI for IWebBrowser here to see whether we have </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// an embedded browser.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IWebBrowser2* pWebBrowser;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hr = pUnk-&gt;QueryInterface(IID_IWebBrowser2, (void**)&amp;pWebBrowser);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pUnk-&gt;Release();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (SUCCEEDED(hr))</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Refresh the frame.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pWebBrowser-&gt;Refresh();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pWebBrowser-&gt;Release();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp; &nbsp;}</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; pEnumerator-&gt;Release();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><p>请留意在代码中我们首先通过<em>GetDocument</em>&nbsp;方法获得了文档的<em>IDispatch&nbsp;</em>对象指针, 该方法是<em>WebBrowser&nbsp;</em>包装类的成员指针.然后我们访问文档的<em>IOleContainer</em>&nbsp;接口.&nbsp;<em>IOleContainer</em>&nbsp;接口提供了能够枚举页面中全部嵌入对象的功能. 然后我们通过调用<em>IOleContainer</em>&nbsp;的<em>EnumObjects</em>&nbsp;方法得到枚举器（<em>EnumObjects</em>）<em>.</em>&nbsp;<em>EnumObjects&nbsp;</em>返回的&nbsp;<em>IEnumUnknown</em>&nbsp;接口的指针可以用于枚举全部嵌入（embeddings）对象. 代码的下一步, 我们遍历全部嵌入对象,查询每一个对象的<em>IWebBrowser2</em>&nbsp;接口. 如果查询成功, 我们已经获得了帧的<em>IWebBrowser2&nbsp;</em>接口指针.我们可以调用它的任何方法和属性，在此例中，我们仅仅调用了每一个帧的<em>Refresh</em>.</p><p style="margin: 0cm 36pt 0pt; "><strong><span style="font-family: 宋体; ">忠告</span></strong></p><div align="center" style="margin: 0cm 36pt 0pt; text-align: center; "><hr align="center" width="100%" size="2" /></div><p style="margin: 0cm 36pt 0pt; ">ActiveX&nbsp;<span style="font-family: 宋体; ">控件宿主于一个</span>html<span style="font-family: 宋体; ">页也有类似情。也许，如果你建立一个访问</span>ie<span style="font-family: 宋体; ">的</span>WebBrowser&nbsp;<span style="font-family: 宋体; ">控件或者页面帧中的</span>WebBrowser&nbsp;<span style="font-family: 宋体; ">的控件，不要将你的控件标记为脚本安全和初始化安全。</span>.</p><h2><a name="t5" style="color: rgb(51, 102, 153); "></a>调用 查找, 察看源码, 以及 Internet 选项</h2><p>浏览WebBrowser 控件的方法和属性, 你可轻易见到控件提供的功能.但是3个可编程由WebBrowser控件提供的项目不容易发觉到：查找对话框, 察看源代码菜单项,以及Internet选项对话框. 如果你曾经用过ie,你无疑很熟悉他们. 查找对话框, 允许你在WEB页中查找文本,通过处理 Ctrl-F 或者选择edit菜单的Find项来调用.</p><p>察看源代码菜单项,允许你显示WEB页的html代码, 可通过选择View菜单的Source项来选择或者右击web页（在弹处菜单中）选择察看源代码. Internet 选项对话框如图6-23所示, 可通过选择Tools菜单的Internet Option项来调用.</p><p><img height="378" src="http://blog.csdn.net/images/blog_csdn_net/shanhe/InternetOption.jpg" width="359" alt="" style="border: none; " /></p><p><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></p><p><strong>Figure 6-23.</strong>&nbsp;<em>Internet Options dialog box.</em></p><p>能够在你的web应用中提供以上功能的确可以带来对用户的友善性,但是调用途径缺不是通过WebBrowser的方法和属性可以实现. 实际上你应当从调用<em>IOleCommandTarget</em>&nbsp;的<em>Exec&nbsp;</em>方法来调用实现于WebBrowser中的以上功能.当调用<em>Exec</em>, 你传递名为&nbsp;<em>CGID_IWebBrowser</em>&nbsp;的GUID 作为你想调用的命令的ID.尽管<em>ExecWB&nbsp;</em>方法是<em>IOleCommandTarget::Exec</em>&nbsp;方法的包装, 但是你不能够通过<em>ExecWB</em>&nbsp;来调用 Find, View Source, 或者 Internet Options 对话框，以为<em>ExecWB</em>&nbsp;不允许你指定命令组GUID. 那意味着该项技术仅能够用于VC++&#8212;你不能够直接从VB中调用。.</p><p style="margin: 0cm 36pt 0pt; "><strong><span style="font-family: 宋体; ">忠告</span></strong></p><div align="center" style="margin: 0cm 36pt 0pt; text-align: center; "><hr align="center" width="100%" size="2" /></div><p style="margin: 0cm 36pt 0pt; "><span style="font-family: 宋体; ">本代简要展示你未收入文档的命令组</span>GUID&nbsp;<span style="font-family: 宋体; ">，那意味着可以将来改编。尽管代码已经在</span>Internet Explorer 3.<em>x</em>, 4.<em>x</em>,&nbsp;<span style="font-family: 宋体; ">和</span>&nbsp;5<span style="font-family: 宋体; ">中测试</span>,<span style="font-family: 宋体; ">，但是不保证在将来的版本中成功运行</span></p><p>以下步骤实现&nbsp;Find, View Source, 以及Internet Options 命令:</p><p style="margin-left: 36pt; text-indent: -18pt; ">1.<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman'; ">&nbsp;&nbsp;&nbsp;&nbsp;</span>定义WebBrowser 控件的命令组GUID:</p><table cellpadding="0" width="95%" border="0" style="margin-left: 36pt; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">DEFINE_GUID(CGID_IWebBrowser,0xED016940L,0xBD5B,0x11cf,0xBA,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x4E,0x00,0xC0,0x4F,0xD7,0x08,0x16);</pre></td></tr></tbody></table><p style="margin: 0cm 0cm 0pt 36pt; text-indent: -18pt; ">2.<span style="font-size: 7pt; line-height: normal; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-family: 宋体; ">定义用于</span>Find, View Source,&nbsp;<span style="font-family: 宋体; ">和</span>&nbsp;Internet Options<span style="font-family: 宋体; ">的</span>ID:</p><table cellpadding="0" width="95%" border="0" style="margin-left: 36pt; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp; </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define HTMLID_FIND 1</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp; #define HTMLID_VIEWSOURCE 2</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp; #define HTMLID_OPTIONS 3</pre></td></tr></tbody></table><p style="margin: 0cm 0cm 0pt 36pt; text-indent: -18pt; ">3.<span style="font-size: 7pt; line-height: normal; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-family: 宋体; ">在需要的时候执行</span>Find, View Source,&nbsp;<span style="font-family: 宋体; ">和</span>Internet Options&nbsp;<span style="font-family: 宋体; ">命令</span>.&nbsp;<span style="font-family: 宋体; ">举例来说，你可创建工具方法接收命令</span>ID<span style="font-family: 宋体; ">并调用</span>&nbsp;<em>IOleCommandTarget::Exec</em>,&nbsp;<span style="font-family: 宋体; ">如下片断所示</span>. (<span style="font-family: 宋体; ">注意在</span>MFC<span style="font-family: 宋体; ">代码中，</span><em>m_webBrowser</em>&nbsp;<span style="font-family: 宋体; ">是</span>&nbsp;WebBrowser&nbsp;<span style="font-family: 宋体; ">控件的实例</span>.&nbsp;<span style="font-family: 宋体; ">同样</span>,&nbsp;<em>nCmdID</em>&nbsp;<span style="font-family: 宋体; ">是定义的</span>ID)</p><table cellpadding="0" width="95%" border="0" style="margin-left: 36pt; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">HRESULT CYourView::ExecCmdTarget(DWORD nCmdID)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; LPDISPATCH lpDispatch = NULL;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; LPOLECOMMANDTARGET lpOleCommandTarget = NULL;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; HRESULT hr = E_FAIL;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // Get the IDispatch of the document.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; lpDispatch = m_webBrowser.GetDocument();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; ASSERT(lpDispatch);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (lpDispatch)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Get a pointer for the IOleCommandTarget interface.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hr = lpDispatch-&gt;QueryInterface(IID_IOleCommandTarget,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (void**)&amp;lpOleCommandTarget);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpDispatch-&gt;Release();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ASSERT(lpOleCommandTarget);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (SUCCEEDED(hr))</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Invoke the given command id </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// for the WebBrowser control.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hr = lpOleCommandTarget-&gt;Exec</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (pguidCmdGroup, nCmdID, 0, NULL, NULL);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpOleCommandTarget-&gt;Release();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; return hr;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p style="margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><h1><a name="t6" style="color: rgb(51, 102, 153); "></a>分发WebBrowser 控件</h1><p>现在你知道了如何利用WebBrowser控件和IE创建专用应用程序, 你大概感兴趣知道那些IE组件你需要打包在你的应用程序以便你的应用程序可以在系统商正常工作即使没有IE5被安装.无论你宿主 WebBrowser 控件还是自动化Internet Explorer, 你必须至少打包IE最小化安装的组件. 为理解为什么，请再一次察看图6-1展示的体系.你可以看到每一个组件是如何的依赖其他组件&#8212;而且这幅图仅仅展示了其表面.它未能展示webbrowser控件和IE多样特性的组件间的全部特征.因为由如此众多的组件调用,为了你的应用程序能够正常工作，你应当确信至少IE最小化安装于用户的操作系统.</p><p>别担心，你不需要打包每一个IE的组件.&nbsp;&nbsp;Internet Explorer 5 安装程序允许你定制你的安装以使你打包你仅需的组件.另外, 如果你使用Internet Explorer Administration Kit (可在<em><a href="http://ieak.microsoft.com/" target="_window2" style="color: #336699; text-decoration: none; ">http://ieak.microsoft.com</a></em>/找到) 建立你的安装程序, 你可以将IE默认安装，免掉多个确认安装步骤的对话框.</p></div><img src ="http://www.cppblog.com/yehao/aggbug/191624.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2012-09-22 21:46 <a href="http://www.cppblog.com/yehao/articles/191624.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何对webbrowser和IE编程（六）</title><link>http://www.cppblog.com/yehao/articles/191623.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Sat, 22 Sep 2012 13:45:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/191623.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/191623.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/191623.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/191623.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/191623.html</trackback:ping><description><![CDATA[<h2>使用VC++和COM API</h2><p style="color: #333333; font-family: Arial; line-height: 26px; ">尽管使用VC不像Vb中那么容易自动化IE，但是也不太难，尤其是你理解了CON和COM API。无论你使用MFC, ATL, 或者标准 C++自动化IE，方法都是一样&#8212;你使用COM API来实现.</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">VC++中创建一个Internet Explorer实例包括要调用COM API&nbsp;<em>CoCreateInstance</em>&nbsp;，指定第一个参数为&nbsp;<em>CLSID_InternetExplorer&nbsp;</em>。创建IE自动化实例不像创建包含webbrowser的Activex控件困难。你不需要实现容器或者site对象的必要接口。</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">来看看如何容易的使用<em>CoCreateInstance&nbsp;</em>创建IE实例吧。启动Visual C++, 新建MFC AppWizard (exe) 应用程序命名为 MfcAutoIE.选择dialog-based option, 认可其他缺省选项.</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">现在加入如VbAutoIE中的控件到表单.对话框看起来如 6-21. 分派ID到对话框的各个控件。 确信控件TAB次序如 Figure 6-22. (tab 次序影响到radio按钮的工作)<img height="303" alt="" src="http://blog.csdn.net/images/blog_csdn_net/shanhe/CH6_A_3.jpg" width="404" style="border: none; " /></p><p style="color: #333333; font-family: Arial; line-height: 26px; "><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></p><p style="color: #333333; font-family: Arial; line-height: 26px; "><strong>Figure 6-21.</strong>&nbsp;<em>MfcAutoIE dialog.</em>&nbsp;<img height="303" alt="" src="http://blog.csdn.net/images/blog_csdn_net/shanhe/CH6_A_4.jpg" width="404" style="border: none; " /></p><p style="color: #333333; font-family: Arial; line-height: 26px; "><strong></strong></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "><strong>Figure 6-22.</strong>&nbsp;<em>MfcAutoIE dialog tab order.</em></p><p style="color: #333333; font-family: Arial; line-height: 26px; ">现在用右键菜单设置每一个隐藏radio按钮的<em>Group&nbsp;</em>，属性设置如表 6-9.</p><p style="color: #333333; font-family: Arial; line-height: 26px; "><strong>Table 6-9.</strong>&nbsp;<em>Member Variables for MfcAutoIE Dialog Controls</em></p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em>Control</em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em>Type</em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em>Member Variable</em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>Hide radio button for AddressBar</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>int</em></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>m_nAddressBar</em></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>Edit box</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>CString</em></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>m_strStatusText</em></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>Hide radio button for MenuBar</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>int</em></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>m_nMenuBar</em></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>Hide radio button for StatusBar</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>int</em></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>m_nStatusBar</em></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>Hide radio button for ToolBar</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>int</em></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>m_nToolBar</em></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">我们使用ClassWizard 为表 6-9 中的控件建立变量时,他们自动加入到&nbsp;<em>CMfcAutoIEDlg</em>. 成员变量设置为<em>-1</em>.</p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 36pt 0pt; "><strong><span style="font-family: 宋体; ">编译</span>MfcAutoIE Example</strong><strong><span style="font-family: 宋体; ">之前我们设置编译的</span>Directory</strong><strong><span style="font-family: 宋体; ">次序</span>&nbsp;</strong><strong><span style="font-family: 宋体; ">属性</span></strong></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin-left: 36pt; margin-right: 36pt; ">编译之前，你需要处理一些重要任务:</p><p style="color: #333333; font-family: Arial; line-height: 26px; margin-left: 72pt; text-indent: -18pt; margin-right: 36pt; ">1.<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman'; ">&nbsp;&nbsp;&nbsp;&nbsp;</span>确信你已经从MSDN中下载IE5的头文件和库文件。</p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 36pt 0pt 72pt; text-indent: -18pt; ">2.&nbsp;<span style="font-family: 宋体; ">在</span>Tools/Options&nbsp;<span style="font-family: 宋体; ">菜单的</span>Directories<span style="font-family: 宋体; ">页</span>,&nbsp;<span style="font-family: 宋体; ">确信</span>lib<span style="font-family: 宋体; ">路径中包含</span>Internet Explorer 5&nbsp;<span style="font-family: 宋体; ">和</span>Windows 2000<span style="font-family: 宋体; ">库文件</span>.<span style="font-family: 宋体; ">载列表中。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 36pt 0pt 72pt; text-indent: -18pt; ">3.&nbsp;<span style="font-family: 宋体; ">配置</span>Include<span style="font-family: 宋体; ">：</span>&nbsp;<span style="font-family: 宋体; ">略</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 36pt 0pt; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">现在我们加入代码使之工作。 首先你应当包含ExDisp.h到你的对话框头文件&#8212;MfcAutoIEDlg.h. ExDisp.h 是包含了WebBrowser接口和类ID的头文件.确信你已经从MSDN下载了最新的版本。</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">建立一个private 或者protected 的数据类型，指向<em>IWebBrowser2&nbsp;</em>&nbsp;的指针,&nbsp;&nbsp;命名为<em>m_pInetExplorer</em>. 如下</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">protected:</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; IWebBrowser2* m_pInetExplorer;</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">现在在构造函数中初始化<em>m_pInetExplorer</em>&nbsp;为&nbsp;<em>NULL</em>&nbsp;。你必须也初始化COM. 放置一个<em>CoInitialize&nbsp;</em>的COM API调用在构造函数。构造函数看起来应当如下：</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">CMfcAutoIEDlg::CMfcAutoIEDlg(CWnd* pParent /*=NULL*/)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; : CDialog(CMfcAutoIEDlg::IDD, pParent),</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp; m_pInetExplorer(NULL)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; //{{AFX_DATA_INIT(CMfcAutoIEDlg)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; m_strStatusText = _T("");</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; m_nAddressBar = -1;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; m_nMenuBar = -1;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; m_nStatusBar = -1;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; m_nToolBar = -1;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; //}}AFX_DATA_INIT</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; //Note that LoadIcon does not require a subsequent DestroyIcon</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; //in Win32.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; m_hIcon = AfxGetApp()-&gt;LoadIcon(IDR_MAINFRAME);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // Initialize COM</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; CoInitialize(NULL);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">建立一个析构函数，以便调用<em>CoUninitialize</em>&nbsp;API 函数用以反初始化 COM. 此处的析构函数:</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">CMfcAutoIEDlg::~CMfcAutoIEDlg()</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // Uninitialize COM.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; CoUninitialize();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">在预备工作之后, 让我们开始实现具体的控制。首先为Start IE5 按钮建立一个消息循环. 通常，你可以使用ClassWizard建立消息循环处理句柄<em>.&nbsp;</em>在此消息句柄, 采用&nbsp;<em>CoCreateInstance</em>&nbsp;API 建立一个IE实例。 此处初建的Internet Explorer实例初始化为隐藏, 所以你必须使用<em>Visible</em>属性使他可见。为了导航到用户的主页，使用<em>GoHome</em>&nbsp;方法。此处为消息处理句柄代码：</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">void CMfcAutoIEDlg::OnStartIE5() </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // If an instance of Internet Explorer has</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // not already been created, create one.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // This instance will initially be hidden,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // so make it visible by using the Visible</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // property. Also, navigate to the user's</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // home page by using the GoHome method.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (m_pInetExplorer)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MessageBox</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (_T("Only one instance of Internet Explorer is allowed."));</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; else</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HRESULT hr;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hr = CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_SERVER,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IID_IWebBrowser2, (LPVOID*)&amp;m_pInetExplorer);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (SUCCEEDED(hr))</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Set the radio buttons to their correct values.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SetRadioButtons();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pInetExplorer-&gt;put_Visible(VARIANT_TRUE);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pInetExplorer-&gt;GoHome();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">在此代码中，我们首先检查是否IE的上一个实例已经建立。如果已经建立，将会显示一个错误消息框。(你仅仅能够启动一个IE的实例，随后你将可以看到如何检测IE窗口被关闭以便重置IE的数据成员。)如果一个IE的实例还未创建，&nbsp;<em>CoCreateInstance</em>&nbsp;将&nbsp;<em>CLSID_InternetExplorer</em>&nbsp;作为第一个参数被调用. (此类 ID 定义于ExDisp.h ，为Internet Explorer的唯一标示符.)</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">第二个参数我们设定为<em>NULL</em>&nbsp;，因为我们不希望此COM对象被聚合（be aggregated）. 我们希望IE运行在一个单独的进程空间，所以我们指定第三个参数为特殊值&nbsp;<em>CLSCTX_SERVER</em>&nbsp;.我们利用第四个参数指示哪一个接口我们将通过<em>CoCreateInstance</em>&nbsp;调用创建一个COM对象后被创建。在此例中，我们将一直希望获得<em>IWebBrowser2</em>, 所以我们指定<em>IID_IWebBrowser2</em>&nbsp;为第四个参数值。最后我们传送存储接口指针的变量. 对于此参数，你必须采用void类型传递一个指针的地址 (确信你传送的指针指向一个接口类型。)</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">如果一个IE实例成功创建，名为<em>SetRadioButtons&nbsp;</em>的成员变量被创建。这是一个protected 成员函数，检查当前地址栏、菜单条、工具条和状态条等的状态 ，用来设置radio 按钮组的状态。.为检查每一个的状态我们简单的获取属性关联的当前值 。</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">C++ 应用中使用COM 没有包装类, 属性被引用为使用&nbsp;<em>get_&nbsp;</em>and&nbsp;<em>put_</em>&nbsp;方法.为检取每一个用户问题的状态，我们简单的调用每一个关联的（UI）项目的<em>get_</em>&nbsp;方法 .除了&nbsp;<em>get_ToolBar</em>外其他get_方法返回指向<em>VARIANT_BOOL</em>&nbsp;数据类型，返回值指示用户接口是否可见或者隐藏。如果用户接口元素可见，将返回<em>VARIANT_TRUE&nbsp;</em>。如果该项目是隐藏的，将返回<em>VARIANT_FALSE&nbsp;</em>。这些值区别于<em>TRUE</em>和&nbsp;<em>FALSE</em>&nbsp;的用法.</p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 36pt 0pt; "><strong><span style="font-family: 宋体; ">提醒</span></strong></p><div align="center" style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 36pt 0pt; text-align: center; "><hr align="center" width="100%" size="2" /></div><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 36pt 0pt; "><span style="font-family: 宋体; ">当在</span>Visual C++<span style="font-family: 宋体; ">涉及</span>&nbsp;<em>VARIANT_BOOL</em>&nbsp;,&nbsp;<span style="font-family: 宋体; ">你必须使用</span><em>VARIANT_TRUE&nbsp;</em><em><span style="font-family: 宋体; ">或者</span></em><em>VARIANT_FALSE&nbsp;</em><span style="font-family: 宋体; ">代替</span>&nbsp;<em>TRUE&nbsp;</em>or&nbsp;<em>FALSE</em>.&nbsp;<em>VARIANT_TRUE</em><span style="font-family: 宋体; ">定义值</span>&nbsp;<em>0xffff</em>,&nbsp;<span style="font-family: 宋体; ">而</span>&nbsp;<em>TRUE</em>&nbsp;<span style="font-family: 宋体; ">定义为</span><em>1</em>.&nbsp;<span style="font-family: 宋体; ">如果你比较</span>&nbsp;<em>VARIANT_TRUE&nbsp;</em><span style="font-family: 宋体; ">和</span>&nbsp;<em>TRUE</em>,&nbsp;<span style="font-family: 宋体; ">你将发现在</span>Vb<span style="font-family: 宋体; ">中不匹配，你可以在涉及到</span><em>VARIANT_BOOL</em>.&nbsp;<span style="font-family: 宋体; ">使用</span>true<span style="font-family: 宋体; ">和</span>false<span style="font-family: 宋体; ">是由于</span>VB<span style="font-family: 宋体; ">替你实现了转换。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; "><em>get</em>_<em>ToolBar</em>&nbsp;方法不同于其他属性，因为它指向一个整型指针，所以我们如果发现返回非0,工具条可见。如果整型值是<em>0</em>,工具条将隐藏：</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 36pt 0pt; "><strong><span style="font-family: 宋体; ">提醒</span></strong></p><div align="center" style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 36pt 0pt; text-align: center; "><hr align="center" width="100%" size="2" /></div><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 36pt 0pt; "><span style="font-family: 宋体; ">如果一个属性只读</span>,&nbsp;<em>put_</em>&nbsp;<span style="font-family: 宋体; ">将不会出现。同样，如果一个属性只写，将不会出现</span><em>get_</em>&nbsp;<span style="font-family: 宋体; ">方法。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; ">此处为&nbsp;<em>SetRadioButtons</em>&nbsp;方法的代码:</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">void CMfcAutoIEDlg::SetRadioButtons()</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; VARIANT_BOOL vtBool = VARIANT_TRUE;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // Get the current state of the AddressBar.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; m_pInetExplorer-&gt;get_AddressBar(&amp;vtBool);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; m_nAddressBar = (vtBool == VARIANT_TRUE) ? 1 : 0;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // Get the current state of the MenuBar.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; m_pInetExplorer-&gt;get_MenuBar(&amp;vtBool);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; m_nMenuBar = (vtBool == VARIANT_TRUE) ? 1 : 0;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // Get the current state of the StatusBar.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; m_pInetExplorer-&gt;get_StatusBar(&amp;vtBool);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; m_nStatusBar = (vtBool == VARIANT_TRUE) ? 1 : 0;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // Get the current state of the ToolBar.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // Unlike the other get methods, get_ToolBar</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // takes a pointer to an integer.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; m_pInetExplorer-&gt;get_ToolBar(&amp;m_nToolBar);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; UpdateData(FALSE);&nbsp; // Initializes dialog box with changed values.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">:</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">void CMfcAutoIEDlg::OnAddrBarShowHide() </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; UpdateData(TRUE);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (m_pInetExplorer)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VARIANT_BOOL vtShow = </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_nAddressBar ? VARIANT_TRUE : VARIANT_FALSE;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pInetExplorer-&gt;put_AddressBar(vtShow);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">void CMfcAutoIEDlg::OnMenuBarShowHide() </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; UpdateData(TRUE);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (m_pInetExplorer)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VARIANT_BOOL vtShow = </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_nMenuBar ? VARIANT_TRUE : VARIANT_FALSE;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pInetExplorer-&gt;put_MenuBar(vtShow);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">void CMfcAutoIEDlg::OnStatusBarShowHide() </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; UpdateData(TRUE);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (m_pInetExplorer)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VARIANT_BOOL vtShow = </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_nStatusBar ? VARIANT_TRUE : VARIANT_FALSE;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pInetExplorer-&gt;put_StatusBar(vtShow);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">void CMfcAutoIEDlg::OnToolBarShowHide() </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; UpdateData(TRUE);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (m_pInetExplorer)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pInetExplorer-&gt;put_ToolBar(m_nToolBar);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">注意到<em>OnToolBarShowHide</em>&nbsp;方法中我们将<em>m_nToolBar</em>&nbsp;数据成员传递给<em>put_ToolBar</em>&nbsp;方法替代了<em>VARIANT_BOOL</em>. 我们暂时不解释为什么，就像<em>get_ToolBar</em>,&nbsp;<em>put_ToolBar</em>&nbsp;传递一个整型而不是<em>VARIANT_BOOL</em>.</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">现在利用ClassWizard 建立一个Change 按钮的消息循环处理句柄 。此消息的句柄将在任何时候设定set Internet Explorer 的状态条为edit 输入框内容。 代码看起来如下：</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">void CMfcAutoIEDlg::OnChangeStatusText() </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; UpdateData(TRUE);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (m_pInetExplorer)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _bstr_t bstrStatusText = m_strStatusText.AllocSysString();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pInetExplorer-&gt;put_StatusText(bstrStatusText);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">确信你在第一个任务就是调用传递TRUE的&nbsp;<em>UpdateData</em>&nbsp;and .这样的目的是更新对阿框中所有相关的控件, 包括&nbsp;<em>m_strStatusText.</em>&nbsp;如果<em>m_pInetExplorer</em>&nbsp;不是<em>NULL</em>&#8212;那意味着 Internet Explorer一个实例已经被创建&#8212;&nbsp;<em>StatusText</em>&nbsp;被设定为用户输入的文字。&nbsp;<em>StatusText</em>&nbsp;同样事采用<em>put_</em>&nbsp;设定<em>Visible&nbsp;</em>属性。 该函数需要一个BSTR的入口参数，所以调用&nbsp;<em>AllocSysString</em>&nbsp;方法使得<em>m_strStatusText</em>&nbsp;数据成员变量分派为<em>BSTR</em>&nbsp;可以传递给<em>put_StatusText</em>.&nbsp;<em>AllocSysString</em>&nbsp;是<em>CString</em>&nbsp;的方法，返回一个Cstring对象中值的&nbsp;<em>BSTR</em>&nbsp;类型。<em>BSTR</em>&nbsp;返回自&nbsp;<em>AllocSysString&nbsp;</em>存储于<em>_bstr_t</em>类型的变量, 一个 COM 编译器支持的Visual C++类。为了使用此类，你必须包含comdef.h 头文件，置于对话框实现文件<em>CMfcAutoIEDlg</em>&#8212;MfcAutoIEDlg.cpp. 该类将小心处理<em>BSTR</em>离开当前范围的状况,所以你不需要调用<em>SysFreeString</em>的<em>&nbsp;</em>Win32 API 以释放调用<em>put_StatusText</em>.之后的BSTR.</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">至此，我们基本上完成了。为了使用户输入Enter时不关闭对话框，重写基类对话框的<em>OnOK</em>方法。在此方法中，简单的不做任何事。确信你没有调用基类的<em>CDialog::OnOK</em>&nbsp;方法，否则，对话框会关闭。</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">现在来重写<em>OnCancel</em>&nbsp;的基类方法, 该方法调用于用户按下ESC或者点击对话框的右键菜单的关闭或者对话框的X按钮。在&nbsp;<em>OnCancel</em>中,如果一个Internet Explorer 实例已经被创建, 在调用<em>Quit</em>&nbsp;方法时关闭<em>InternetExplorer</em>&nbsp;对象。&nbsp;<em>Quit&nbsp;</em>甚至可以在用户默认关掉Internet Explorer. 如果出现此情形，&nbsp;<em>Quit&nbsp;</em>方法将返回&nbsp;<em>RPC_S_SERVER_UNAVAILABLE</em>, 标示Internet Explorer 不再可用.你可以简单忽略此错误消息。以下为<em>OnCancel</em>的代码:</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">void CMfcAutoIEDlg::OnCancel()</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (m_pInetExplorer)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pInetExplorer-&gt;Quit();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; CDialog::OnCancel();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">最后, 你必须释放掉指向IE的<em>IWebBrowser2&nbsp;</em>接口指针。你可以在对话框的析构函数中处理。此处为更型后的析构函数：</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">CMfcAutoIEDlg::~CMfcAutoIEDlg()</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // Release the WebBrowser interface pointer</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (m_pInetExplorer)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pInetExplorer-&gt;Release();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pInetExplorer = NULL;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; // Uninitialize COM</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; CoUninitialize();</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 宋体; ">现在，通常我们可以编译运行对话框应用程序。启动</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 'Times New Roman'; ">IE</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 宋体; ">实例，测试。</span><img src ="http://www.cppblog.com/yehao/aggbug/191623.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2012-09-22 21:45 <a href="http://www.cppblog.com/yehao/articles/191623.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何对webbrowser和IE编程（五）</title><link>http://www.cppblog.com/yehao/articles/191622.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Sat, 22 Sep 2012 13:44:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/191622.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/191622.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/191622.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/191622.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/191622.html</trackback:ping><description><![CDATA[<div style="color: #333333; font-family: Arial, Console, Verdana, 'Courier New'; border: 1px solid #cccccc; background-color: #eeeeee; float: left; min-width: 200px; padding: 4px 10px; "><p style="text-align: right; margin: 0px; "><span style="float: left; ">目录<a href="http://blog.csdn.net/shanhe/article/details/416176#" title="系统根据文章中H1到H6标签自动生成文章目录" style="color: #336699; text-decoration: none; ">(?)</a></span><a href="http://blog.csdn.net/shanhe/article/details/416176#" title="收起" style="color: #336699; text-decoration: none; ">[-]</a></p><ol style="margin-left: 14px; padding-left: 14px; line-height: 19px; "><li><a href="http://blog.csdn.net/shanhe/article/details/416176#t0" style="color: #336699; text-decoration: none; ">自动化 Internet Explorer</a></li><ol><li><a href="http://blog.csdn.net/shanhe/article/details/416176#t1" style="color: #336699; text-decoration: none; ">使用VB</a></li><ol><li><a href="http://blog.csdn.net/shanhe/article/details/416176#t2" style="color: #336699; text-decoration: none; ">VbAutoIE.bas</a></li></ol></ol></ol></div><div style="color: #333333; font-family: Arial, Console, Verdana, 'Courier New'; clear: both; "></div><div id="article_content" style="margin: 20px 0px 0px; line-height: 26px; font-family: Arial; color: #333333; "><h1><a name="t0" style="color: rgb(51, 102, 153); "></a>自动化&nbsp;Internet Explorer</h1><p>自动化打开了开发基于web应用的世界。 它允许你使用VB或者VC定制成熟的应用。自动化的好处：通过属性和方法可以改变IE的外观；你可以提供诸如导航条等用户接口以便控制用户的导航。</p><p>自动化IE很容易。你建立一个简单的应用启动一个IE实例，然后使用控制webbrowser的途径-<em>IWebBrowser2&nbsp;</em>接口来控制IE实例。</p><p style="margin: 0cm 36pt 0pt; "><strong><span style="font-family: 宋体; ">提醒</span></strong></p><div align="center" style="margin: 0cm 36pt 0pt; text-align: center; "><hr align="center" width="100%" size="2" /></div><p style="margin: 0cm 36pt 0pt; "><span style="font-family: 宋体; ">术语自动化（</span><em>automation</em><em><span style="font-family: 宋体; ">）</span></em><span style="font-family: 宋体; ">真实的含义是通过自动化接口</span>--<em>&nbsp;IDispatch</em>.<span style="font-family: 宋体; ">控制一个</span>COM<span style="font-family: 宋体; ">对象。但是在此是指控制</span>IE<span style="font-family: 宋体; ">的技术，你不需要直接通过</span><em>IDispatch</em></p><h2><a name="t1" style="color: rgb(51, 102, 153); "></a>使用VB</h2><p>前面已经介绍了如何五分钟在VB中使用webbrowser来创建全功能的浏览器应用. 你也可以大致使用此时间用VB自动化IE。让我们开始。</p><p>启动一个Standard EXE 工程，选择References 菜单项. 引用对话框展开如Figure 6-19：<img height="321" alt="" src="http://blog.csdn.net/images/blog_csdn_net/shanhe/CH7_1_1.jpg" width="404" style="border: none; " /></p><p><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></p><p><strong>Figure 6-19.</strong>&nbsp;<em>References dialog box.</em></p><p>滚动下拉，选中&nbsp;Microsoft Internet Controls 检查框,点击OK 。加入一个命令按钮到窗体,命名为<em>btnStart</em>, 修改标题为&nbsp;<em>Start IE5</em>. 然后双击加入click事件代码。</p><p>当用户点击Start IE5 按钮, 你想应用程序启动一个Internet Explorer 5实例. 先建立一个类型为&nbsp;<em>InternetExplorer</em>&nbsp;的全局变量. 命名为<em>InternetExplorer1</em>.</p><p>现在， 在<em>btnStart的Click&nbsp;</em>事件中, 加入如果上一个实例没有创建就创建新IE实例的代码。你可以使用<em>CreateObject</em>&nbsp;或者Vb的<em>New&nbsp;</em>关键字.如下:</p><p>&nbsp;</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">Set InternetExplorer1 = New InternetExplorer</pre></td></tr></tbody></table><p>&nbsp;</p><p>该代码创建一个新实例，但是实例是隐藏的，要显示该实例，设定<em>Visible&nbsp;</em>属性为&nbsp;<em>True</em>, 如下：</p><p>&nbsp;</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">InternetExplorer1.Visible = True</pre></td></tr></tbody></table><p>&nbsp;</p><p>现在你需要导航到某个web页，你可以如下调用<em>InternetExplorer</em>&nbsp;对象的Navigate方法, 如下:</p><p>&nbsp;</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">InternetExplorer1.Navigate "http://www.microsoft.com/"</pre></td></tr></tbody></table><p>&nbsp;</p><p>至此，整个Vb的自动化IE的源代码看起来如下:</p><p>&nbsp;</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">Option Explicit</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">Dim InternetExplorer1 As InternetExplorer</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">Private Sub btnStart_Click()</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; ' Only create a new instance of Internet Explorer</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; ' if one hasn't already been created.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; '</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; If Not InternetExplorer1 Is Nothing Then</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Exit Sub</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; End If</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; Set InternetExplorer1 = New InternetExplorer</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;' Make Internet Explorer visible and navigate</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; ' to Microsoft's home page.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; '</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; InternetExplorer1.Visible = True</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; InternetExplorer1.Navigate "http://www.microsoft.com/"</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">End Sub</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">Private Sub Form_Load()</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; Set InternetExplorer1 = Nothing</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">End Sub</pre></td></tr></tbody></table><p>&nbsp;</p><p>运行应用程序看到IE启动了! 新的IE实例将被启动导航到MS的主页。者不太困难，是不是？现在让我们加入一些实在的较酷的特征允许你控制你自己创建的IE实例。</p><p>首先保存工程为&nbsp;VbAutoIE.vbp, 且保存你的表单 VbAutoIE.frm. 然后加入一些控制到你的表单，如图Figure 6-20. 这些允许你显示或者隐藏IE中不同的用户接口特征如地址栏、菜单条、状态条和工具条等。你也可以加入文字到状态条。<img height="299" alt="" src="http://blog.csdn.net/images/blog_csdn_net/shanhe/CH7_2.jpg" width="404" style="border: none; " /></p><p>&nbsp;</p><p><strong>Figure 6-20.</strong>&nbsp;<em>Visual Basic form with controls to customize the Internet Explorer user interface.</em></p><p>现在如下表设定每一个控件的属性如表6-8.创建4个选项组,每一个包含 一个显示和一个隐藏选项按钮如Figure 6-20.</p><p><strong>Table 6-8.</strong>&nbsp;<em>Control Properties for a Visual Basic Program Automating Internet Explorer</em></p><p>&nbsp;</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em>Control</em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em>Properties</em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>Frame1-4</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>Captions = "<em>AddressBar</em>", "<em>MenuBar</em>", "<em>StatusBar</em>&nbsp;", and "<em>ToolBar</em>", respectively</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>Hide Option Buttons</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>Caption = "<em>Hide</em>"; Index =&nbsp;<em>0</em>; Value =&nbsp;<em>False</em>; Names =&nbsp;<em>optAddrBar</em>,&nbsp;<em>optMenuBar</em>,<em>optStatusBar</em>, and&nbsp;<em>optToolBar</em>, respectively</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>Show Option Buttons</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>Caption = "<em>Show</em>"; Index =&nbsp;<em>1</em>; Value =&nbsp;<em>True</em>; Names =&nbsp;<em>optAddrBar</em>,&nbsp;<em>optMenuBar</em>,<em>optStatusBar</em>, and&nbsp;<em>optToolBar</em>, respectively</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>Label</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>Caption = "<em>Status Text</em>"</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>TextBox</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>Name =&nbsp;<em>txtStatusText</em>. Remove the default text for the&nbsp;<em>Text&nbsp;</em>property</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>CommandButton</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>Caption = "<em>Change</em>"; Name =&nbsp;<em>btnChange</em></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td></tr></tbody></table><p>&nbsp;</p><p>加入控制<em>InternetExplorer</em>&nbsp;对象的代码控制浏览器的用户接口。看看清单6-1</p><p><strong>Listing 6-1.</strong></p><p>&nbsp;</p><table cellpadding="0" width="95%" border="0" style="width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><h3><a name="t2" style="color: rgb(51, 102, 153); "></a>VbAutoIE.bas</h3><pre style="white-space: pre-wrap; word-wrap: break-word; ">Option Explicit</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">Dim InternetExplorer1 As InternetExplorer</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">Const HideBar = 0</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">Const ShowBar = 1</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">Private Sub btnChange_Click()</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; On Error Resume Next</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; InternetExplorer1.StatusText = txtStatusText.Text</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">End Sub</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">Private Sub btnStart_Click()</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; ' Only create a new instance of Internet Explorer</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; ' if one hasn't already been created.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; '</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; If Not InternetExplorer1 Is Nothing Then</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Exit Sub</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; End If</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;Set InternetExplorer1 = New InternetExplorer</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;' Set the user interface features to match the</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; ' entries specified by the user.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; '</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; If optAddrBar(ShowBar).Value = True Then</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InternetExplorer1.AddressBar = True</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; Else</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InternetExplorer1.AddressBar = False</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; End If</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;If optMenuBar(ShowBar).Value = True Then</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InternetExplorer1.MenuBar = True</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; Else</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InternetExplorer1.MenuBar = False</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; End If</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;If optToolBar(ShowBar).Value = True Then</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InternetExplorer1.ToolBar = True</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; Else</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InternetExplorer1.ToolBar = False</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; End If</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; If optStatusBar(ShowBar).Value = True Then</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InternetExplorer1.StatusBar = True</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; Else</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InternetExplorer1.StatusBar = False</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; End If</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;' Make Internet Explorer visible and navigate</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; ' to Microsoft's home page.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; '</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; InternetExplorer1.Visible = True</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; InternetExplorer1.Navigate "http://www.microsoft.com/"</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">End Sub</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">Private Sub Form_Load()</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; Set InternetExplorer1 = Nothing</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">End Sub</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">Private Sub Form_Unload(Cancel As Integer)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; On Error Resume Next</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; InternetExplorer1.Quit</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">End Sub</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">Private Sub optAddrBar_Click(Index As Integer)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; On Error Resume Next</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; InternetExplorer1.AddressBar = CBool(Index)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">End Sub</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">Private Sub optMenuBar_Click(Index As Integer)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; On Error Resume Next</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; InternetExplorer1.MenuBar = CBool(Index)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">End Sub</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">Private Sub optStatusBar_Click(Index As Integer)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; On Error Resume Next</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; InternetExplorer1.StatusBar = CBool(Index)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">End Sub</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">Private Sub optToolBar_Click(Index As Integer)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; On Error Resume Next</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; InternetExplorer1.ToolBar = Index</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">End Sub</pre></td></tr></tbody></table><p>&nbsp;</p><p>在清单6-1, 当表单被装载，&nbsp;&nbsp;<em>InternetExplorer1&nbsp;</em>对象设定为<em>Nothing.当</em>Start IE5 按钮被点击, 我们检查确信没有上一个实例启动，如果启动了我们直接返回。</p><p><span style="font-size: 10.5pt; font-family: 宋体; ">如果上一实例没有启动，我们采用关键字</span><em><span style="font-size: 10.5pt; font-family: 'Times New Roman'; ">New&nbsp;</span></em><span style="font-size: 10.5pt; font-family: 宋体; ">创建一个新实例。然后我们检查选项组的状态</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; ">.</span><span style="font-size: 10.5pt; font-family: 宋体; ">我们依据选项当前值进行</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; ">IS</span><span style="font-size: 10.5pt; font-family: 宋体; ">属性的设置。然后设置</span><em><span style="font-size: 10.5pt; font-family: 'Times New Roman'; ">Visible&nbsp;</span></em><span style="font-size: 10.5pt; font-family: 宋体; ">属性为</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; ">&nbsp;<em>True.</em>&nbsp;</span><span style="font-size: 10.5pt; font-family: 宋体; ">最后我们使用</span><em><span style="font-size: 10.5pt; font-family: 'Times New Roman'; ">Navigate&nbsp;</span></em><span style="font-size: 10.5pt; font-family: 宋体; ">方法导航到</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; ">MS</span><span style="font-size: 10.5pt; font-family: 宋体; ">的主页</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; ">.</span></p></div><img src ="http://www.cppblog.com/yehao/aggbug/191622.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2012-09-22 21:44 <a href="http://www.cppblog.com/yehao/articles/191622.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何对webbrowser和IE编程（四）</title><link>http://www.cppblog.com/yehao/articles/191621.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Sat, 22 Sep 2012 13:43:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/191621.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/191621.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/191621.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/191621.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/191621.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 目录(?)[-]寄宿WebBrowser 控件使用VB打印web页使用 Visual C++使用 MFC使用 ATL打印 Web 页使用 Visual C++使用 MFC使用 ATL打印 Web 页寄宿WebBrowser 控件我们现在开始在VB和VC中创建一些程序来寄宿（Host）WebBrowser控件。在你完成本部分的样本，你将对如何创建寄宿一个WebBrowser控件的应用程序又一个基本的...&nbsp;&nbsp;<a href='http://www.cppblog.com/yehao/articles/191621.html'>阅读全文</a><img src ="http://www.cppblog.com/yehao/aggbug/191621.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2012-09-22 21:43 <a href="http://www.cppblog.com/yehao/articles/191621.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何对webbrowser和IE编程（一）</title><link>http://www.cppblog.com/yehao/articles/191620.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Sat, 22 Sep 2012 13:35:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/191620.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/191620.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/191620.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/191620.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/191620.html</trackback:ping><description><![CDATA[<p style="color: #333333; font-family: Arial; line-height: 26px; "><span style="font-family: 宋体; ">一、</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; "><span style="font-family: 宋体; ">因为工作缘故，需要研究对</span>IE<span style="font-family: 宋体; ">编程，所以翻译了</span>MS<span style="font-family: 宋体; ">的有关资料，供参考。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; ">IE<span style="font-family: 宋体; ">的体系<img height="296" src="http://blog.csdn.net/images/blog_csdn_net/shanhe/ie%20architecture.jpg" width="407" alt="" style="border: none; " /></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; "><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></p><p style="color: #333333; font-family: Arial; line-height: 26px; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; ">WebBrowser Host</p><p style="color: #333333; font-family: Arial; line-height: 26px; "><span style="font-family: 宋体; ">首先，必须有</span>COM<span style="font-family: 宋体; ">的基础知识，因为</span>IE<span style="font-family: 宋体; ">本身就是</span>COM<span style="font-family: 宋体; ">技术的典型应用。我们看到最上层是</span>WebBrowser<span style="font-family: 宋体; ">的宿主（</span>Host<span style="font-family: 宋体; ">），也就是任何你想重用</span>(ReUse)webbrowser control<span style="font-family: 宋体; ">的应用程序，可以是</span>vb<span style="font-family: 宋体; ">程序，也可以是</span>vc<span style="font-family: 宋体; ">或者任何其他语言的应用程序。应用程序必须是可容纳</span>activex<span style="font-family: 宋体; ">控件的容器。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; ">Webbrowser control<span style="font-family: 宋体; ">既是</span>activex control<span style="font-family: 宋体; ">也是</span>activex document&nbsp;<span style="font-family: 宋体; ">的宿主。作为控件，它可以置于任何</span>activex<span style="font-family: 宋体; ">容器，作为文档容器，它针对特殊的类型，调用特殊类型注册的文档</span>server<span style="font-family: 宋体; ">以显示文档。如果你想显示一个</span>.doc<span style="font-family: 宋体; ">文档，</span>webbrowser control<span style="font-family: 宋体; ">装载</span>windows word,<span style="font-family: 宋体; ">，对于</span>html<span style="font-family: 宋体; ">文档，</span>webbrowser<span style="font-family: 宋体; ">装载名为</span>mshtml<span style="font-family: 宋体; ">的组件</span>(<span style="font-family: 宋体; ">如图所示</span>)<span style="font-family: 宋体; ">。针对不同的文档，你不需要开发不同的应用，仅仅是调用</span>webbrowser control<span style="font-family: 宋体; ">即可。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; ">Shdocvw</p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">Shdocvw.dll<span style="font-family: 宋体; ">包含了</span>webbrowser control&nbsp;<span style="font-family: 宋体; ">，控制</span>webbrowser control (<span style="font-family: 宋体; ">就像控制其他任何</span>activex com&nbsp;<span style="font-family: 宋体; ">控件一样</span>)<span style="font-family: 宋体; ">，提供浏览能力给上层宿主。请注意</span>webbrowser control<span style="font-family: 宋体; ">位于第二级中。甚至</span>IE<span style="font-family: 宋体; ">也不直接而是通过</span>shdocw.dll<span style="font-family: 宋体; ">来使用</span>webbrowser control<span style="font-family: 宋体; ">的。尽管</span>shdocvw<span style="font-family: 宋体; ">提供了大部分的浏览功能，但是并不提供</span>IE<span style="font-family: 宋体; ">窗口的呈现功能。尽管如此，</span>shdocvw<span style="font-family: 宋体; ">还是提供了简单创建</span>web&nbsp;<span style="font-family: 宋体; ">应用程序的能力。之后章节会讲到如何将</span>ie<span style="font-family: 宋体; ">的高级特性加入到你的应用程序。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">MSHTML</p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; "><span style="font-family: 宋体; ">早期的</span>mshtml<span style="font-family: 宋体; ">具有读取显示</span>html<span style="font-family: 宋体; ">的功能。</span>MSHTML<span style="font-family: 宋体; ">实际上是一个</span>active&nbsp;<span style="font-family: 宋体; ">文档服务器，但是却可以作为其他控件的容器（如图中所示的）。记得吗，你可以将</span>activex<span style="font-family: 宋体; ">控件置于</span>html<span style="font-family: 宋体; ">中，此时</span>mshtml<span style="font-family: 宋体; ">就是一个</span>activex<span style="font-family: 宋体; ">宿主，还可以控制其他的控件如</span>vbscript&nbsp;<span style="font-family: 宋体; ">脚本引擎和</span>javascript<span style="font-family: 宋体; ">脚本引擎，</span>java applet ,geszhong<span style="font-family: 宋体; ">，各种插件</span>&#8212;<span style="font-family: 宋体; ">别意外，</span>plug-in<span style="font-family: 宋体; ">都是按照</span>ie activex<span style="font-family: 宋体; ">规范写的。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; "><span style="font-family: 宋体; ">二、</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">WebBrowser Control&nbsp;<span style="font-family: 宋体; ">与</span>&nbsp;Internet Explorer</p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; "><span style="font-family: 宋体; ">二者又太多的共同点，你都是通过</span>COM<span style="font-family: 宋体; ">接口来访问其功能。当调用</span>webbrowser<span style="font-family: 宋体; ">控件时，使用的是</span>webbrowser<span style="font-family: 宋体; ">对象，在</span>vc<span style="font-family: 宋体; ">中是使用</span>class ID CLSID_WebBrowser<span style="font-family: 宋体; ">的接口类。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; "><span style="font-family: 宋体; ">当自动化</span>ie<span style="font-family: 宋体; ">时，必须建立名为</span>&nbsp;InternetExplorer<span style="font-family: 宋体; ">的对象，</span>vc<span style="font-family: 宋体; ">等语言中使用名为</span>class ID CLSID_InternetExplorer<span style="font-family: 宋体; ">的接口类。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;<img height="244" src="http://blog.csdn.net/images/blog_csdn_net/shanhe/webbrowser%204%20interfaces.jpg" width="419" alt="" style="border: none; " /></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; "><span style="font-family: 宋体; ">接口</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">webbrowser<span style="font-family: 宋体; ">有</span>4<span style="font-family: 宋体; ">个接口（如图），其中</span>3<span style="font-family: 宋体; ">个提供全部的功能，第</span>4<span style="font-family: 宋体; ">个</span>DWebBrowserEvents2<span style="font-family: 宋体; ">接口暴露事件</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">ie4&nbsp;<span style="font-family: 宋体; ">之前，仅有</span>IwebBrowser<span style="font-family: 宋体; ">和</span>IwebBrowserApp<span style="font-family: 宋体; ">两个接口，且二者共享相同的功能，当开发</span>ie4<span style="font-family: 宋体; ">时候，决定加入第三个接口</span>IWebBrowser2<span style="font-family: 宋体; ">扩展</span>webbrowser<span style="font-family: 宋体; ">的功能。该接口派生于第二个接口。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">IWebBrowser</p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">IWebBrowser&nbsp;<span style="font-family: 宋体; ">仅仅是</span>WebBrowser control<span style="font-family: 宋体; ">的最初接口，</span>&nbsp;<span style="font-family: 宋体; ">提供基本的例如导航</span>web<span style="font-family: 宋体; ">页面的功能。</span>&nbsp;<span style="font-family: 宋体; ">作为其他派生接口的基础接口，有</span>8<span style="font-family: 宋体; ">个方法和</span>30<span style="font-family: 宋体; ">个属性。</span></p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><span style="font-family: 宋体; ">方法</span><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p></td><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em>&nbsp;</em></strong><strong><em><span style="font-family: 宋体; ">描述</span></em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>GoBack</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">导航到历史列表中的上一个页面</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>GoForward</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">导航到历史历表中的下一个项目</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>GoHome</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">导航到缺省页面</span>.</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>GoSearch</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">导航到缺省搜索页面</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>Navigate</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">导航到一个页面或者页面</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>Refresh</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">刷新当前页面</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>Refresh2</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">可以选择刷新级别，如下：</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><strong><em>REFRESH_NORMAL</em></strong>&nbsp;<span style="font-family: 宋体; ">普通刷新，并且不发送</span>HTTP&nbsp;<em>pragma:nocache</em>&nbsp;<span style="font-family: 宋体; ">到服务器</span>.</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><strong><em>REFRESH_IFEXPIRED</em></strong>&nbsp;<span style="font-family: 宋体; ">仅仅当页面失效时才发送刷新请求</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><strong><em>REFRESH_CONTINUE</em></strong>&nbsp;<span style="font-family: 宋体; ">内部使用，不要在编程时使用</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><strong><em>REFRESH_COMPLETELY</em></strong>&nbsp;<span style="font-family: 宋体; ">发送</span>HTTP&nbsp;<em>pragma:nocache</em>&nbsp;header&nbsp;<span style="font-family: 宋体; ">到服务器</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>Stop</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">停止当前导航</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; ">尽管WebBrowser control 提供了你需要的导航回退以及前向的方法，但是没有提供存取历史列表的途径. 你可与直接通过属性<em>LocationUR</em>来获取当前页的URL.</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">在VB或者VC++中调用<em>GoBack&nbsp;</em>和&nbsp;<em>GoForward&nbsp;</em>方法式很容易的.你可以使用WebBrowser control 或者 Internet Explorer对象. 举例来讲, 在VB中你可以如下调用：</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">WebBrowser1.GoBack&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ' Hosting WebBrowser control</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">InternetExplorer1.GoForward&nbsp; ' Automating Internet Explorer object</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">VC++中如下:</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">m_webBrowser.GoBack();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Hosting WebBrowser control</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">m_pInternetExplorer-&gt;GoForward(); // Automating Internet Explorer object</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">尽管&nbsp;<em>GoBack&nbsp;</em>和&nbsp;<em>GoForward&nbsp;&nbsp;</em>方法十分重要，当控制WebBrowser control或者自动化操作 Internet Explorer,<em>&nbsp;Navigate</em>&nbsp;is 却是最重要的方法.&nbsp;<em>Navigate&nbsp;</em>允许你导航到特定的你所想的web页或者文件.&nbsp;<em>Navigate</em>&nbsp;带有5个参数, 允许你指定特定的URL以实现导航以及其他定义导航行为的信息.</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">第一个参数是&nbsp;URL, 指示web页的位置和名称或者何处的文件你想装载。 (次擦书类型是&nbsp;<em>BSTR</em>.) URL 可以是你所使用的标准URL 协议类型的一种，例如HTTP 和 FILE, 或者是全路经文件名的本地文件系统, 例如 C:/MyFile.htm.</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">第二个参数,&nbsp;<em>Flags</em>, 你可指定如何或者甚至何处装载特定的URL. (参数的类型是指向&nbsp;<em>VARIANT</em>的指针)&nbsp;<em>Flags</em>&nbsp;的值来自名为&nbsp;<em>BrowserNavConstants&nbsp;</em>的枚举类型 ，定义于 ExDisp.h 头文件中且有6个值, 详细解释见下列表. 你可以指定一个或者多个<em>Flags</em>&nbsp;参数值 (请留意有些当前并未实现).</p><p style="color: #333333; font-family: Arial; line-height: 26px; margin-left: 36pt; text-indent: -18pt; "><span style="font-size: 10pt; font-family: Symbol; ">&#183;<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman'; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><em>navOpenInNewWindow</em>. 将导致一个新的窗口打开以显示URL. 缺省,如果你在自己的应用程序中控制 WebBrowser control，这些值将导致新的 Internet Explorer 浏览器窗口打开.</p><ul type="disc" style="color: #333333; font-family: Arial; line-height: 26px; "><li><em>navNoHistory</em>.&nbsp;<span style="font-family: 宋体; ">指定此</span>URL<span style="font-family: 宋体; ">将不加入到</span>URL<span style="font-family: 宋体; ">历史列表中</span></li><li><em>navNoReadFromCache</em>.&nbsp;<span style="font-family: 宋体; ">当前未实现</span>.</li><li><em>navNoWriteToCache</em>.&nbsp;<span style="font-family: 宋体; ">当前未实现</span>.</li><li><em>navAllowAutoSearch</em>.&nbsp;<span style="font-family: 宋体; ">如果指定的</span>URL<span style="font-family: 宋体; ">未找到，自动搜索功能将试图导航到通常的顶级域名如</span>.com .net .org<span style="font-family: 宋体; ">以找到正确的</span>URL<span style="font-family: 宋体; ">。如果失败，</span>&nbsp;URL<span style="font-family: 宋体; ">将传递给搜索引擎</span>.</li><li><em>navBrowserBar</em>.&nbsp;<span style="font-family: 宋体; ">如果可能，将</span>&nbsp;URL&nbsp;<span style="font-family: 宋体; ">装入到</span>&nbsp;Explorer&nbsp;<span style="font-family: 宋体; ">的地址栏</span>Bar<span style="font-family: 宋体; ">。</span></li></ul><p style="color: #333333; font-family: Arial; line-height: 26px; ">第三个参数&nbsp;<em>TargetFrameName</em>. 指定web页的哪一个frame将会发生导航. (参数的类型是指向<em>VARIANT</em>的指针)此字符串将为以存在于web页中的名字或者一个指定的值如&nbsp;<em>_top</em>&nbsp;或&nbsp;<em>_search</em>.&nbsp;<em>_top</em>&nbsp;值指定 URL 将被当前最顶层web页装入并不在任何一个当前页中存在的frame.&nbsp;&nbsp;<em>_search</em>&nbsp;指示搜索面板将被打开. (该值仅在你自动化操控Internet Explorer时发生.) 如果你指定的frame名称并未发现，, 新的Internet Explorer 窗口将被打开。</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">你可以使用&nbsp;<em>PostData&nbsp;</em>参数&nbsp;(第四个)通过HTTPpost事务将指定特定的数据发送到服务器. (参数的类型是指向&nbsp;<em>VARIANT</em>的指针) Post 处理用于将在HTML表单收集的数据发送到服务器。如果此参数不指定任何数据 ,&nbsp;&nbsp;<em>Navigate&nbsp;</em>方法将使用Get方法. 另外,如果你不指定 HTTP 协议的URL (换句话讲,如果你指定例如 FILE 协议的 URL),&nbsp;<em>PostData&nbsp;</em>参数将被忽略。</p><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 宋体; ">你也可以使用第五个参数</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 'Times New Roman'; ">,&nbsp;<em>Headers</em>,&nbsp;</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 宋体; ">以发送</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 'Times New Roman'; ">HTTP&nbsp;</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 宋体; ">头信息到服务器</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 'Times New Roman'; ">. (T</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 宋体; ">参数的类型是指向</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 'Times New Roman'; ">&nbsp;<em>VARIANT</em></span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 宋体; ">的指针</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 'Times New Roman'; ">)&nbsp;</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 宋体; ">这些加入的头信息将被</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 'Times New Roman'; ">&nbsp;WebBrowser&nbsp;</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 宋体; ">控件如常发送出去</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 'Times New Roman'; ">.&nbsp;</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 宋体; ">作为</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 'Times New Roman'; ">&nbsp;<em>PostData&nbsp;</em></span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 宋体; ">参数</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 'Times New Roman'; ">,&nbsp;</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 宋体; ">如果你并不指定第一个参数</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 'Times New Roman'; ">,&nbsp;<em>Headers&nbsp;</em></span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 宋体; ">将被忽略</span><span style="color: #333333; font-size: 10.5pt; line-height: 26px; font-family: 'Times New Roman'; ">.</span><img src ="http://www.cppblog.com/yehao/aggbug/191620.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2012-09-22 21:35 <a href="http://www.cppblog.com/yehao/articles/191620.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何对webbrowser和IE编程（二）</title><link>http://www.cppblog.com/yehao/articles/191619.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Sat, 22 Sep 2012 13:33:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/191619.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/191619.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/191619.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/191619.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/191619.html</trackback:ping><description><![CDATA[<p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; ">调用&nbsp;<em>Navigate&nbsp;</em>方法比<em>GoBack</em>&nbsp;以及&nbsp;<em>GoForward&nbsp;&nbsp;</em>要困难,但如果你正仅仅导航到URL 且并不传递任何附加参数, 它的调用很容易。 举例来说, VB中导航到 Microsoft 主页, 可如下:</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">WebBrowser1.Navigate "http://www.microsoft.com"</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; ">VB代码调用<em>Navigate&nbsp;</em>如此容易因为所有参数出第一个参数外都可以是可选. 如此相对照，VC++不可以省略任何参数. 如果你想使用VC++不是勇任何特别的参数导航到 Microsoft的 home page, 你必须传递空的<em>VARIANT&nbsp;</em>结构。 MFC 应用程序,你必须如下调用&nbsp;<em>Navigate</em></p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">COleVariant vtEmpty;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">m_webBrowser.Navigate(_T("http://www.microsoft.com"), &amp;vtEmpty, &amp;vtEmpty,</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;vtEmpty, &amp;vtEmpty);</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; ">该例子展示了在MFC应用程序中控制WebBrowser控件. 我传递一个普通的字符串而替代&nbsp;<em>BSTR&nbsp;</em>因为 MFC 提供了一个 WebBrowser 控件的包装类,第一个载包装类中是<em>LPCTSTR</em>, 一个普通的字符串. 其他参数为指向&nbsp;<em>VARIANT&nbsp;</em>结构的指针。 如果你不想指定任何特别的参数, 别仅仅传递&nbsp;<em>NULL</em>&nbsp;&#8212;那样做, 你的应用程序会招来崩溃。你必须传递一个空的<em>VARIANT&nbsp;</em>结构的指针. 前面的代码使用了<em>COleVariant&nbsp;</em>类, 那是一个与&nbsp;<em>CComVariant&nbsp;</em>类相似的类<a href="http://writeblog.csdn.net/fckeditor/editor/ch05a.htm" style="color: #336699; text-decoration: none; "></a>。&nbsp;<em>COleVariant</em>&nbsp;简单包装了&nbsp;<em>VARIANT&nbsp;</em>使得<em>VARIANT&nbsp;</em>结构易于使用.</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; "><strong>属性</strong>&nbsp;现在你看到了所有的&nbsp;<em>IwebBrowser&nbsp;</em>的方法，你大概向了解其属性。(我是不是太苛求了?)&nbsp;<em>IWebBrowser</em>&nbsp;接口有30个属性，描述于表6-2. 我一已按照<em>IWebBrowser</em>&nbsp;&nbsp;的Vtable中的字母序列出。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; "><strong>Table 6-2.</strong>&nbsp;IWebBrowser&nbsp;<em>属性按照vtable排序</em></p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p align="center" style=" text-align: center; "><strong><em><span style="font-family: 宋体; ">属性</span></em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p></td><td style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p align="center" style=" text-align: center; "><strong><em><span style="font-family: 宋体; ">描述</span></em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><em>Application</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><span style="font-family: 宋体; ">返回宿主</span>WebBrowser&nbsp;<span style="font-family: 宋体; ">控件的自动化对象</span>&nbsp;(<em>IDispatch</em>)&nbsp;<span style="font-family: 宋体; ">实现，如果对象不可用，则返回的</span>WebbOrwser<span style="font-family: 宋体; ">控件的自动化对象</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><em>Parent</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><span style="font-family: 宋体; ">返回</span>WebBrowser<span style="font-family: 宋体; ">控件的父控件的自动化实现</span>&nbsp;(<em>IDispatch</em>)&nbsp;<span style="font-family: 宋体; ">，通常是容器</span>&#8212;<span style="font-family: 宋体; ">举例来讲</span>,<span style="font-family: 宋体; ">，您的宿主或者</span>Internet Explorer&nbsp;<span style="font-family: 宋体; ">窗口。</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><em>Container</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><span style="font-family: 宋体; ">返回</span>WebBrowser<span style="font-family: 宋体; ">控件容器的自动化对象</span>&nbsp;(<em>IDispatch</em>)&nbsp;<span style="font-family: 宋体; ">。通常，该值返回同</span><em>Parent</em>&nbsp;<span style="font-family: 宋体; ">属性一样的值。</span>.</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><em>Document</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><span style="font-family: 宋体; ">返回活动文档的自动化实现</span>&nbsp;(<em>IDispatch</em>)&nbsp;<span style="font-family: 宋体; ">。如果</span>&nbsp;HTML&nbsp;<span style="font-family: 宋体; ">当前显示在</span>WebBrowser<span style="font-family: 宋体; ">，</span>&nbsp;<em>Document</em>&nbsp;<span style="font-family: 宋体; ">属性给出你存取</span>&nbsp;DHTML&nbsp;<span style="font-family: 宋体; ">对象模型的途径</span>.</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><em>TopLevelContainer</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><span style="font-family: 宋体; ">返回一个布尔值指示</span>IE<span style="font-family: 宋体; ">是否是</span>WebBRowser<span style="font-family: 宋体; ">控件的顶级容器。在</span>words<span style="font-family: 宋体; ">中，如果</span>IE<span style="font-family: 宋体; ">是宿主应用承需则返回</span><em>true</em></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><em>Type</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><span style="font-family: 宋体; ">返回已经在</span>WebBrowser<span style="font-family: 宋体; ">中装载的对象的类型。举例，如果</span>HTML document<span style="font-family: 宋体; ">被装载</span>,&nbsp;<em>Type&nbsp;</em><span style="font-family: 宋体; ">将返回</span>&nbsp;<em>Microsoft HTML Document 5.0</em>.&nbsp;<span style="font-family: 宋体; ">如果文档是</span>Word&nbsp;<span style="font-family: 宋体; ">文档</span>,&nbsp;<em>Type&nbsp;</em><span style="font-family: 宋体; ">返回</span>&nbsp;<em>Microsoft Word Document</em>.</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><em>Left</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p>.<span style="font-family: 宋体; ">返回或设置控件在容器窗口左边距</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><em>Top</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p>.<span style="font-family: 宋体; ">返回或设置控件在容器窗口顶部边距</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><em>Width</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><span style="font-family: 宋体; ">返回或设置</span>webbrowser<span style="font-family: 宋体; ">控件在窗口中的水平方向的向苏为单位宽度</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><em>Height</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><span style="font-family: 宋体; ">返回或设置</span>webbrowser<span style="font-family: 宋体; ">控件在窗口中的处置方向的向像素为单位高度</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><em>LocationName</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><span style="font-family: 宋体; ">返回一个</span>WebBrowser<span style="font-family: 宋体; ">当前显示的资源名称的字符串</span>&nbsp;(<span style="font-family: 宋体; ">换句话讲</span>, HTML&nbsp;<span style="font-family: 宋体; ">页</span>, Word&nbsp;<span style="font-family: 宋体; ">文档</span>,<span style="font-family: 宋体; ">，</span>folder,&nbsp;<span style="font-family: 宋体; ">诸如此类</span>)&nbsp;<span style="font-family: 宋体; ">。</span>&nbsp;<span style="font-family: 宋体; ">如果资源是</span>&nbsp;HTML&nbsp;<span style="font-family: 宋体; ">页，字符串是标题。如果资源是文件或者文件夹，字符串为文件名或者文件夹名。</span>&#8212;<span style="font-family: 宋体; ">举例</span>, foo.doc&nbsp;<span style="font-family: 宋体; ">（</span>Word<span style="font-family: 宋体; ">文档）或者</span>&nbsp;&nbsp;Temp&nbsp;<span style="font-family: 宋体; ">（</span>temp directory.<span style="font-family: 宋体; ">）</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><em>LocationURL</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><span style="font-family: 宋体; ">返回</span>WebBrowser<span style="font-family: 宋体; ">正在显示的资源的</span>URL</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><em>Busy</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><p><span style="font-family: 宋体; ">返回一个布尔值指示</span>WebBrowser&nbsp;<span style="font-family: 宋体; ">当前是否正在装入</span>&nbsp;URL.<span style="font-family: 宋体; ">。如果当前属性返回</span>&nbsp;<em>true</em>,<em>&nbsp;</em><span style="font-family: 宋体; ">你可以使用</span>&nbsp;<em>Stop</em>&nbsp;<span style="font-family: 宋体; ">方法取消代掉导航。</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; ">看完表&nbsp;6-2, 清晰展示了你可使用的属性. 当中的一些可能需要更多的解释.&nbsp;<em>IWebBrowser</em>&nbsp;使用的相当多的一个属性是&nbsp;<em>LocationURL</em>, 给出了当前你装入WebBrowser窗口的 URL。 获取<em>LocationURL</em>&nbsp;值在VB中相当容易：</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">Dim strLocation</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">strLocation = WebBrowser1.LocationURL</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; ">Visual C++的MFC应用,&nbsp;&nbsp;MFC 包装类使的访问<em>LocationURL</em>&nbsp;很容易. 你简单调用&nbsp;<em>GetLocationURL</em>方法,该方法返回一个&nbsp;<em>CString</em>&nbsp;对象. 当你想在自动化IE中或者webBrowser的MFC应用中访问<em>LocationURL</em>&nbsp;when automating Internet Explorer or when hosting the WebBrowser control in a C++ application that's not built by using MFC, 你必须调用携带一指向BSTR的指针<em>。</em><em>BSTR</em>&nbsp;将包含返回值. 此处展示如何在 C++中使用:</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">BSTR bstrURL;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">m_pInternetExplorer-&gt;get_LocationURL(&amp;bstrURL);</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; ">存取&nbsp;<em>Document</em>&nbsp;属性在VB中相当容易，当定义一个变量后（举例,&nbsp;<em>HtmlDoc</em>）, 值需要 set 为<em>Document</em>&nbsp;属性：</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">Set HtmlDoc = WebBrowser1.Document</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; ">MFC 中也很容易,使用 MFC 包装类的GetDocument方法：</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">IDispatch* pDisp;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">pDisp = m_webBrowser.GetDocument();</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; "><em>GetDocument&nbsp;</em>返回指向代表文档&nbsp;<em>IDispatch</em>&nbsp;接口的指针. 如果&nbsp;<em>GetDocument&nbsp;</em>失败, 该对象将为<em>NULL</em>.</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; ">非MFC C++ 应用或者任何自动化IE的C++ 应用访问<em>Document</em>&nbsp;属性就只能够采用调用COM的方法&#8212;通过属性的<em>get_</em>方法. (注艺属性实只读,所以这里无<em>put_&nbsp;</em>方法.) 当调用&nbsp;<em>Document&nbsp;&nbsp;</em>的<em>get_</em>&nbsp;方法,你传递一个接受&nbsp;<em>IDispatch</em>&nbsp;的指针.此处展示了如何调用：</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; background-color: transparent; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">IDispatch* pDisp;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">HRESULT hr = m_pInternetExplorer-&gt;get_Document(&amp;pDisp);</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; ">当使用这些代码,你可以使用 SUCCEEDED 宏（ Win32 API的一部分）, 以监测调用是否成功。在尝试使用<em>Idispatch</em>接口前你应当确信调用成功。</p><img src ="http://www.cppblog.com/yehao/aggbug/191619.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2012-09-22 21:33 <a href="http://www.cppblog.com/yehao/articles/191619.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何对webbrowser和IE编程（三）</title><link>http://www.cppblog.com/yehao/articles/191618.html</link><dc:creator>厚积薄发</dc:creator><author>厚积薄发</author><pubDate>Sat, 22 Sep 2012 13:32:00 GMT</pubDate><guid>http://www.cppblog.com/yehao/articles/191618.html</guid><wfw:comment>http://www.cppblog.com/yehao/comments/191618.html</wfw:comment><comments>http://www.cppblog.com/yehao/articles/191618.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yehao/comments/commentRss/191618.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yehao/services/trackbacks/191618.html</trackback:ping><description><![CDATA[<h3><a href="http://blog.csdn.net/shanhe/article/details/397373">http://blog.csdn.net/shanhe/article/details/397373</a>&nbsp;<br /><em>IWebBrowserApp</em></h3><p style="color: #333333; font-family: Arial; line-height: 26px; "><em>IWebBrowserApp</em>&nbsp;接口仅仅在IE中实现。 典型的,你使用<em>InternetExplorer</em>&nbsp;对象创建一个IE的实例. 然后你使用&nbsp;<em>IWebBrowserApp</em>&nbsp;接口操纵此实例. (今天采用<em>IWebBrowser2</em>&nbsp;替代)<em>IWebBrowserApp</em>&nbsp;接口继承自&nbsp;<em>IWebBrowser</em>, 所以它提供&nbsp;<em>IWebBrowser&nbsp;</em>的全部功能。</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">因为<em>IWebBrowserApp</em>呈现一个IE窗口的实例, 所以它的方法和属性典型地允许你控制浏览器窗口的用户接口。 这些方法和属性并非包含在WebBrowser的&nbsp;<em>IWebBrowser&nbsp;</em>中的：寄宿control的应用程序提供诸如状态条, 工具条, 以及菜单条等用户接口. WebBrowser 控件仅仅用于装载web页以及其它类型文件。</p><p style="color: #333333; font-family: Arial; line-height: 26px; "><em>IWebBrowserApp</em>&nbsp;有4个方法和10 各属性。</p><p style="color: #333333; font-family: Arial; line-height: 26px; "><strong>方法</strong>&nbsp;<em>IWebBrowserApp&nbsp;</em>接口的属性很直观立如下表, 但是有2个有理由值的讨论：<em>GetProperty</em>&nbsp;和<em>PutProperty</em>. 此两个方法允许你在IE属性包（property bag）中存储一个属性一边你能够在其后重新找回他们。 你将典型地从一个web页上存储一些状态信息到另一个web页 (事实上,使用<em>IWebBrowser2</em>&nbsp;接口你可以在宿主一个WebBrowser 控件时候使用此方法)</p><p style="color: #333333; font-family: Arial; line-height: 26px; "><strong>Table 6-3.</strong>&nbsp;IWebBrowserApp&nbsp;<em>&nbsp;vtable 次序的方法</em></p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em><span style="font-family: 宋体; ">方法</span></em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p></td><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em><span style="font-family: 宋体; ">描述</span></em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>Quit</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">促使</span>&nbsp;Internet Explorer&nbsp;<span style="font-family: 宋体; ">窗口关闭。换句话讲，将自动化操作关闭</span>IE<span style="font-family: 宋体; ">实例</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>ClientToWindow</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">转换一个点从窗口坐标到客户坐标。</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>PutProperty</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">存储一个属性值到</span>ie<span style="font-family: 宋体; ">的属性包，将可以随手采用</span><em>GetProperty</em>.<span style="font-family: 宋体; ">获取</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>GetProperty</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">获取先前由</span>&nbsp;<em>PutProperty</em>.<span style="font-family: 宋体; ">方法存储的属性值</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">VB代码：</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">InternetExplorer1.PutProperty "CurrentPicture", 10</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">InternetExplorer1.GetProperty("CurrentPicture")</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">VC++代码：</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">CSomeClass::PutGetProperty(VARIANT vtCurrentValue, VARIANT* vtNewValue)</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">{</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; HRESULT hr;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; hr = m_pInternetExplorer-&gt;PutProperty(L"CurrentPicture",</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vtCurrentValue);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; if (SUCCEEDED(hr))</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; {</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp; // Notice that vtNewValue is already a pointer, so you</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp; // don't have to pass the address to GetProperty.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp; //</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp; hr = m_pInternetExplorer-&gt;GetProperty(L"CurrentPicture", </pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vtNewValue);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; }</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;<p>&nbsp;</p></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp; return hr;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">}</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; "><em>PutGetProperty</em>&nbsp;方法接受包含当前属性值的&nbsp;<em>VARIANT</em>&nbsp;变量指针且将接收属性值。</p><p style="color: #333333; font-family: Arial; line-height: 26px; "><strong>属性</strong>&nbsp;<em>IWebBrowserApp&nbsp;</em>接口有10 个属性.<strong>&nbsp;Table 6-4.</strong>&nbsp;IWebBrowserApp&nbsp;<em>vtable 次序的属性</em></p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em><span style="font-family: 宋体; ">属性</span></em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p></td><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em><span style="font-family: 宋体; ">描述</span></em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>Name</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">返回对象的名称</span>t. (<span style="font-family: 宋体; ">举例，当自动化</span>IE<span style="font-family: 宋体; ">，</span>&nbsp;<em>Name</em>&nbsp;<span style="font-family: 宋体; ">属性将返回</span>&nbsp;<em>Microsoft Internet Explorer</em>.)</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>HWND</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">返回</span>IE<span style="font-family: 宋体; ">窗口的句柄</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>FullName</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">返回</span>ie<span style="font-family: 宋体; ">可执行文件的全路径</span>&nbsp;(iexplore.exe).</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>Path</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">返回</span>IE<span style="font-family: 宋体; ">应用程序的全路径</span>.</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>Visible</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">监测和设置</span>IE<span style="font-family: 宋体; ">窗口是否可见。</span>&nbsp;(<span style="font-family: 宋体; ">换句话讲，你可与使用此属性显示</span>/<span style="font-family: 宋体; ">隐藏</span>)</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>StatusBar</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">显示或者隐藏</span>IE<span style="font-family: 宋体; ">状态条，也可监测当前状态条</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>StatusText</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">设置或隐藏状态条文字</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>ToolBar</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">显示或者隐藏</span>IE<span style="font-family: 宋体; ">工具条，也可监测当前工具条状态</span>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>MenuBar</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">显示或者隐藏</span>IE<span style="font-family: 宋体; ">菜单条，也可监测当前工具菜单态</span>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>FullScreen</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">设置或者检测一个值指示</span>IE<span style="font-family: 宋体; ">当前是否最大化显示。最大化显示，</span>iE<span style="font-family: 宋体; ">占据整个屏幕</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">Table 6-4 中的属性列表直截了当且易于使用。举例来说， 如果你想从你的Vb程序中获取IE状态条中的文字，你应当使用如下代码：</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">Dim strStatusText</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">strStatusText = InternetExplorer1.StatusText</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">使用MFC包装类的VC++程序代码如下：</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">BSTR bstrStatusText;</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">HRESULT hr = m_pInternetExplorer-&gt;get_StatusText(&amp;bstrStatusText);</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><h3><a name="t1" style="color: rgb(51, 102, 153); "></a><em>IWebBrowser2</em></h3><p style="color: #333333; font-family: Arial; line-height: 26px; ">因为COM规则要求接口恒久不变, 要加入新的工呢高COM,你必须增加新的接口。 新的接口可扩展自其他接口已扩展功能。 举例,当心的需求引入WebBrowser 和Internet Explorer 接口, 开发者被要求建立一个新的接口:&nbsp;<em>IWebBrowser2</em>.</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">早期,&nbsp;<em>IWebBrowser2&nbsp;</em>继承自&nbsp;<em>IWebBrowser&nbsp;</em>和&nbsp;<em>IWebBrowserApp</em>,<em>&nbsp;</em>还提供不包含在着两个接口中的功能.<em>&nbsp;所以你应当使用</em>&nbsp;<em>IWebBrowser2</em>&nbsp;接口替代 来操纵WebBrowser 控件或者 Internet Explorer.</p><p style="color: #333333; font-family: Arial; line-height: 26px; "><em>IWebBrowser2&nbsp;</em>接口有4个方法和8个属性.</p><p style="color: #333333; font-family: Arial; line-height: 26px; "><strong>方法</strong>&nbsp;&nbsp;&nbsp;<em>IWebBrowser2</em>&nbsp;接口方法如下描述，按照 vtable 次序, in Table 6-5.</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">也许<em>IWebBrowser2&nbsp;</em>、接口踵使用最多的方法是<em>ExecWB</em>. 它通过WebBrowser实现了一个&nbsp;<em>IOleCommandTarget</em>&nbsp;接口的Exec的包装实现。 在&nbsp;<em>ExecWB&nbsp;</em>方法 被创建前, 你不可以直接从VB中调用<em>IOleCommandTarget::Exec</em>, 因为VB不可访问&nbsp;<em>IOleCommandTarget</em>&nbsp;接口 ，因而VB不可直接使用该接口的ExecWB方法。&nbsp;<em>IOleCommandTarget::Exec&nbsp;</em>方法过去大量使用，所以 WebBrowser 开发者决定创建<em>ExecWB</em>&nbsp;以使事情变得容易。</p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "><strong>Table 6-5.</strong>&nbsp;IWebBrowser2&nbsp;<em>&nbsp;Vtable 次序的方法</em></p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em><span style="font-family: 宋体; ">方法</span></em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p></td><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em><span style="font-family: 宋体; ">描述</span></em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>Navigate2</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">功能基于</span><em>Navigate</em>&nbsp;<span style="font-family: 宋体; ">方法，不同在于</span>&nbsp;<em>Navigate2</em>&nbsp;<span style="font-family: 宋体; ">允许你导航到飞</span>URL<span style="font-family: 宋体; ">表达的地方，例如</span>Windows shell folder. (Windows shell folder&nbsp;<span style="font-family: 宋体; ">是指向标示符指针</span>,&nbsp;<span style="font-family: 宋体; ">或者</span>windows shell<span style="font-family: 宋体; ">命名空间中的</span>&nbsp;PIDL,)</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>QueryStatusWB</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>IoleCommandTarget</em><span style="font-family: 宋体; ">接口的</span><em>QueryStatus</em><span style="font-family: 宋体; ">方法在</span>&nbsp;WebBrowser.<span style="font-family: 宋体; ">中的包装实现</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>ExecWB</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>IoleCommandTarget</em><span style="font-family: 宋体; ">接口的</span><em>Exec</em><span style="font-family: 宋体; ">方法在</span>&nbsp;WebBrowser.<span style="font-family: 宋体; ">中的包装实现</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>ShowBrowserBar</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">显示或者隐藏特定的浏览器条</span>.&nbsp;<span style="font-family: 宋体; ">该方法仅仅用于</span><em>InternetExplorer</em>&nbsp;<span style="font-family: 宋体; ">对象</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; ">为什么你无论如何都要调用ExecWB方法？因为它提供了你需要的功能（通过<em>IOleCommandTarget::Exec</em>）不是暴露于webbrowser接口。你大概疑惑于为社么开发者不实现扩展属性和方法。记住：COM规则是一旦接口发表就不可改变。所以你不能够不能增加功能而不创建新的接口。</p><p style="color: #333333; font-family: Arial; line-height: 26px; "><em>ExecWB</em>&nbsp;方法允许WebBrowser 开发者增加新的功能而不用创建新的接口。再之, 那是由WebBrowser 通过&nbsp;<em>ExecWB</em>&nbsp;代表性的暴露不常用的工的途径, 譬如调用 Save As 对话框或者缩放web页的字体。&nbsp;&nbsp;<em>ExecWB</em>&nbsp;工作的方法是传递一个你想调用的command ID 和必需的参数. 太多的 command IDs ，他们包含于<em>OLECMDID</em>&nbsp;实现文档头文件he DocObj.h .</p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; ">作为举例, 支持缩放web页的内容字体。Internet Explorer 允许你通过View菜单的Text Size子菜单改变字体的大小从最小到最大。&nbsp;<em>ExecWB</em>&nbsp;方法暴露了允许你改变显示在浏览器中的文字大小。对于Zoom 命令, 你可指定特殊值<em>0</em>,&nbsp;<em>1</em>,&nbsp;<em>2</em>,&nbsp;<em>3</em>, or&nbsp;<em>4</em>,&nbsp;&nbsp;<em>0&nbsp;</em>是最小字体 ，4是最大字体。以下举例为改变字体为最大（VB）：</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">WebBrowser1.ExecWB OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, _</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CLng(4), Null</pre></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; ">再次代码中, 我调用&nbsp;<em>ExecWB</em>&nbsp;方法, 传递<em>OLECMDID_ZOOM</em>&nbsp;常量给第一个参数. 此常量指定 zoom 操作将被执行。 第二个参数传递给<em>ExecWB</em>&nbsp;不要提示用户。另外的选择, 你可以提醒用户而是用<em>OLECMDEXECOPT_PROMPTUSER</em>. (见 DocObj.h.)</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">第三个输入参数指示要设定的文字尺寸。我想是文字尽可能的大,所以我指定了4 。注意我在调用中使用了VB的Clng函数包装此值,转换我指定的此值为一个variant&#8212;输入需要的类型.最后为一个输出参数包含任何返回值。因为返回值不需要关心，我传递<em>Null</em>.</p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "><strong>属性</strong>&nbsp;<em>IWebBrowser2&nbsp;</em>接口有8个属性。 (Table 6-6 按照vtable次序展示其)。他们都很直观，我仅仅解释恰宏很特别的一个&#8212;<em>AddressBar</em>.</p><p style="color: #333333; font-family: Arial; line-height: 26px; "><strong>Table 6-6.</strong>&nbsp;IWebBrowser2&nbsp;<em>Properties in Vtable Order</em></p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em><span style="font-family: 宋体; ">属性</span></em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p></td><td style="border: #d4d0c8; padding: 3.75pt; "><p align="center" style=" text-align: center; "><strong><em><span style="font-family: 宋体; ">描述</span></em></strong><strong></strong></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>ReadyState</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">返回</span>WebBrowser&nbsp;<span style="font-family: 宋体; ">的状态</span>(<span style="font-family: 宋体; ">换句话讲</span>&nbsp;<span style="font-family: 宋体; ">，该属性指示文档是否完成装载</span>).<span style="font-family: 宋体; ">尽管你可以使用</span>&nbsp;<em>ReadyState</em>&nbsp;<span style="font-family: 宋体; ">属性</span>,&nbsp;<span style="font-family: 宋体; ">使用</span>&nbsp;<em>DocumentComplete</em>&nbsp;<span style="font-family: 宋体; ">时间检测文档是否装载还是比较好些。</span>&nbsp;(<span style="font-family: 宋体; ">那意味着所有</span>HTML<span style="font-family: 宋体; ">和文档被装载</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>Offline</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>.<span style="font-family: 宋体; ">返回或者设置检测</span>webbrowser<span style="font-family: 宋体; ">是否处于脱机模式的变量</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>Silent</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">返回或设置</span>&nbsp;WebBrowser&nbsp;<span style="font-family: 宋体; ">是否处于沉默模式。如果处于沉默模式，意味着没有对话框可以被显示</span>.</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>RegisterAsBrowser</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>.<span style="font-family: 宋体; ">设置或者检测</span>Webbrowser<span style="font-family: 宋体; ">是否是作为顶层浏览器被登记</span></p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>RegisterAsDropTarget</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p>.<span style="font-family: 宋体; ">设置或返回</span>WebBrowser<span style="font-family: 宋体; ">是否作为导航的拖放对象</span>&nbsp;<span style="font-family: 宋体; ">。如果登记委托放对象</span>,<span style="font-family: 宋体; ">用户可直接拖放连接到浏览器</span>&nbsp;&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>TheaterMode</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">返回或者设置</span>Internet Explorer<span style="font-family: 宋体; ">是否处于</span>theater&nbsp;<span style="font-family: 宋体; ">或者</span>&nbsp;normal window&nbsp;<span style="font-family: 宋体; ">模式</span>.<span style="font-family: 宋体; ">。在</span>theater&nbsp;<span style="font-family: 宋体; ">模式</span>, Internet Explorer<span style="font-family: 宋体; ">占据整个屏幕就像处于</span>FullScreen&nbsp;<span style="font-family: 宋体; ">模式，但也有最小化的用户接口元素</span>&nbsp;(<span style="font-family: 宋体; ">此属性仅仅展示于</span><em>InternetExplorer</em><span style="font-family: 宋体; ">对象</span>)</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>AddressBar</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">显示或者隐藏地址栏</span>(<span style="font-family: 宋体; ">此属性仅仅展示于</span><em>InternetExplorer</em>&nbsp;<span style="font-family: 宋体; ">对象</span>)</p><p>&nbsp;</p><p>&nbsp;</p></td></tr><tr><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><em>Resizable</em></p><p>&nbsp;</p><p>&nbsp;</p></td><td valign="top" style="border: #d4d0c8; padding: 3.75pt; "><p><span style="font-family: 宋体; ">返回或者设置</span>Internet Explorer<span style="font-family: 宋体; ">是否可被调整大小</span>,&nbsp;<span style="font-family: 宋体; ">你可利用此属性防止用户改变</span>webbrowser<span style="font-family: 宋体; ">的大小</span>(<span style="font-family: 宋体; ">此属性仅仅展示于</span><em>InternetExplorer</em>&nbsp;<span style="font-family: 宋体; ">对象</span>)</p><p>&nbsp;</p><p>&nbsp;</p></td></tr></tbody></table><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; margin: 0cm 0cm 0pt 10.5pt; text-indent: -10.5pt; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "><em>AddressBar</em>&nbsp;属性允许你显示/隐藏Internet Explorer 地址栏&#8212;一个包含可输入URL的文本框 允许你导航到某个Url。 能够显示或者隐藏地址条允许你完全控制你的用户的导航体验</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">在你的企业网络或者中小学控制用户导航体验.在此环境下，你将控制用户的导航以至于可确定某些不恰当地页面不可访问。你可创建你自己的浏览器。但是如果你没有时间和资源这么做，你可以自动化IE来代替.自动化IE允许你管掉所有的用户界面允许用户导航到某个web页,像菜单条, 工具条,以地址栏. 之后你可建立一定数量的可访问web页连接列表给用户。</p><p style="color: #333333; font-family: Arial; line-height: 26px; ">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; "></p><p style="color: #333333; font-family: Arial; line-height: 26px; ">关掉这些用户接口很容易. VB代码:</p><table cellpadding="0" width="95%" border="0" style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; width: 659px; "><tbody><tr><td style="border: #d4d0c8; padding: 3.75pt; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">InternetExplorer1.AddressBar = False</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">InternetExplorer1.ToolBar = False</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">InternetExplorer1.MenuBar = False</pre></td></tr></tbody></table><img src ="http://www.cppblog.com/yehao/aggbug/191618.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yehao/" target="_blank">厚积薄发</a> 2012-09-22 21:32 <a href="http://www.cppblog.com/yehao/articles/191618.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>