MFC IE控件修改网页链接打开方式

C++编写网页游戏辅助工具~~~~~~~ 有人肯定会问,简单游,按键精灵,C#等,这么轻松就能写辅助,为什么还用C++? 别人写的辅助也都用过不少,简单功能模拟按键确实能做到,但是存在非常多的问题,软件缓存大,开2个号就非常卡。等等。 而且,这还是一个态度问题,现在网上真正优秀的贴子不多了,大部分都是菜鸟在问一些所谓的作业题,而回答问题的都不过是从别的帖子上复制,粘贴过来的!知识就像是孩子,不是你亲生的,总是会有遗憾!别人是无法代替你 阅读详情

很多应用程序内嵌IE来加载网页,使用MFC的CWebBrowser2自动生成的控件,自动生成的IE控件的代码基本不可读,函数调用都是这种:

void GoBack()
	{
		InvokeHelper(0x64, DISPATCH_METHOD, VT_EMPTY, NULL, NULL);
	}
	void GoForward()
	{
		InvokeHelper(0x65, DISPATCH_METHOD, VT_EMPTY, NULL, NULL);
	}
	void GoHome()
	{
		InvokeHelper(0x66, DISPATCH_METHOD, VT_EMPTY, NULL, NULL);
	}
	void GoSearch()
	{
		InvokeHelper(0x67, DISPATCH_METHOD, VT_EMPTY, NULL, NULL);
	}
	void Navigate(LPCTSTR URL, VARIANT * Flags, VARIANT * TargetFrameName, VARIANT * PostData, VARIANT * Headers)
	{
		static BYTE parms[] = VTS_BSTR VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT ;
		InvokeHelper(0x68, DISPATCH_METHOD, VT_EMPTY, NULL, parms, URL, Flags, TargetFrameName, PostData, Headers);
	}

当需要修改事件方式时,看MSDN上,有一套极其恶心的API,通过queryInterface来获取IDispatch对象,然后修改事件:

class MyWebEventDispatcher : public DWebBrowserEvents2 {
public:
	DWORD dwCookie;
	STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject)
	{
		HRESULT hr = E_NOINTERFACE;
		if (riid == __uuidof(IDispatch))
		{
			*ppvObject = (IDispatch*)this;
			AddRef();
			hr = S_OK;
		}
		else if (riid == __uuidof(DWebBrowserEvents2))
		{
			*ppvObject = (DWebBrowserEvents2*)this;
			AddRef();
			hr = S_OK;
		}

		return hr;
	}

	STDMETHODIMP_(ULONG) AddRef(void)
	{
		return 1;
	}

	STDMETHODIMP_(ULONG) Release(void)
	{
		return 1;
	}

	STDMETHOD(GetTypeInfoCount)(UINT*)
	{
		return E_NOTIMPL;
	}

	STDMETHOD(GetTypeInfo)(UINT, LCID, ITypeInfo**)
	{
		return E_NOTIMPL;
	}

	STDMETHOD(GetIDsOfNames)(REFIID, LPOLESTR *rgszNames, UINT, LCID, DISPID *rgDispId)
	{
		return E_NOTIMPL;
	}
	STDMETHODIMP Invoke(DISPID dispidMember,
		REFIID riid, LCID lcid,
		WORD wFlags,
		DISPPARAMS* dispParams,
		VARIANT* pvarResult,
		EXCEPINFO* pExcepInfo,
		UINT* puArgErr)
	{
		CComBSTR url;
		switch (dispidMember) {
		case DISPID_BEFORENAVIGATE2:
			url = ((*dispParams).rgvarg)[5].pvarVal->bstrVal;
			//MessageBox(NULL, L"打开窗口", NULL, NULL);
			if (url == "http://www.adatum.com")
			{
				// If so, navigate the browser frame to standard resource page 
				CComQIPtr<IWebBrowser2> spBrowser = ((*dispParams).rgvarg)[6].pdispVal;
				if (spBrowser != NULL)
				{
					static const CComBSTR newURL = L"res://ieframe.dll/navcancl.htm";
					spBrowser->Navigate(newURL, NULL, NULL, NULL, NULL);
					// Set Cancel parameter to TRUE to cancel the current event
					*(((*dispParams).rgvarg)[0].pboolVal) = TRUE;
				}
			}
			return S_OK;

		case DISPID_NAVIGATECOMPLETE2:
			return S_OK;
		}
		return S_FALSE;
	}

	STDMETHODIMP Advise(IUnknown* pUnkCP, const IID& iid)
	{
		if (pUnkCP == NULL) {
			return E_INVALIDARG;
		}

		IConnectionPointContainer* pCPC = NULL;
		HRESULT hr = pUnkCP->QueryInterface(IID_IConnectionPointContainer, reinterpret_cast<void**>(&pCPC));
		if (SUCCEEDED(hr)) {
			IConnectionPoint* pCP = NULL;
			hr = pCPC->FindConnectionPoint(iid, &pCP);
			if (SUCCEEDED(hr)) {
				hr = pCP->Advise(this, &dwCookie);
				pCP->Release();
			}
			pCPC->Release();
		}
		return hr;
	}

	/**
	* Register DWebBrowserEvents2 to IWebBrowser2.
	*/
	STDMETHODIMP Advise(HWND hwnd, IWebBrowser2* pIE)
	{
		HRESULT hr = Advise(pIE, __uuidof(DWebBrowserEvents2));
		return hr;
	}

	HRESULT connectToBrowser(IWebBrowser2* pIE) {
		HRESULT hr;
		CComPtr<IConnectionPoint> spCP;

		IConnectionPointContainer* pCPC = NULL;
		pIE->QueryInterface(IID_IConnectionPointContainer, reinterpret_cast<void**>(&pCPC));
		// Receives the connection point for WebBrowser events
		hr = pCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);
		if (FAILED(hr))
			return hr;

		// Pass our event handlers to the container. Each time an event occurs
		// the container will invoke the functions of the IDispatch interface
		// we implemented.
		hr = spCP->Advise(reinterpret_cast<IDispatch*>(this), &dwCookie);

		return hr;
	}
};

