定制浏览器

2023-11-11

 定制浏览器
http://www.vcmain.com/helloworld/archive/11310.html

helloworld 发表于:2008-9-29 14:52:00   阅读数:8


定制浏览器
作者:冯明德


浏览器控件是个典型的Active控件,提供了大量的接口及自动化对象,可以灵活的加以控制,需要的时候,可以通过这些接口控制浏览器的行为,或提供相应的出接口定制浏览器。

一、概述
浏览器对象CLSID:
CLSID_WebBrowser

提供的主要接口
IWebBrowser2 浏览器的接口

当文档建立后,可以得到相应的文档接口,文档中各标记元素的接口。
在DHTML中,大量的对象和事件就是又这些接口提供和管理的。

IHTMLDocument2
IHTMLWindow2
IHTMLEventObj
IHTMLElement
....

浏览器还将调用宿主提供的接口,以发出事件或给用户提供定制机会。
出接口
DIID_DWebBrowserEvents2
DIID_HTMLDocumentEvents
DIID_HTMLWindowEvents

(ICustomDoc)
IDocHostUIHandler

二、事件的相应
除了使用MFC缺省的事件响应机制外,也可以自建事件接受器,来响应事件
也就是,在封装对象中提供DIID_DWebBrowserEvents2 接口,然后将此接口作为接受器连接到浏览器对象。

一种做法是
在派生类中,使用MFC建立接口方案提供一个DIID_DWebBrowserEvents2接口对象嵌套成员。

class CFMDBrowser : public CWebBrowser
{
	...
	//事件接收器接口
	//DWebBrowserEvents
	//这是一个IDispatch分发接口
	BEGIN_INTERFACE_PART(BrowserEventSink,DWebBrowserEvents)
		STDMETHOD(GetTypeInfoCount)(UINT *pctinfo);	
		STDMETHOD(GetTypeInfo)(UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo);
		STDMETHOD(GetIDsOfNames)(REFIID riid,
				LPOLESTR *rgszNames,UINT cNames,
				LCID lcid,DISPID *rgDispId);
		STDMETHOD(Invoke)(DISPID dispIdMember,REFIID riid,LCID lcid,
				WORD wFlags,DISPPARAMS *pDispParams,
				VARIANT *pVarResult,EXCEPINFO *pExcepInfo,
				UINT  *puArgErr);	
	END_INTERFACE_PART(BrowserEventSink)

	DWORD m_dwEventSinkCookie;
	...
}


这是一个接收器接口,无需添入到对象的接口表中。
(无需:BEGIN_INTERFACE_MAP、END_INTERFACE_MAP)

这是一个以分发接口(IDispatch)作为出接口的典型例子。在接口函数的实现中。Invoke负责又分发ID调用不同的虚拟函数。(事件函数作为虚拟函数,供派生类重载)

