Sciter之c++与前端事件状态交互(六)
上一篇介绍了c与前端html相互调用能力,本章将介绍c与html(前端)事件状态相互。
前言
Sciter 是一个高质量但小众的嵌入式 UI 引擎,适合追求性能、体积和原生集成的桌面应用开发者。
我觉得 Sciter 比较有意思,它很小众,是闭源的,商用需要许可。它是Andrew Fedoniouk开发维护,Andrew获得了物理学和应用数学硕士学位以及艺术文凭。他的职业生涯始于俄罗斯航空航天工业的研究员。这种跨领域背景使他既具备深厚的技术功底,又懂得用户界面设计的艺术。
Sciter官网:https://sciter.com/ 2025-11-15 sciter-js-sdk最新版v6.0.2.28
本次入门开发环境:window 10 + Clion 2024.3 + Sciter-js v6.0.2.28(2025-11-15最新版) + Bundled MinGW 11.0
c++监听js事件
- 基于窗口级别的
handle_event
c++ 代码
#include <cstdint> // C++ 标准头文件(首选)
#include <windows.h>
#include <thread>
#include <fcntl.h>
#include "sciter-x-window.hpp"
#include "aux-cvt.h"
#include "sciter-x.h"
#include "sciter-x-dom.h"
#include "sciter-x-threads.h"
#include "sciter-x-behavior.h"
class myWindow : public sciter::window {
public:
myWindow() : window(SW_MAIN | SW_ENABLE_DEBUG) {}
// 重写 window 的事件处理
bool handle_event(HELEMENT he, BEHAVIOR_EVENT_PARAMS ¶ms) override {
if (params.cmd == DOCUMENT_PARSED && params.heTarget == root())
initial_window_state_defined = sciter::dom::element(root()).get_attribute("window-state").length() != 0;
// 能够处理所有事件,例如按钮点击、窗口激活、获得失去焦点等...
// 捕获自定义事件
if (params.cmd == CUSTOM && params.name != nullptr) {
// 还有大量事件需要过滤
if (wcscmp(params.name, L"my-custom-event") == 0) {
// 筛选出我们的事件
std::wcout << L"捕获到自定义事件: " << params.name << "cmd = 0x" << std::hex << params.cmd << std::endl;
std::wcout << L"接收到的数据:" << params.data.to_string() << std::endl;
}
}
return false;
}
};
int uimain(std::function<int()> run) {
// 创建ui窗口实例
sciter::om::hasset<myWindow> window = new myWindow();
// 加载前端UI的html文件
window->load(
WSTR("file://C:\\Users\\Administrator\\Desktop\\project\\sciter\\app\\demo_20251121\\ui\\hello-ui_event.html"));
window->expand();
return run();
}
/**
* 图形用户界面(GUI)应用程序的标准入口函数,相当于控制台程序中的 main 函数。
* 2025-11-15 by lingkang
*/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
// 启用试调
SciterSetOption(NULL, SCITER_SET_SCRIPT_RUNTIME_FEATURES,
ALLOW_FILE_IO |
ALLOW_SOCKET_IO |
ALLOW_EVAL |
ALLOW_SYSINFO);
// 设置控制台输出为宽字符模式(可选但推荐)
_setmode(_fileno(stdout), _O_U8TEXT);
// 初始化sciter
sciter::application::start();
// 加载我们的窗口
uimain([]() -> int { return sciter::application::run(); });
// 结束时 关闭
sciter::application::shutdown();
return 0;
}
static std::vector<sciter::string> _argv;
// 设置 sciter 的初始化应用
namespace sciter {
namespace application {
HINSTANCE hinstance() {
return nullptr; // not used
}
const std::vector<sciter::string> &argv() {
// 获取命令行参数
return _argv;
}
}
}
前端代码
<!DOCTYPE html>
<html
window-width=600px
window-height=450px
window-resizable=true
>
<head>
<meta charset="UTF-8">
<title>lingkang的sciter前端与c++之间事件状态交互</title>
<style>
.flex-row {
display: flex;
flex-direction: row;
gap: 10px;
}
</style>
</head>
<body style="display: flex;flex-direction: column;gap: 20px">
<h2>发送事件给c++</h2>
<button id="btn-01">发送简单事件</button>
<h2>监听c++发过来的事件</h2>
<p>这是一个伪命题,转换思路为:c++调用js代码即可。例如上一篇提到的 “c++调用前端js定义的 my_js_fun 方法”</p>
<script>
// 给按钮绑定点击事件
document.getElementById('btn-01').onclick = function () {
const event = new Event('my-custom-event', {
data: 'lingkang你好~'
})
// 发送
Window.this.postEvent(event)
}
</script>
</body>
</html>
前端监听c++事件
这是一个伪命题,转换思路为:c++调用 js 代码即可。例如上一篇提到的 “c++调用前端js定义的 my_js_fun 方法” 来触发前端方法事件
c++调用js定义的方法伪代码:
// 调用html中定义的js方法
void callJavaScriptFun() {
// 入参,只有一个
VALUE argvs[1];
LPCWSTR chars = L"入参字符串:lingkang";
ValueStringDataSet(&argvs[0], chars, wcslen(chars), 0);
VALUE result;
// 调用前端js定义的 my_js_fun 方法
SCDOM_RESULT ok = SciterCallScriptingFunction(root(), "my_js_fun", argvs, 1, &result);
if (ok == SCDOM_OK) {
LPCWSTR str_data;
UINT str_length;
ValueStringData(&result, &str_data, &str_length);
// 获取字符串数据
std::wcout << "调用js的结果: " << str_data << std::endl;
} else {
// 处理错误
std::cout << "调用js出错啦 " << std::endl;
}
// 清理
ValueClear(&result);
ValueClear(&argvs[0]);
}
效果