其实通常不用这么麻烦,右键到IE控件上,选择“添加事件处理程序”,然后可以选择事件。


就会自动注册事件到选定的窗口,完全不用手动去修改那一堆恶心的代码:

BEGIN_EVENTSINK_MAP(CMyIETestDlg, CDialog)
	ON_EVENT(CMyIETestDlg, IDC_EXPLORER1, 250, CMyIETestDlg::MyBeforeNavigate2Explorer, VTS_DISPATCH VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PBOOL)
	ON_EVENT(CMyIETestDlg, IDC_EXPLORER1, 273, CMyIETestDlg::NewWindow3Explorer1, VTS_PDISPATCH VTS_PBOOL VTS_UI4 VTS_BSTR VTS_BSTR)
END_EVENTSINK_MAP()


void CMyIETestDlg::MyBeforeNavigate2Explorer(LPDISPATCH pDisp, VARIANT* URL, VARIANT* Flags, VARIANT* TargetFrameName, VARIANT* PostData, VARIANT* Headers, BOOL* Cancel)
{
	// TODO: 在此处添加消息处理程序代码
	CString str = URL->bstrVal;
	//TRACE(str);
	//MessageBox(NULL, L"asdasd", NULL, NULL);
	if (str != L"http://localhost:8000/test.html") {
		*Cancel = true;
		ShellExecute(0, L"open", str, NULL, NULL, SW_SHOWNORMAL);
	}

}

void CMyIETestDlg::NewWindow3Explorer1(LPDISPATCH* ppDisp, BOOL* Cancel, unsigned long dwFlags, LPCTSTR bstrUrlContext, LPCTSTR bstrUrl)
{
	// TODO: 在此处添加消息处理程序代码
	CString url = bstrUrl;
	ShellExecute(0, L"open", url, NULL, NULL, SW_SHOWNORMAL);
	*Cancel = TRUE;
}
IE控件加载的网页中的链接默认用IE打开,现在我需要修改为使用用户的默认浏览器打开,读了MSDN发现需要去截获BeforeNavigate2 事件,比起用QueryInterface重载IDispach:Invoke这种恶心写法,直接无脑右键添加事件方便的多。但是发现BeforeNavigate2在新窗口打开的时候并没有被调用,只是第一次Navgate2加载链接的时候被调用了。对于新窗口打开链接需要截获NewWindow3事件,获取用户点击的链接,用ShellExecute来打开链接。

NewWindow3:读MSDN,发现窗口打开方式为_blank和windows.open时,是打开新窗口会触发这个事件。

或者用兼容性更好的NewWindow2事件:

