【小沐学C++】C++ MFC中嵌入web网页控件(WebBrowser、WebView2、CEF3)

文章介绍了如何在MFC应用程序中集成和使用WebBrowser控件,包括新建项目、添加控件、创建实例和处理窗口事件。接着,详细讲解了如何使用WebView2,包括下载安装包、添加控件代码及运行。最后提到了CEF3的下载和编译过程,它是一个基于Chromium的开源框架,用于在第三方应用中嵌入浏览器功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、简介

WebBrowser控件最常见的用途之一是向应用程序添加 Internet 浏览功能。使用 IWebBrowser2 接口,可以浏览到本地文件系统、网络或万维网上的任何位置。可以使用IWebBrowser2::Navigate 方法告知控件要浏览到哪个位置。第一个参数是包含位置名称的字符串。要浏览到本地文件系统或网络上的某个位置,请指定文件系统位置的完整路径或网络上该位置的 UNC 名称。若要浏览到万维网上的某个站点,请指定该站点的 URL。
在这里插入图片描述

2、WebBrowser

To add the WebBrowser control to a basic Microsoft Foundation Classes (MFC) application, perform the following steps.

  1. Right-click the Project name, and point to Add, the select Class… from the context menu.
  2. Select “MFC Class From ActiveX Control” and click Add.
  3. Select “Microsoft Web Browser” from among the classes listed in the registry. Highlight the IWebBrowser2 interface, and click the right arrow to generate a new CWebBrowser2 class.
  4. Click Finish.

2.1 新建测试项目

选择模板:Visual C++ -> MFC应用程序,如下:
在这里插入图片描述
选择:单个文档
在这里插入图片描述
创建的项目文件如下:
在这里插入图片描述

2.2 添加web控件类文件

在项目“MFCApplication9”上鼠标右键,在菜单里选择“类向导。。。”
在这里插入图片描述
在弹窗“类向导”中选择ActiveX控件中的MFC类。
在这里插入图片描述
安装如下的提示,选择Microsoft Web Browser<1.0>.
在这里插入图片描述
按照如下提示,选择IWebBrowser2。然后点击按钮完成。
在这里插入图片描述
然后自动在项目中生成控件的类文件如下:
在这里插入图片描述

2.3 添加web控件变量

在文件MFCApplication9View.h中添加代码如下:

#include "CWebBrowser2.h"

CWebBrowser2 *m_pBrowser;

在这里插入图片描述

2.4 添加窗口事件

对CMFCApplication9View视图类添加窗口事件:WM_CREATE,WM_SIZE

int CMFCApplication9View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  在此添加您专用的创建代码

	return 0;
}


void CMFCApplication9View::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);

	// TODO: 在此处添加消息处理程序代码
}

在这里插入图片描述
在这里插入图片描述

2.5 添加web控件实例创建代码

在上面的两个事件函数里添加对应的代码:

void CMFCApplication9View::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);

	if (m_pBrowser) {
		m_pBrowser->MoveWindow(0, 0, cx, cy);
	}
	// TODO: 在此处添加消息处理程序代码
}
int CMFCApplication9View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  在此添加您专用的创建代码

	// Create the control.
	m_pBrowser = new CWebBrowser2;
	ASSERT(m_pBrowser);
	if (!m_pBrowser->Create(NULL, NULL, WS_VISIBLE, CRect(0, 0, 0, 0), this, NULL))
	{
		TRACE("failed to create browser/n");
		delete m_pBrowser;
		m_pBrowser = NULL;
		return 0;
	}

	// Initialize the first URL.
	COleVariant noArg;
	CString strURL("https://image.baidu.com/");
	//CString strURL("https://cn.bing.com/");
	m_pBrowser->Navigate(strURL, &noArg, &noArg, &noArg, &noArg);
	return 0;
}

2.6 编译和运行

在这里插入图片描述
在这里插入图片描述

3、WebView2

Microsoft Edge WebView2 控件允许在本机应用中嵌入 web 技术(HTML、CSS 以及 JavaScript)。 WebView2 控件使用 Microsoft Edge 作为绘制引擎,以在本机应用中显示 web 内容。
在这里插入图片描述

支持以下编程环境:

  • Win32 C/C++
  • .NET Framework 4.5 或更高版本
  • .NET Core 3.1 或更高版本
  • .NET 5
  • .NET 6
  • WinUI 2.0
  • WinUI 3.0

3.1 新建测试项目