STDMETHODIMP CFMDBrowser::XBrowserEventSink::Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,
				  WORD wFlags,DISPPARAMS *pDispParams,
				  VARIANT *pVarResult,EXCEPINFO *pExcepInfo,
				  UINT  *puArgErr)
{
	METHOD_PROLOGUE(CFMDBrowser,BrowserEventSink)
	//将事件分发到各虚拟函数
	//分发ID的定义见 exdispid.h
	switch(dispIdMember)
	{
	case DISPID_BEFORENAVIGATE:
		...
		HRESULT hr=pThis->OnBeforeNavigate(..) //事件对应的虚拟函数
		...
		break;
        case DISPID_NAVIGATECOMPLETE:
        		...
	case ...
	case ...
}


建立与浏览器的连接
得到IConnectionPointContainer接口,查找与DIID_DWebBrowserEvents对应的接收器,建立连接,记录连接的标号(m_dwEventSinkCookie);

BOOL CFMDBrowser::Connect()
{

	IUnknown *p_Unk=GetControlUnknown();
	if(p_Unk==NULL)
		return FALSE;

	BOOL bOK=FALSE;

	//查找连接点对象
	IConnectionPointContainer *i_cpc=0;
	HRESULT hr=p_Unk->QueryInterface(IID_IConnectionPointContainer,
		(void **)(&i_cpc));
	if (SUCCEEDED(hr))
	{
		IConnectionPoint *i_cp=0;
		hr=i_cpc->FindConnectionPoint(DIID_DWebBrowserEvents,&i_cp);
		if (SUCCEEDED(hr))
		{
			hr=i_cp->Advise(&m_xBrowserEventSink,&m_dwEventSinkCookie);
			i_cp->Release();
			bOK=TRUE;
		}
		i_cpc->Release();
	}
	
	return bOK;
}

结束时,断开与浏览器的连接

BOOL CFMDBrowser::DisConnect()
{
	IUnknown *p_Unk=GetControlUnknown();
	if(p_Unk==NULL)
		return FALSE;
	
	BOOL bOK=FALSE;
	
	//查找连接点对象
	IConnectionPointContainer *i_cpc=0;
	HRESULT hr=p_Unk->QueryInterface(IID_IConnectionPointContainer,
		(void **)(&i_cpc));
	if (SUCCEEDED(hr))
	{
		IConnectionPoint *i_cp=0;
		hr=i_cpc->FindConnectionPoint(DIID_DWebBrowserEvents,&i_cp);
		if (SUCCEEDED(hr))
		{
			hr=i_cp->Unadvise(m_dwEventSinkCookie);
			i_cp->Release();
			bOK=TRUE;
		}
		i_cpc->Release();
	}
	
	return bOK;
}

三、定制浏览器UI
浏览器提供了IDocHostUIHandler出接口,向用户查询界面特性
可以提供这个接口,与浏览器连接上,在其实现中,定制界面

1.建立接口

class CFMDBrowser : public CWebBrowser
{
	...
	//IDocHostUIHandler接口,控制浏览器界面
	BEGIN_INTERFACE_PART(UIHandlerSink,IDocHostUIHandler)
		STDMETHOD(ShowContextMenu)(DWORD,POINT*,IUnknown*,IDispatch*);
		STDMETHOD(GetHostInfo)(DOCHOSTUIINFO*);
		STDMETHOD(ShowUI)(DWORD,
			IOleInPlaceActiveObject*,
			IOleCommandTarget*,
			IOleInPlaceFrame*,
			IOleInPlaceUIWindow*);
		STDMETHOD(HideUI)();
		STDMETHOD(UpdateUI)();
		STDMETHOD(EnableModeless)(INT);
		STDMETHOD(OnDocWindowActivate)(INT);
		STDMETHOD(OnFrameWindowActivate)(INT);
		STDMETHOD(ResizeBorder)(LPCRECT,IOleInPlaceUIWindow*,INT);
		STDMETHOD(TranslateAccelerator)(LPMSG,const GUID*,DWORD);
		STDMETHOD(GetOptionKeyPath)(LPOLESTR*,DWORD);
		STDMETHOD(GetDropTarget)(IDropTarget*,IDropTarget**);
		STDMETHOD(GetExternal)(IDispatch**);
		STDMETHOD(TranslateUrl)(DWORD,OLECHAR*,OLECHAR**);
		STDMETHOD(FilterDataObject)(IDataObject*,IDataObject**);
	END_INTERFACE_PART(UIHandlerSink)
	...
}

无需添加接口映射

2.连接到浏览器
需要在NavigateComplete时间发生后,得到
ICustomDoc接口,由此接口的
SetUIHandler成员设置UI接口。

//设置界面接口
IDispatch *i_dispatch=0;
if (SUCCEEDED(i_dispatch=pThis->GetDocument()))
{
	IHTMLDocument2 *i_htmldoc2=0;
	if (SUCCEEDED(i_dispatch->QueryInterface(IID_IHTMLDocument2,
			(void **)(&i_htmldoc2))))
	{
			// force connection of IDocHostUIHandler

			ICustomDoc *i_customdoc=0;
			if (SUCCEEDED(i_htmldoc2->QueryInterface(
						IID_ICustomDoc,
						(void **)(&i_customdoc))))
			{
				i_customdoc->SetUIHandler(
					&(pThis->m_xUIHandlerSink));
				i_customdoc->Release();
			}

	}
	i_dispatch->Release();
}

3.在接口的实现中,控制用户界面
例如更改右键菜单
在STDMETHOD(ShowContextMenu)(DWORD,POINT*,IUnknown*,IDispatch*);
的实现中:

HRESULT CFMDBrowser::ShowContextMenu(DWORD,POINT*,IUnknown*,IDispatch*)
{
	..建立自己的菜单
        return S_OK;         
}

http://www.xici.net/b66783/d14811541.htm
http://www.xici.net/b66783/d14811541.htm
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

定制浏览器 的相关文章

  • 如何调整 CWnd 内 WPF 控件的大小?

    我正在托管 WPFUserControlMFC 内部CWnd 它工作得很好 我现在需要弄清楚如何与其父控件一起调整控件的大小 我已经迷上了OnSize我正在打电话GetWindowRect并将结果设置为我的控件 如下所示 void CChi
  • 如何停止对辅助隐式加载 DLL 的 DLL 劫持

    例如 COMDLG32 DLL 隐式链接到以下系统 DLL 以及其他 xmllite dll dll srvcli dll wkscli dll 链接信息库 netutils dll 微星 dll 由于这些是由操作系统隐式加载的 而不是使用
  • 想要将 ColeDateTime 转换为 CTime

    我正在从数据库中读取日期时间ColeDateTime格式 我想将其转换为CTime获取日期 月份 年份和时间 CString repDt this will hold the datetime which i read from Datab
  • 带有 std::variant 或 union 包装器的通用接口

    这个问题与使用 std variant 强制使用通用接口 无需继承 https stackoverflow com questions 72434897 enforcing a common interface with stdvarian
  • Moq-ing 类或接口有什么区别?

    我一直在使用moq http code google com p moq 在我的单元测试中模拟对象 我在关于最小起订量的网站上看到它能够模拟类和接口 有一天 我与我的一位同事进行了讨论 他们表示没有理由模拟类 我应该只模拟接口 我对此并没有
  • MinGW支持MFC吗?

    我已经使用 MinGW 开发了 WinAPI 应用程序 没有出现任何问题 现在 我可以用 MFC 做同样的事情吗 我只是在这里猜测 但我认为您需要购买 Visual Studio 的副本才能获得使用 MFC 的许可证 MFC 也不因其对 C
  • 安卓中的界面

    我在 android 中编写了一个包含图像和视频视图的表格布局 我想在 android 中编写一个界面 它将在不干扰我的布局的情况下获取图像以及数据和视频 该数据可以采用任何形式 来自任何来源 并且必须通过接口提供给布局 我应该如何为我在a
  • 如何将接口类型传递给过程

    如何将接口类型传递给过程参数 type Hello PortType interface ISoapInvokable 243CBD89 8766 F19D 38DF 427D7A02EAEE function GetDeneme s st
  • CUDD C++ 接口,用于将布尔值转换为 BDD 以及生成的最小项集(到割集)

    我正在与 https github com ivmai cudd https github com ivmai cudd 目标是进行以下重复过程 1 输入 连贯 非递减 布尔函数表达式 顶部 a 1a 2a 3 x 1x 2x 3 z 1z
  • 在运行时选择模板参数时如何避免代码呈指数级增长

    考虑一堆基本类型 Foo 所有这些都具有通用方法的独特实现 Bar 我可以结合Foo1 Foo2 Foo5像这样 CombinedFoo
  • 数据源和数据集的区别

    我目前正在开发一个项目 其主要任务是读取存储在 SQL 数据库中的数据并以用户友好的形式显示它们 使用的编程语言是C 我在 Borland C Builder 6 环境中工作 但我认为标题中提出的问题与编程语言或库无关 当从数据库读取数据时
  • 在 C# 中将“set”添加到接口的属性中

    我希望通过为该接口中的属性提供设置访问器来 扩展 该接口 界面看起来像这样 interface IUser string UserName get 我想要这样的东西 interface IMutableUser IUser string U
  • 错误 C2248: 'CObject::CObject' : 无法访问类 'CObject' afxwin.h 中声明的私有成员

    我试图让班级负责在灰色背景上放置一些文本 Score h pragma once class Score public Score Score void UpdateScore int points void UpdateLives int
  • 如何通过MFC将应用程序设置保存到注册表中?

    我有一个由 MFC 项目向导创建的 MFC 应用程序 我想在注册表中保存 读取应用程序设置 所以问了这个question https stackoverflow com questions 1880275 good c registry w
  • 如何在UITextField上自动打开键盘?

    我有一个非常简单的表格 当触摸单元格时 它会打开一个带有一个 UITextfield 的新视图 我想要的只是键盘会自动打开 而用户无需触摸 UITextfield 这一切都是在 Interface Builder 中完成的 所以我不确定如何
  • Pylance:“property”与“int”不兼容

    from typing extensions import Protocol class IFoo Protocol value int class Foo IFoo property def value self gt int retur
  • 具有键唯一性和按位置排序的 MFC 字典集合

    看着表上http msdn microsoft com en us library y1z022s1 28v vs 80 29 aspx core collection shape features http msdn microsoft
  • 结构体实现接口安全吗?

    我似乎记得读过一些关于在 CLR 中通过 C 实现结构如何不好的内容 但我似乎找不到任何相关内容 是不是很糟糕 这样做会产生意想不到的后果吗 public interface Foo Bar GetBar public struct Fub
  • 为什么这个实现方法看不到它的同级方法? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我有一个实现接口的类 public class SQLiteHHSDBUtils IHHSDBUtils void IHHSDBUtils
  • 您将整个应用程序中使用的常量保存在哪里?

    界面是存储我的信息的可接受的地方吗 public static final Foo bar 您是否推断它们可以从程序外部读取 你给它编了一个超级课吗 当情况出现时 你会怎么做 我会将每个常量放入与其最密切相关的类或接口中 例如 因为它将被其

随机推荐

  • 数仓知识点

    传统数仓知识 1 数据仓库分层 ODS 数据准备层 该区为数据仓的准备区 直接输入源数据 如业务库 埋点日志和消息队列等 DWD 数据细节层 该层为业务层和数据层的隔离层 保持和ODS层相同的颗粒度 该层还进行了数据清洗和规范化操作 例如去
  • 阿里巴巴笔试-2020.7.27-第二题 藏宝架

    题目 有个藏宝架有n层 每层的宝物数量不一 每个宝物都有其价值 现在要求拿出m个宝物 并且需要遵守规则 每次只能拿选定层的两端的宝物 要拿出的m个宝物的总价值是各种方案里最大的 输入 第一行是 n 和 m 后面每一行是各层的数据 n m 下
  • WebSocket 基于JAVA Spring boot Spring Colud 的使用

    先上代码再看调试结果 package com qiang user util import com alibaba fastjson JSONObject import org springframework stereotype Comp
  • 软考网络工程师-最新最全小白攻略

    一 前言 最近Beau 博主本人 也是考取了2023年上半年的软考网络工程师 这里也准备给小白们做一些避坑流程 这里附上通过图 二 考前准备 1 报考条件 无 无年龄 资质 学历限制 无需通过软考初级才能报考 是中国守法公民即可报名 2 考
  • webpack 保存文件后自动打包_自动打包插件webpack-dev-server的安装、配置及使用

    1 介绍 webpack dev server插件可以实现Webpack的自动打包编译 这样 就不需要每次修改完代码都重新手动输入webpack打包了 2 安装 在项目的根路径下输入 cnpm i webpack dev server D
  • Python----模块(Module)和包(Package)

    Python 包 包 定义 为了组织好模块 会将多个模块分为包 Python 处理包也是相当方便的 简单来说 包就是文件夹 但该文件夹下必须存在 init py 文件 常见的包结构如下 最简单的情况下 只需要一个空的 init py 文件即
  • uniapp中使用网页录音并上传声音文件(发语音)——js-audio-recorder的使用【伸手党福利】

    uniapp中上传音频只能在app或小程序当中实现 如何使用网页完成语音的录制和上传则成为了困扰前端童鞋的重点 本文着重解决 js audio recorder报 error 浏览器不支持getUserMedia 的问题 js audio
  • qt使用socket连续发图片,服务端使用qt或者python接受图片

    首先客户端是用qt 不能用python这种 首先在pro里面 QT network 然后引入头文件 include
  • 2023最新AI创作商用ChatGPT源码分享+支持AI绘画

    一 SparkAI智能创作系统 SparkAi创作系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统 本期针对源码系统整体测试下来非常完美 可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统 那么如何搭建部
  • Vue 中使用 Upload 组件上传 Excel

    vue 中使用 Element 的 upload 组件上传 Excel 大致可以分两种情况 使用 action 上传到服务器 使用 axios 上传到服务器 注意 上传文件可能由于前后端格式不统一导致上传失败 application x w
  • openTLD算法在opencv3的PatchGenerator

    由于opencv3的各种版本相对于opencv2的版本已经改变了很多内容 openTLD跟踪算法所依赖的一些函数在opencv3中已经消失了 为此需要对openTLD进行适当修改才能使之在opencv3的各种版本中运行 加入如下文件 并在对
  • C++一本通基础算法:深度优先搜索(DFS)

    算法概述 搜索 类似于枚举 从头结点开始 搜索发现有一些路可以走 先选择一条 走到一个结点处 重复上述过程 一直走到不能走为止 然后返回上一个结点 选择第二条路 一直检索知道将头结点所有的路走完 算法图像 如图所示 从1开始 发现可以到达2
  • 06:TIM定时器功能------编码器接口功能

    目录 1 简历 2 正交编码器 3 编码器接口基本结构 4 编码器的工作模式 5 极性反转 A 编码器接口测速 1 连接图 2 函数介绍 3 步骤 4 代码 B 编码器接口计次 1 连接图 2 代码 1 简历 Encoder Interfa
  • 2020-12-03 PMP 群内练习题 - 光环

    1 完工估算 EAC 是下面哪一项的定期评估 A 已完成工作的成本 B 已完成工作的价值 C 预测项目完成时的总成本 D 预测完成项目还将需要的成本 如果挣值 EV 350 实际成本 AC 400 计划值 PV 300 那么成本偏差 CV
  • 怎么更改wifi频段_【wifi信号频率】wifi频率怎么设置 wifi2.4g和5g哪个更好

    wifi频率怎么设置 1 打开浏览器 输入192 168 1 1 进入路由设置界面 2 单击左侧的设置向导 然后单击下一步 3 一般情况 选择让路由器自动选择上网方式 4 输入你从运营商那里获得上网账号 密码 5 弹出无线频段选择界面 可按
  • __declspec用法详解

    dllimport dllexport 格式 declspec dllimport declarator declspec dllexport declarator 分别用来从dll导入函数 数据 或对象以及从dll中导出函数 数据 或对象
  • 中文分词之HMM模型详解

    关于HMM模型的介绍 网上的资料已经烂大街 但是大部分都是在背书背公式 本文在此针对HMM模型在中文分词中的应用 讲讲实现原理 尽可能的撇开公式 撇开推导 结合实际开源代码作为例子 争取做到雅俗共赏 童叟无欺 没有公式 就没有伤害 模型介绍
  • android:layout_height,玩转ConstraintLayout之大小设置模式

    ConstraintLayout有三种大小设置模式 spread 默认 拉伸 wrap 自适应 percent 百分比 可通过app layout constraintWidth default app layout constraintH
  • kali安装中文输入法

    kali系统安装中文输入法 配置阿里云的数据源 vim etc apt sources list 文件中加入 i键进入插入状态 ESC退出插入状态 进入命令状态 wq保存退出 deb http mirrors aliyun com kali
  • 定制浏览器

    定制浏览器 http www vcmain com helloworld archive 11310 html helloworld 发表于 2008 9 29 14 52 00 阅读数 8 定制浏览器 作者 冯明德 浏览器控件是个典型的A