void CMyIETestDlg::NewWindow2Explorer1(LPDISPATCH* ppDisp, BOOL* Cancel)
{
	*Cancel = TRUE;
	HRESULT hr;
	IDispatch *pDisp = CWebBrowser2.get_Document();
	IHTMLDocument2 *pHTMLDocument2 = NULL;

	if (pDisp)
	{
		hr = pDisp->QueryInterface(IID_IHTMLDocument2, (void**)&pHTMLDocument2);
		if (!SUCCEEDED(hr))
		{
			return;
		}
	}

	if (pHTMLDocument2 != NULL)
	{
		CComPtr<IHTMLElement> pIHTMLElement;
		pHTMLDocument2->get_activeElement(&pIHTMLElement);

		if (pIHTMLElement != NULL)
		{
			variant_t url;
			hr = pIHTMLElement->getAttribute(L"href", 0, &url);
			if (SUCCEEDED(hr))
			{
				CString strURL(V_BSTR(&url));
				//打开默认浏览器
				ShellExecute(m_hWndOwner, NULL, strURL, NULL, NULL, SW_NORMAL);
			}
		}
	}
}


从零到一:在Visual Studio中构建并调试MFC ActiveX控件 本文详细介绍了在Visual Studio中从零开始构建并调试MFC ActiveX控件的完整流程,包括环境准备、项目创建、编译注册、界面设计、核心功能实现及网页集成等关键步骤。针对开发过程中常见的OCX注册失败、界面闪烁等问题提供了实用解决方案,帮助开发者高效完成ActiveX控件开发与部署。 阅读详情

相关推荐

MFC集成WebBrowser控件实战:从基础创建到C++/JS双向通信

在Windows桌面开发中,将Web内容嵌入原生应用是常见的需求,这通常通过浏览器控件实现。其核心原理是利用操作系统提供的浏览器渲染引擎,在应用窗口中创建一个可交互的网页容器。这项技术的价值在于能够融合Web的动态内容、丰富交互与原生应用的系统级能力,实现混合应用开发。典型的应用场景包括内嵌报表展示、在线文档查看、地图集成以及需要Web界面但又要调用本地功能的客户端程序。本文聚焦于MFC框架,深入探讨了如何集成经典的WebBrowser控件,涵盖了CHtmlView与手动创建两种方案,并详细解析了C++与J

weixin_33672400的博客 409

VC/MFC Q&A 200409