新建一个MFC的项目如上。

3.2 下载和安装WebView2包

通过菜单“项目”-“管理NuGet程序包”,下载相关包。
在这里插入图片描述
在“浏览”分页的左上角的搜索栏中,键入 Microsoft.Web.WebView2。 或者,复制并粘贴下面的单行代码块。 然后选择“ Microsoft.Web.WebView2”。以及在右侧选择对应的版本,然后点击按钮安装。
在这里插入图片描述
自动弹窗下载提示框,点击确定按钮。
在这里插入图片描述
输出下载的日志信息。
在这里插入图片描述
在项目的代码文件夹里会自动创建子文件夹packages,里面保存了下载的相关包文件夹:Microsoft.Web.WebView2.1.0.902.49
在这里插入图片描述
再下另一个包:Microsoft.Windows.ImplementationLibrary。

稍后,你将安装 Windows 实现库 (WIL) - 仅限标头的 C++ 库,通过适用于 Windows COM 编码模式的可读、类型安全的 C++ 接口,使 Windows 上的开发人员的生活更加轻松。 可通过 Visual Studio 中的 解决方案资源管理器 为项目安装此 Microsoft.Windows.ImplementationLibrary 包。

在 “NuGet” 窗口中,单击“ 浏览 ”选项卡。在左上角的搜索栏中,键入 Microsoft.Windows.ImplementationLibrary。 或者,复制并粘贴下面的单行代码块。 然后选择 “Microsoft.Windows.ImplementationLibrary”。
在这里插入图片描述
同样在项目文件夹里会下载子文件夹:Microsoft.Windows.ImplementationLibrary.1.0.191107.2
在这里插入图片描述
项目文件夹的文件packages.config:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.Web.WebView2" version="1.0.902.49" targetFramework="native" />
  <package id="Microsoft.Windows.ImplementationLibrary" version="1.0.191107.2" targetFramework="native" />
</packages>

3.3 添加web控件代码

(1)添加变量和头文件

#include <iostream>
#include <wrl.h>
#include <wil/com.h>
#include "WebView2.h"

using namespace Microsoft::WRL;

// Pointer to WebViewController
static wil::com_ptr<ICoreWebView2Controller> webviewController;

// Pointer to WebView window
static wil::com_ptr<ICoreWebView2> webview;

在这里插入图片描述

(2)在OnCreate事件函数中添加代码:

int CMFCApplication9View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;

	HWND hWnd = this->m_hWnd;

	// TODO:  在此添加您专用的创建代码
	// <-- WebView2 sample code starts here -->
	// Step 3 - Create a single WebView within the parent window
	// Locate the browser and set up the environment for WebView
	CreateCoreWebView2EnvironmentWithOptions(nullptr, nullptr, nullptr,
		Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
			[hWnd](HRESULT result, ICoreWebView2Environment* env) -> HRESULT {

		// Create a CoreWebView2Controller and get the associated CoreWebView2 whose parent is the main window hWnd
		env->CreateCoreWebView2Controller(hWnd, Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
			[hWnd](HRESULT result, ICoreWebView2Controller* controller) -> HRESULT {
			if (controller != nullptr) {
				webviewController = controller;
				webviewController->get_CoreWebView2(&webview);
			}

			// Add a few settings for the webview
			// The demo step is redundant since the values are the default settings
			wil::com_ptr<ICoreWebView2Settings> settings;
			webview->get_Settings(&settings);
			settings->put_IsScriptEnabled(TRUE);
			settings->put_AreDefaultScriptDialogsEnabled(TRUE);
			settings->put_IsWebMessageEnabled(TRUE);

			// Resize WebView to fit the bounds of the parent window
			RECT bounds;
			::GetClientRect(hWnd, &bounds);
			webviewController->put_Bounds(bounds);

			// Schedule an async task to navigate to Bing
			webview->Navigate(L"https://www.bing.com/");

			// <NavigationEvents>
			// Step 4 - Navigation events
			// register an ICoreWebView2NavigationStartingEventHandler to cancel any non-https navigation
			EventRegistrationToken token;
			webview->add_NavigationStarting(Callback<ICoreWebView2NavigationStartingEventHandler>(
				[](ICoreWebView2* webview, ICoreWebView2NavigationStartingEventArgs* args) -> HRESULT {
				wil::unique_cotaskmem_string uri;
				args->get_Uri(&uri);
				std::wstring source(uri.get());
				if (source.substr(0, 5) != L"https") {
					args->put_Cancel(true);
				}
				return S_OK;
			}).Get(), &token);
			// </NavigationEvents>

			// <Scripting>
			// Step 5 - Scripting
			// Schedule an async task to add initialization script that freezes the Object object
			webview->AddScriptToExecuteOnDocumentCreated(L"Object.freeze(Object);", nullptr);
			// Schedule an async task to get the document URL
			webview->ExecuteScript(L"window.document.URL;", Callback<ICoreWebView2ExecuteScriptCompletedHandler>(
				[](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT {
				LPCWSTR URL = resultObjectAsJson;
				//doSomethingWithURL(URL);
				return S_OK;
			}).Get());
			// </Scripting>

			// <CommunicationHostWeb>
			// Step 6 - Communication between host and web content
			// Set an event handler for the host to return received message back to the web content
			webview->add_WebMessageReceived(Callback<ICoreWebView2WebMessageReceivedEventHandler>(
				[](ICoreWebView2* webview, ICoreWebView2WebMessageReceivedEventArgs* args) -> HRESULT {
				wil::unique_cotaskmem_string message;
				args->TryGetWebMessageAsString(&message);
				// processMessage(&message);
				webview->PostWebMessageAsString(message.get());
				return S_OK;
			}).Get(), &token);

			// Schedule an async task to add initialization script that
			// 1) Add an listener to print message from the host
			// 2) Post document URL to the host
			webview->AddScriptToExecuteOnDocumentCreated(
				L"window.chrome.webview.addEventListener(\'message\', event => alert(event.data));" \
				L"window.chrome.webview.postMessage(window.document.URL);",
				nullptr);
			// </CommunicationHostWeb>

			return S_OK;
		}).Get());
		return S_OK;
	}).Get());

	// <-- WebView2 sample code ends here -->
	return 0;
}

