L o a d i n g . . .
主打一个C++
文章详情

C++调用WebView2在windows系统实现快速htmlUI联动

Posted on 2026-01-01 17:16:30 by 主打一个C++

*纯个人使用记录

重要: 安装 WebView2 NuGet 包

Microsoft.Web.WebView2
Microsoft.Windows.ImplementationLibrary

html代码测试,与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());
}


*转载请注明出处:原文链接:https://52xuexi.site/page/160.html

作者近期文章
  • Python
  • 主打一个C++   2025-07-01 17:58:09
  • Anaconda 是管理 Python 环境最方便的工具,能一键创建、切换、删除环境什么的•下载地址:https://www.anaconda.com/download/suc
提示
×
确定
数据库执行: 7次 总耗时: 0.01s
页面加载耗时: 



wechat +447752296473
wechat cpp-blog