文章详情
C++调用WebView2在windows系统实现快速htmlUI联动
Posted on 2026-01-01 17:16:30 by 主打一个C++
*纯个人使用记录
重要: 安装 WebView2 NuGet 包
Microsoft.Web.WebView2
Microsoft.Windows.ImplementationLibraryhtml代码测试,与exe同目录,名称为index.html
<html>
<head>
<style>
body { font-family: 'Segoe UI', sans-serif; padding: 20px;background-color: #ff0000; }
button { padding: 10px 20px; font-size: 16px; cursor: pointer; margin: 5px; }
#content { margin-top: 20px; border: 1px solid #ccc; padding: 15px; min-height: 50px; }
</style>
</head>
<body>
<h2>WebView2 C++ 示例</h2>
<button id='btnInsert'>插入一段 HTML</button>
<button id='btnCallCpp'>调用 C++</button>
<div id='content'>点击按钮,我会改变内容。</div>
</body>
<script>
document.getElementById('btnInsert').addEventListener('click', function() {
document.getElementById('content').innerHTML = '<p style=\"color:blue;\">这是动态插入的 <b>HTML</b> 内容!</p>';
});
document.getElementById('btnCallCpp').addEventListener('click', function() {
callC('Hello from JS!');
});
window.chrome.webview.addEventListener('message', function(event) {
alert('收到 C++ 消息:' + event.data);
});
</script>
<script>
function callC(msg) {
window.chrome.webview.postMessage(msg);
}
</script>
</html>C++测试代码:习惯性的多字节
#include <windows.h>
#include <wrl.h>
#include <wil/com.h>
#include <WebView2.h>
#include <WebView2EnvironmentOptions.h>
#include <string>
#include <fstream>
#include <vector>
#include <cstdio>
using namespace Microsoft::WRL;
// 全局变量
HWND g_hMainWnd = nullptr;
ComPtr<ICoreWebView2Controller> g_webviewController;
ComPtr<ICoreWebView2> g_webview;
//指令分发
void IDF(ICoreWebView2* sender, PCWSTR cmd);
// 从文件加载 HTML(多字节 ANSI),转换为宽字符串
std::wstring LoadHtmlFromFile(const char* filename) {
std::ifstream file(filename, std::ios::binary | std::ios::ate);
if (!file.is_open()) {
MessageBoxA(nullptr, "无法打开 index.html 文件!", "错误", MB_ICONERROR);
exit(1);
}
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<char> buffer(size + 1);
if (!file.read(buffer.data(), size)) {
MessageBoxA(nullptr, "读取文件失败!", "错误", MB_ICONERROR);
exit(1);
}
buffer[size] = '\0';
// 将 ANSI 字符串转换为宽字符(使用系统默认代码页)
int wideLen = MultiByteToWideChar(CP_UTF8, 0, buffer.data(), (int)size, nullptr, 0);
if (wideLen == 0) {
MessageBoxA(nullptr, "编码转换失败!", "错误", MB_ICONERROR);
exit(1);
}
std::wstring wstr(wideLen, L'\0');
MultiByteToWideChar(CP_UTF8, 0, buffer.data(), (int)size, &wstr[0], wideLen);
return wstr;
}
// 窗口过程
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_SIZE:
if (g_webviewController) {
RECT bounds;
GetClientRect(hWnd, &bounds);
g_webviewController->put_Bounds(bounds);
}
break;
default:
return DefWindowProcA(hWnd, msg, wParam, lParam); // 注意使用 ANSI 版本
}
return 0;
}
void InitializeWebView2(HWND hWnd) {
// 1. 创建环境选项
auto options = Make<CoreWebView2EnvironmentOptions>();
// 2. 异步创建环境
HRESULT hr = CreateCoreWebView2EnvironmentWithOptions(
nullptr, nullptr, options.Get(),
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
[hWnd](HRESULT result, ICoreWebView2Environment* env) -> HRESULT {
if (FAILED(result)) return result;
// 3. 创建控制器
env->CreateCoreWebView2Controller(
hWnd,
Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
[hWnd](HRESULT result, ICoreWebView2Controller* controller) -> HRESULT {
if (FAILED(result)) return result;
g_webviewController = controller;
g_webviewController->get_CoreWebView2(&g_webview);
// 4. 设置大小
RECT bounds;
GetClientRect(hWnd, &bounds);
g_webviewController->put_Bounds(bounds);
// 5. 从文件加载 HTML
std::wstring html = LoadHtmlFromFile("index.html");
HRESULT hr = g_webview->NavigateToString(html.c_str());
if (FAILED(result)) {
MessageBoxA(nullptr, "出现未知的错误!", "错误", MB_ICONERROR);
return result;
}
// 6. 注册 JS → C++ 消息回调
g_webview->add_WebMessageReceived(
Callback<ICoreWebView2WebMessageReceivedEventHandler>(
[](ICoreWebView2* sender, ICoreWebView2WebMessageReceivedEventArgs* args) -> HRESULT {
wil::unique_cotaskmem_string message;
args->TryGetWebMessageAsString(&message);
IDF(sender, message.get());
return S_OK;
}
).Get(),
nullptr
);
return S_OK;
}
).Get()
);
return S_OK;
}
).Get()
);
}
int main() {
HINSTANCE hInstance = GetModuleHandle(nullptr);
HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
if (FAILED(hr)) {
// 处理初始化失败,可以弹出错误并退出
MessageBoxA(nullptr, "COM 初始化失败!", "错误", MB_ICONERROR);
return -1;
}
// 注册窗口类(ANSI 版本)
WNDCLASSEXA wc = {};
wc.cbSize = sizeof(WNDCLASSEXA);
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.lpszClassName = "WUYOUCLASS"; // 多字节字符串
RegisterClassExA(&wc);
// 创建窗口(ANSI 版本)
g_hMainWnd = CreateWindowExA(
0, "WUYOUCLASS", "天堂W",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
nullptr, nullptr, hInstance, nullptr
);
if (!g_hMainWnd) return 0;
ShowWindow(g_hMainWnd, SW_SHOW);
UpdateWindow(g_hMainWnd);
InitializeWebView2(g_hMainWnd);
MSG msg;
while (GetMessageA(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
CoUninitialize();
return (int)msg.wParam;
}
//指令分发
void IDF(ICoreWebView2* sender, PCWSTR cmd) {
MessageBoxW(nullptr, cmd, L"来自 JS", MB_OK);
std::wstring reply = cmd;
sender->PostWebMessageAsString(reply.c_str());
}