(3)在OnSize事件函数中添加代码:

void CMFCApplication9View::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);

	// TODO: 在此处添加消息处理程序代码
	if (webviewController != nullptr) {
		RECT bounds;
		GetClientRect(&bounds);
		webviewController->put_Bounds(bounds);
	};
}

3.4 编译和运行

最后运行的测试程序的界面如下:
在这里插入图片描述

4、CEF3

CEF全称Chromium Embedded Framework,是一个基于Google Chromium 的开源项目。Google Chromium项目主要是为Google Chrome应用开发的,而CEF的目标则是为第三方应用提供可嵌入浏览器支持。CEF隔离底层Chromium和Blink的复杂代码,并提供一套产品级稳定的API,发布跟踪具体Chromium版本的分支,以及二进制包。CEF的大部分特性都提供了丰富的默认实现,让使用者做尽量少的定制即可满足需求。

在这里插入图片描述

4.1 下载cef3

https://cef-builds.spotifycdn.com/index.html
在这里插入图片描述
浏览器直接搜索关键词「CEF Automated Builds」找到新的下载站点。

4.2 编译和运行cef3

对于cef来说,只需要把编译出来的libcef_dll_wrapper.lib拿来使用即可,其他文件直接包里的即可。

cef_binary_3.3578.1860.g36610bd_windows32 
或 
cef_binary_88.2.9+g5c8711a+chromium-88.0.4324.182_windows32_minimal

VisualStudio2017、2019编译非常快速,使用CMake对相关代码为例,使用CMake-gui转换,默认是64位版本(如果需要使用32位版本,转换的时候注意选择Win32),转换后的vs工程默认就是Unicode字符集MTd(MT)的,直接编译libcef_dll_wrapper即可,生成的lib拷走,其他的lib直接使用现成的。

创建成功后只编译libcef_dll_wrapper即可,其他lib和资源使用编译好的即可。
尽量链接release版本的,要链接:libcef.lib、cef_sandbox.lib、libcef_dll_wrapper
字符串要传递的时候,需转换为Unicode,可使用std::wstring转换。
cefinitialize崩溃:说明exe执行路径下缺少相关文件导致初始化失败,可以把Resources目录下的locales文件夹、icudtl.dat、cef*.pak等文件复制过来。

  • 通过cmake构建cef的vs工程。

在这里插入图片描述

  • 依次点击按钮:“Configure” -> “Generate” -> “Open Project”

在这里插入图片描述

  • 生成vs工程文件:

在这里插入图片描述
用vs2017打开解决方案文件cef.sln,如下:
在这里插入图片描述
其中cefsimple和cefclient是基于win32的实现cef3浏览器的简单示例代码,相对而言,cefsimple比较简单,代码量比较少,mfc中也主要是用这个工程中的文件。
编译和运行,其中cefclient.exe运行如下:
在这里插入图片描述

D:\cef_binary88\Release\libcef.lib
D:\cef_binary88\Release\cef_sandbox.lib
D:\cef_binary88\Release\libcef_dll_wrapper.lib

结语

如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;╮( ̄▽ ̄)╭
如果您感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进;o_O???
如果您需要相关功能的代码定制化开发,可以留言私信作者;(✿◡‿◡)
感谢各位大佬童鞋们的支持!( ´ ▽´ )ノ ( ´ ▽´)っ!!!

<think>好的,用户问的是C++是否可以使用UEditor。首先,我需要确认UEditor是什么,以及它通常支持的平台和语言。 UEditor是百度开发的富文本编辑器,主要用于网页中,所以通常和前端技术如HTML、JavaScript一起使用。用户提到C++,可能是在问是否能在C++开发的应用中集成这个编辑器。 接下来,我需要考虑C++应用的常见场景。比如,桌面应用程序或者后端服务。如果是桌面应用,可能需要嵌入一个Web视图控件来加载UEditor,因为UEditor本身是基于Web的。这样的话,C++框架如Qt的QtWebEngine或MFC中的WebBrowser控件可能会用到。 另外,用户可能是想在后端用C++处理UEditor生成的内容,比如解析HTML或处理文件上传。这时候,C++可以作为后端服务,通过HTTP接口与前端UEditor交互,处理数据。 还要注意UEditor的依赖,它需要浏览器环境,所以纯C++环境可能无法直接运行,必须结合Web技术。可能需要通过C++启动一个本地服务器,或者将应用设计为混合模式,前端Web,后端用C++。 另外,是否有现成的C++集成案例或者库?可能需要查看官方文档或社区支持。如果官方没有提供C++的SDK,可能需要自己处理接口和数据交换,比如通过JSON或HTTP通信。 最后,总结可能性:C++可以通过嵌入Web组件来使用UEditor,但需要依赖Web技术栈的支持,无法直接作为原生控件使用。需要根据具体应用场景选择合适的集成方式。</think>C++ 可以通过以下方式集成 UEditor 富文本编辑器,但需注意其实现原理和局限性: 1. 基本实现方案 - 适用场景:C++桌面应用程序(如Qt/MFC/WxWidgets) - 技术路线: $$WebView控件 + 本地HTTP服务$$ ① 使用Qt的QWebEngineView或CEF框架加载UEditor网页 ② 通过C++创建本地HTTP服务器(如cpp-httplib) ③ 实现前后端通信: ```cpp // C++伪代码示例 svr.Post("/save-content", [](const Request& req, Response& res) { std::string content = req.body; // 处理HTML内容... res.set_content("保存成功", "text/plain"); }); ``` 2. 技术难点 - 跨语言通信:需实现C++与JavaScript的互操作 ```javascript // 前端调用C++ external.invokeCppFunction(JSON.stringify(data)); ``` - 文件上传处理:需自行实现图片上传接口 $$上传路径 = 服务器根目录 + 随机文件名$$ 3. 推荐方案对比 | 方案 | 开发难度 | 性能 | 维护成本 | 适用场景 | |-------------------|----------|--------|----------|------------------| | Qt WebEngine | ★★☆☆☆ | 较高 | 低 | 跨平台桌面应用 | | CEF框架 | ★★★★☆ | 高 | 中 | 复杂Web集成 | | 独立浏览器进程 | ★★★☆☆ | 较低 | 高 | 简单功能实现 | 4. 替代方案建议 - 考虑Scintilla编辑器(纯C++实现) ```cpp // 初始化示例 ScintillaEdit *editor = new ScintillaEdit(); editor->setLexer(SCLEX_HTML); ``` - 优点:无Web依赖、内存占用低(约30MB vs UEditor的150MB+) 5. 注意事项 - 安全防护:需对HTML内容进行过滤(防止XSS攻击) - 性能优化:建议设置内存缓存上限 $$缓存上限 = 页面数量 \times 单页平均大小$$ 结论:虽然技术上可行,但需要权衡开发成本与需求场景。对需要深度定制的富文本场景推荐使用Web方案,基础文本编辑建议选择原生C++组件。
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值