laiyiling收集整理,以后如果有时间会进行分类整理些资料,便于阅读查找。问】如何判定剪贴板中有没有文本数据? 答】COleDataObject dataObject;dataObject.AttachClipboard();if(dataObject.IsDataAvailable(CF_TEXT)){    .....//有文本数据}问】如何得到ComboBox的Edit句柄?答】CE

C++、.NET、WPF、Android 4839

构建基于MFC的IE浏览器实例教程

MFC(Microsoft Foundation Classes)是微软公司为了开发Windows应用程序而推出的一套C++类库,它封装了大部分的Windows API,并提供了大量的面向对象的接口。自1992年首次发布以来,MFC一直作为微软官方推荐的快速应用开发工具之一,为许多Windows桌面应用程序提供了坚实的基础。MFC不仅简化了Windows编程的复杂性,还增强了代码的可维护性和扩展性。

weixin_33481022的博客 713

利用DIID_DWebBrowserEvents2接口接收WebBrowser事件

接收事件的途径依靠开发工具你创建客户应用程序,你可以接收事件通过不同的途径. 显然, 在Vb中接收事件同在VC中接收事件相比是如此不同和容易.在 C++ 应用中,你可以用不同的技术,通过使用 ATL, MFC, 或者标准C++.Visual Basic 中接收事件 Visual Basic是创建大多数类型应用的最轻松的工具, 所以我告诉你VB是处理事件最溶的工具时也不要惊奇. ATL 和 Vi

清风专栏 1万+

MFC浏览器(最终版)

MFC浏览器,能实现一般上网所需全部功能,精力有限,不再改进了

(10)Proteus 8.9上的STM32仿真系列(HAL)---freertos

实验设计:通过cubemxide生成freertos工程,然后创建一个 pc13 led灯间隔200ms闪烁的任务。非常遗憾的是proteus8.9仿真失败,实物上没有问题,但还是把流程过一遍。 一、原理图 实物是淘宝上stm32f103 c8t6的核心板,proteus上没有这个芯片,这里图上大概表示一下,用的是核心板自带的pc13引脚的led灯。 二、cubemxide配置 1.RCC如之前工程一样配置 2、配置SYS timebase Source不要使用systick,自己选择一个定时器,我这

qq_35442550的博客 7342

浏览器的定制与扩展

下载源代码 本文分如下章节: 前言 在MFC中使用浏览器 怎样扩展或定制浏览器 定制鼠标右键弹出出菜单 实现脚本扩展(很重要的external接口) C++代码中如何调用网页脚本中的函数 定制消息框的标题 怎样定制、修改浏览器向Web服务器发送的HTTP请求头 怎样修改浏览器标识 去掉讨厌的异常警告 怎样处理浏览器内的拖放 怎样禁止网页元素的选取...

weixin_34166847的博客 290

水气泵控制原理,三角波发生电路,LM331M/TR芯片,高速运放芯片

气泵的控制采用闭环控制,根据气泵的FG反馈信号进行反馈调节,由于气泵的反馈信号是脉冲反馈,即频率改变,占空比不变,即需要通过F/V转换芯片转换成电压信号,变为电压与转速成正比,其电压进入比较器与基准电压进行比较,将比较结果进行运算并进行PWM控制信号。水泵的控制采用闭环控制,根据水泵的pwm信号进行反馈调节,水泵的反馈信号是脉冲反馈,即频率改变,占空比不变,即需要通过F/V转换芯片转换成电压信号,变为电压与转速成反比,其电压进入比较器与基准电压进行比较,将比较结果进行运算并对PWM控制信号。

m0_51010122的博客 2856

vc 利用IEHelper实现简单网址过滤

本文转于vc知识库 http://www.vckbase.com/document/viewdoc/?id=614Microsoft为"我的电脑",IE流浏览器都设置了接口,只要你注册一个自己定义的COM DLL库,windows 在IE启动的时候都会调用这个DLL,(相当于挂钩了),所以你在你的DLL文件中对输入的网址进行处理了! 下载一个IEhelper,IE浏览网页的时候有几个事件要发生

河边杨柳 960

从菜鸟到高手:我的Abaqus壳单元S4R、S3R、S8R选择心路历程

第一次打开Abaqus的单元库时,我被琳琅满目的壳单元类型晃花了眼。S4R、S3R、S8R、STRI65、S9R5...这些看似随意的字母数字组合,背后却隐藏着影响仿真精度的关键密码。作为一名从土木工程转行到汽车结构仿真的工程师,我花了三年时间才真正理解如何根据问题特性精准选择壳单元。这段学习历程充满试错与顿悟,今天就用几个关键案例,分享我的壳单元选择方法论。

weixin_42525637的博客 418

告别Failed to start错误!保姆级教程:用Ubuntu20.04安装盘搞定GRUB与系统服务修复

本文提供Ubuntu20.04系统启动失败的专业修复指南,详细讲解如何利用安装盘解决GRUB与系统服务问题,避免重装系统导致的数据丢失。涵盖分区挂载、chroot环境操作、服务诊断与修复等实用技巧,帮助用户高效恢复系统正常运行。

weixin_32578161的博客 331

onbeforenavigate2 打开一个html文件,使用WPF浏览器控件时,如何使用BeforeNavigate2?...

是。 WPF的WebBrowser控件真的是脑死亡。最重要的是它甚至是密封的。您必须使用Windows.Forms的WebBrowser控件并将其嵌入WindowsFormsHost中。另外,你必须从WebBrowser派生一个类并在其中做一些COM魔术。像这样制作一个UserControl:xmlns="http://schemas.microsoft.com/winfx/2006/xaml/p...

weixin_35989968的博客 247

【车载以太网】【SOMEIP】Wireshark测试someip

一、 Wireshark SOMEIP plugin 1.1 插件安装 Wireshark插件目录:Help -> About Wireshark -> Folders/Pluginshttps://github.com/jamores/eth-ws-someip 解压后,将所有后缀是lua的文件拷贝到Wireshark安装目录plugins/2.4.10/下。 1.2时间戳调整为UTC显示格式 View -> Time Display Format -> Date and Tim.

专注汽车软件开发、AutoSAR、车载以太网、SOA、EE架构。 9725

[备忘]自定义IE浏览器控件

英文原文:http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/hosting/wbcustomization.asp译文出处:http://dev.youkuaiyun.com/article/19/19627.shtm 自定义浏览器本教程提供了自定义浏览器控件的行为和外观的一些方法。你将看到高级的宿主接口,IDo

在路上 2604

【STM32Cube_14】使用硬件I2C读写环境光强度传感器(BH1750)

本篇详细的记录了如何使用STM32CubeMX配置STM32L431RCT6的硬件I2C外设读取环境光强度传感器数据(BH1750)

Mculover666的博客(嵌入式) 7242

计算机组成原理(第三版)唐朔飞-第七章指令系统-课后习题

机器字长是指CPU一次能处理数据的位数通常与CPU的寄存器位数有关。指令字长是指机器指令中二进制代码的总位数。存储字长是指存储单元中存放二进制代码的总位数。三者可以相等也可以不等视不同机器而定。答:OP(4位)A1(6位)A_1(6位)A1​(6位)A2(6位)A_2(6位)A2​(6位)设二地址指令格式为该指令系统的基本格式,4位操作码共有16种编码,其中13种用来定义二地址指令,还剩3种可用作扩展标志。一地址指令条数=3∗26=192。

weixin_45735391的博客 7万+

基于MFC的网页ActiveX控件开发全程实录2(js向ActiveX控件传递参数)

原文转自https://blog.youkuaiyun.com/qianbin3200896/article/details/81452822 1、ActiveX控件部分(JS到ActiveX控件)继续上一篇博客中新建的项目,找到DActiveXDemo,右键添加——属性 添加第一个参数,用来传递字符串,具体如下 可以看到在ActiveXDemoCtrl.h文件中创建了一...

weixin_30569033的博客 116

第1集:认识 Claude Code —— AI 编程新纪元

1. 定义 Claude Code:终端中的 AI 编程代理Claude Code 是 Anthropic 公司于 2025 年 5 月正式推出的命令行 AI 编程工具,它不只是一个代码补全工具,而是一个能够理解项目、自主执行任务的**终端 AI 代理(Agent)。它的核心理念是 **"生于终端,活于终端"** (lives in your terminal)。与深度嵌入图形界面(GUI)的工具不同,Claude Code 选择直接融入开发者最原始、最核心的工作环境——命令行。

dianziyao_的博客 865

在HTML网页中插入ActiveX控件

开发工具:1. Visual Studio 2005,用于ActiveX组件的开发2. Microsoft ActiveX Control Pad,用于生成包含ActiveX Control的HTML网页。步骤:1. 通过Visual Studio 2005新建一个MFC ActiveX Control工程,编译之后在debug/release目录下可以找到一个XXXX.ocx文件。具体步骤可以参

简单,快乐 2万+

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

OSG 窗口与网页浏览器的嵌合

http://www.osgchina.org/projects/osgChina/wiki/Support/3rd/OSGandIE.php本文作者:array                                    校对整理:FlySky                      整理日期:2008/03/015OpenSceneGraph 与网络浏览器的嵌合,换句话说,

杨德龙的专栏 6958

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

VC2005从开发MFC ActiveX ocx控件到发布到.net网站的全部过程

原谅链接:http://www.cnblogs.com/gengaixue/archive/2010/08/13/1799112.html 开篇语:最近在弄ocx控件发布到asp.net网站上使用,就是用户在使用过程中,自动下载安装ocx控件。(此文章也是总结了网上好多人写的文章,我只是汇总一下,加上部分自己的东西,在这里感谢所有在网上发表相关内容的朋友们。) ActiveX控件用于W

FoxBryant的专栏 1316

MFC到Linux+QT的移植

MFC下的sleep()函数是以微秒为单位的,Linux下的speep()以秒为单位,usleep以微妙为单位; MFC下的ShowWindow()用于显示窗口,QT中显示窗口通过show()函数; MFC下的控件可以绑定一个变量(例如输入控件),当绑定的变量修改值后,通过ShowWindow()可以更新到界面上,而QT上不需要绑定变量,直接通过控件的成员函数设置值后数据会自动更新到界面上...

weixin_30848775的博客 1113

VC中自定义IE浏览器

VC中自定义IE浏览器http://www.5xsoft.com/Article.aspx?id=155本教程提供了自定义浏览器控件的行为和外观的一些方法。你将看到高级的宿主接口,IDocHostUIHandler, IDocHostUIHandler2, IDocHostShowUI,和ICustomDoc。本文也讨论其他自定义方法,例如在宿主的IDispatch实现中处理DISPID_

skyremember的专栏 6208

简单activeX控件制作流程示例

无语,密码学第一节课的实验的第一个内容就是Write an ActiveX control.....什么呀,什么都不知道,然后就去网上找教程喽。。。。折腾了一个下午,没一个有用的,郁闷。。。好吧,还好有同学折腾出来了,原来是这么简单?!在VS2008下,创建项目,项目类型就选 MFC窗口控件吧,然后都按默认点击下一步就行了。。。之后呢,认识MFC的话就会明白了,在类视图里创建一个方法,接下来会有创...

iteye_3573的博客 336
上一篇: Unity中Socket和多线程导致Editor和程序卡住解决
naruto2011sasuke
博客等级 码龄15年 16粉丝 47原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值