VC编程技巧:IE控件的高级用法
一、如何显示内存中的 HTML 网页
二、屏蔽 IE 控件的上下文菜单
三、扩展 HTML 脚本中的 external 对象
四、显示 HTML 样式的对话窗
五、执行 HTML 脚本
http://www.yesky.com/326/1950826.shtml
一、如何显示内存中的 HTML 网页
或者因为网页保密的考虑;或者因为软件分发的考虑,有的时候就需要让 IE 或 IE 浏览器控件显示内存或资源中的 HTML 网页。在 MFC 中,CHtmlView::LoadFromResource() 可以显示程序资源中的 HTML 内容。我们都知道MFC的 CHtmlView 其实是对 IWebBrowser2 的一个包装,但是在 IWebBrowser2 中却没有类似的方法。那么它是如何实现的那?步骤如下:
1、首先通过 IWebBrowser2::Navigate2() 显示一个网页,其目的是产生有效的对象,从而得到 IHTMLDocument2 接口;
2、IWebBrowser2::get_Document() 得到 IHTMLDocument2 接口指针;
3、IHTMLDocument2::QueryInterface() 得到 IPersistStreamInit 接口指针;
4、IPersistStreamInit::InitNew() 初始化接口对象;
5、IPersistStreamInit::Load() 装载内存中的 HTML 数据流(IStream *);
内存指针转换为流的方法是:
I、 GlobalAlloc() 申请内存;
II、 复制 HTML 字符串内容到上述的内存中;
III、 CreateStreamFromHGlobal() 转换内存为 IStream 指针;
原理性代码如下:
// 显示一个空白网页 m_ie.Navigate2( &CComVariant(_T("about:blank")),NULL,NULL,NULL,NULL); // 得到 IHTMLDocument2 指针 CComPtr< IDispatch > spDoc(m_ie.GetDocument()); // 得到 IPersistStreamInit 指针 CComQIPtr< IPersistStreamInit, &IID_IPersistStreamInit > spPSI( spDoc ); // 申请内存,复制 HTML 字符串 LPTSTR lpMem = (LPTSTR)::GlobalAlloc( GPTR, ::lstrlen( lpHtml )+1 ); lstrcpy( lpMem, "xxx xxx" ); // 转换内存为流对象指针 CComPtr< IStream > spStream; CreateStreamOnHGlobal( lpMem, TRUE, &spStream ); // 初始化后,装载显示 spPSI->InitNew(); spPSI->Load( spStream ); |
图一、IE控件显示内存中的 HTML 文件
|
IE 所能支持的数据传输协议,除了大家所熟悉的 http、ftp、file......还有一个协议是 res ,它表示浏览显示文件中的 HTML 资源。你可以在 IE 的地址栏上直接输入这样格式的 URL:"res://文件名/资源名"。
把 HTML 文件加入到程序资源的方法比较简单,在资源卡片中,鼠标右键弹出菜单,执行 Import...(引入),选择指定的 HTML 文件,然后给一个资源名称即可。(在这里,最方便的资源名称用字符串比较好,如果使用整数ID,那么将来在使用的时候是这样的格式:res://文件名/#101,这里假设 101 是资源的ID号。真麻烦!我不太喜欢这样的方式。)对于图片文件等其它的附件,则需要手工编辑资源 RC 文件(用 IDE 环境引入,它会试图用文本方式打开一个2进制文件,多数情况下会“死机”)。下图是事例程序引入资源后的样式:
图三、HTML 资源的引入 |
手工编辑 RC 文件的部分是:
...... ///////////////////////////////////////////////////////////////////////////// // // HTML // HTML_TOWORD HTML DISCARDABLE "res\\ToWord.htm" // 这两个是HTML文件,可以引入 |
二、屏蔽 IE 控件的上下文菜单
屏蔽或自定义 IE 控件的上下文菜单,其实就是需要实现 IDocHostUIHandler 接口中的 ShowContextMenu 方法。如果使用 ATL 编写程序,我认为实现是比较简单的(也许是我使用 ATL 写 COM 比 MFC 熟悉一些的因素吧)。事例程序由于用 MFC 书写,真是搞的我头晕眼花,翻箱倒柜终于找到了微软书写的演示代码,于是我就直接复制过来使用了。(换句话说,读者在阅读这部分代码的时候,如果有问题可不要问我。你直接打电话去咨询Microsoft 哈。)
三、扩展 HTML 脚本中的 external 对象
从 CCmdTarget 派生一个自动化对象(新建C++类的时候,注意别忘了选择 Automation)。在这个类里,你可以使用 ClassWizard 的 Automation 卡片,添加自定义的方法和属性。而在 HTML 的脚本程序中,就可以使用 window.external 进行调用了。用这个方法,实现了对 HTML 脚本功能的扩充。在 HTML 脚本和自动化对象之间要建立起关系,则需要实现 IDocHostUIHandler::GetExternal() 方法。
四、显示 HTML 样式的对话窗
这节内容是本文的重点。
用户的界面设计经历了若干个发展阶段。最早的程序设计,可以说没有用户界面;然后发展出一些简单的与用户交互的界面(控制台界面,全屏文本界面);再然后发展出了图形界面。其实我们现在的商业程序设计中,界面的处理代码占用了很大的篇幅。为了使界面的处理变得简单、通用、易修改维护,人们制作了很多的界面程序库。说实在话,大多数的界面程序库由于封装的不好,一是不灵活,二是经常需要修改它内部的 BUG,重用的效果并不理想。通用的换肤软件也只能实现对标准的窗口类进行皮肤美化,对自定义的窗口类还是需要自己写钩子。
现在,我们已经有一个非常好的方法进行界面设计了,那就是使用 HTML(使用 Visual Studio.net 的程序员,一定对 .net 的界面很喜欢吧?!.net 开发环境,无处不在使用 HTML 方式的界面)。即使是一个完全地道的本地软件(非B/S软件),也可以使用本地 ASP 方式,HTA 方式进行程序设计。软件用户非常喜欢这样的程序,因为他早就熟悉并掌握了浏览器的操作,另外,对于程序员来说,也非常喜欢这种方式,因为不会再为换肤,不同用户不同的界面特化而伤脑筋了。
微软将要在下一代的程序设计中使用 XML 来描述用户界面。这种设计方式将会解放你、我这样的程序员,把咱们的工作量全部都转化到美工师那里去了:) 借 vckbase 的平台,现在呼吁大家,尽快学习和掌握 HTML、XML 的设计和脚本编程,并能熟练地对它们与 C++ 对象的交互进行编程。可以预计在未来的两三年内,拥有这样水平的程序员,一定会开始吃香饽饽了,嘿嘿......
下面,就如何显示一个 HTML 对话窗,开始我们未来软件方式的编程吧。
我们要调用 MSHTML.DLL 中的一个函数 ShowHTMLDialog(Ex) 来完成 HTML 对话窗的显示和数据交互。这个函数的声明是:
HRESULT ShowHTMLDialogEx( HWND hwndParent, IMoniker *pMk, DWORD dwDialogFlags, VARIANT *pvarArgIn, WCHAR *pchOptions, VARIANT *pvarArgOut ); |
hwndParent 对话窗的父窗口句柄 这个太简单了,不多罗嗦。
pMk URL的命名接口指针 表示在对话窗中显示哪个URL的页面。但它不是以简单的URL字符串方式提供的。它使用了moniker(命名)接口指针。 根据URL得到IMoniker *很简单,调用CreateURLMoniker()。唯一要注意的是,这个函数需要连接 Urlmon.lib 库。
dwDialogFlags 对话窗类型 可以组合 HTMLDLG_NOUI、HTMLDLG_MODAL、HTMLDLG_MODELESS、HTMLDLG_PRINT_TEMPLATE、HTMLDLG_VERIFY。
示例程序使用的是模式对话窗。HTMLDLG_NOUI 在下一节中介绍。
pvarArgIn 对话窗的输入参数 一个传入对话窗的VARIANT变量,对话窗脚本中使用 window.dialogArguments 可以取得。
pchOptions 对话窗样式 用字符串表示的对话窗样式。参考 IHTMLWindow2::showModalDialog()函数。
比如:"dialogHeight:100px dialogWidth:200px"表示200点宽,100点高。如果你不想在程序中指定,也可以在HTML中<html style=....>描述。
pvarArgOut 对话窗输出参数 对话窗的VARIANT返回值,对话窗脚本中使用 window.returnValue 可以赋值。
这个函数在 vc.net 的头文件上有完整的声明,如果你使用 vc 6.0 的话,那么函数声明、函数指针定义和一些常量,你需要手工添加。还好,本文的示例程序是在 VC6 下编写和调试的,下载代码后,请仔细阅读源文件和注释就可以了。
五、执行 HTML 脚本
关于调用脚本的方法,我在 vckbase 发表了好几篇文章(鬼知道我为什么对脚本这么有兴趣)。ShowHTMLDialogEx()函数中,如果类型参数给出 HTMLDLG_NOUI,则表示并不真正显示一个对话窗,而是加载指定的 HTML 并执行其中的脚本。示例程序的该脚本中,执行一连串的动作,完成了把上一个 HTML 对话窗中用户输入的文本,发送到 MS WORD 中去。以此上下串联起来,演示了本文章中所讨论的所有功能。下面我把脚本和注释给朋友们展现一下:
On Error Resume Next Set wordapp=CreateObject("Word.Application") ''''运行 MS WORD if err<>0 then MsgBox("没有安装 MS WORD") else wordapp.visible = true ''''显示WORD界面 wordapp.Documents.Add "",false, 0 ''''新增一个空文档 wordapp.Selection.TypeText window.dialogArguments ''''键入传递进来的文本 end if window.close '''' 关闭 |
VC编程技巧:IE控件的高级用法的更多相关文章
- 【VC编程技巧】文件☞2.3CArchive的用法
CArchive 对象提供了一个类型安全缓冲机制CArchive 对象提供了一个类型安全缓冲机制.用于将可序列化对象写入CFile 对象或从中读取可序列化对象.通常,CFile 对象表示磁盘文件:但是 ...
- WebBrowser控件的高级定制+mshtml
--> blog:WebBrowser控件的高级定制---以下为三篇重要的参考文献, 第一篇可以禁用了js弹窗和声音 第二篇的引用文献禁用了IE弹窗,但是原文的说明很好 第3篇 ...
- VC中动态添加控件
VC中动态添加控件 动态控件是指在需要时由Create()创建的控件,这与预先在对话框中放置的控件是不同的. 一.创建动态控件: 为了对照,我们先来看一下静态控件的创建. 放置静态控件时必须先建立一个 ...
- VC中添加web控件的方法
在VC中使用WebBrowser控件的两方法 黄森堂(vcmfc)著 ClassWizard方式: 1.创建包装类:View->ClassWizard->Add Class->For ...
- atitit.基于组件的事件为基础的编程模型--服务器端控件(1)---------服务器端控件和标签之间的关系
atitit.基于组件的事件为基础的编程模型--服务器端控件(1)---------服务器端控件和标签之间的关系 1. server控件是要server了解了标签.种类型的server控件: 1 1. ...
- WPF编程,将控件所呈现的内容保存成图像的一种方法。
原文:WPF编程,将控件所呈现的内容保存成图像的一种方法. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/article/detai ...
- WPF编程:textbox控件文本框数据显示最后一行
WPF编程:textbox控件文本框数据显示最后一行 TextBox控件在接收大量数据的时候,滚动条一般在最上方,如何使滚动条随着数据的接收而向下滚动呢?比如有一个TextBox'控件txbRecvD ...
- 在VC中使用WebBrowser控件的两方法
ClassWizard方式: 1.创建包装类:View->ClassWizard->Add Class->Form a Type Library->C:/winnt/syste ...
- MFC编程 | tab control控件的使用
因为课程需要,会用到MFC编程,所以讲一些经验总结下,以便日后使用查询. // tab control控件的使用 // 建立一个Cluster窗口,通过tab可以切换成C-Means和Fuzzy C- ...
随机推荐
- iOS开发基础之排序
Objective-C 有排序的API,省了我们很多事. 主要有以下3种方法. NSComparator NSArray *unsortedArray = @[@5,@3,@8,@1,@7]; NSA ...
- linux 常用软件安装-目录
nginx apache php mysql oracle tomcat memcached mongodb sqlserver
- CMakeLists实战解读--YouCompleteMe
原文转载自:Ricky.K http://www.cnblogs.com/rickyk/p/3877238.html 个人一直有一个想法,就是想出一系列关于CMakeLists.txt国外经典例子的实 ...
- Javascript中最常用的55个经典技巧
Javascript中最常用的55个经典技巧1. oncontextmenu="window.event.returnValue=false" 将彻底屏蔽鼠标右键<table ...
- mac下安装pcntl
Now you need to find out what version of PHP is installed on OSX $ php -vPHP 5.3.10 with Suhosin-Pa ...
- Using jQuery to add a dynamic “Back To Top” floating button with smooth scroll
Ever read a really long blog post or article and then had to scroll all the way up to the top of the ...
- iphone开发第一个UI应用程序QQ
#import <UIKit/UIKit.h> @interface HViewController : UIViewController @property (retain, nonat ...
- Android图像处理1
项目开发要用,在慕课中学习了一下关于Android图像处理的相关功能,并进行了整理. 在Android中,我们通过最基本的改变图像的RGBA值,改变图像的颜色与饱和度. Android中有ColorM ...
- python安装与环境变量配置
默认情况下,在windows下安装python之后,系统并不会自动添加相应的环境变量.此时不能在命令行直接使用python命令. 1. 首先需要在系统中注册python环境变量:假设python的安装 ...
- JVM的组成部分与内存管理
JVM的组成部分与内存管理 JVM区域划分 由于Java程序是交由JVM执行的,所以我们在谈Java内存区域划分的时候事实上是指JVM内存区域划分.在讨论JVM内存区域划分之前,先来看一下Java程序 ...