C++ Saucer 编写Windows桌面应用
文章目录
- 一、背景
- 二、Saucer 简介
- 核心特性
- 典型应用场景
- 三、生成自己的项目
- 四、以Win32项目方式构建
- Win32项目
- 禁用最大化按钮
- 五、总结
一、背景
使用Saucer框架,开发Windows桌面应用,把一个html页面作为GUI设计放到Saucer里,隐藏掉运行时弹出的控制台窗口(当cmake项目非Win32时,在Windows环境下会弹出控制台),同时禁用最大化按钮。
二、Saucer 简介
Saucer 是一个现代化的C++库,专为使用Web技术构建跨平台桌面应用而设计。它允许开发者利用熟悉的Web前端技术(HTML/CSS/JavaScript)结合C++后端能力,为Windows、macOS和Linux等主流桌面操作系统创建高性能应用程序。
核心特性
1. 跨平台支持
一套代码即可编译并运行在三大桌面操作系统上,无需为不同平台单独实现。
2. Web技术集成
前端界面完全基于Web技术(HTML/CSS/JavaScript),可直接嵌入现有前端框架(如React、Vue),同时通过C++处理底层逻辑。
3. 灵活的前后端交互
支持C++与JavaScript的双向通信,允许前端调用后端功能,或后端主动更新界面,适用于复杂交互场景。
4. TypeScript支持
提供官方TypeScript类型定义包(@saucerjs/types),增强前端开发的类型安全性和开发体验。
5. 模块化构建
通过CMake配置项目,支持自定义编译选项(如渲染引擎选择、调试模式开关),适应不同项目需求。
6. 轻量级依赖
仅需系统级基础依赖(如Web渲染引擎),无需引入臃肿的运行时环境。
典型应用场景
- 需原生性能但要求快速迭代UI的应用(如数据可视化工具)。
- 将现有Web应用迁移为桌面端应用。
- 混合开发:Web界面 + C++计算/文件操作等底层功能。
三、生成自己的项目
考虑比较简单的使用,我直接在saucer目录里新增projects文件夹,在里面新建自己的cmake项目。
cmake_minimum_required(VERSION 3.16)
project(calendar LANGUAGES CXX VERSION 1.0)# --------------------------------------------------------------------------------------------------------
# Create executable
# --------------------------------------------------------------------------------------------------------add_executable(${PROJECT_NAME} "main.cpp")
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_23)
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 23 CXX_EXTENSIONS OFF CXX_STANDARD_REQUIRED ON)# --------------------------------------------------------------------------------------------------------
# Copy The HTML file
# --------------------------------------------------------------------------------------------------------file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/index.htmlDESTINATION ${CMAKE_CURRENT_BINARY_DIR})# --------------------------------------------------------------------------------------------------------
# Link libraries
# --------------------------------------------------------------------------------------------------------target_link_libraries(${PROJECT_NAME} PRIVATE saucer)
把项目作为子目录添加到整体的CMakeLists.txt
文件中:
# --------------------------------------------------------------------------------------------------------
# My Projects
# --------------------------------------------------------------------------------------------------------add_subdirectory("projects/calendar")
该项目的main.cpp
文件如下:
#include <saucer/smartview.hpp>int main()
{auto app = saucer::application::init({.id = "calendar"});saucer::smartview webview{{.application = app}};// 设置webview尺寸及标题webview.set_size(360, 600);webview.set_title("日历");// 指定页面文件webview.set_file("index.html");webview.show();app->run();return 0;
}
我的开发环境是VS2022,切换到cmake目标视图,可以看到这个项目:
生成并运行该项目,效果如下:
可以看到,项目会先启动一个控制台窗口,然后再打开桌面应用。
四、以Win32项目方式构建
考虑程序是在Windows平台上运行,带着控制台窗口显然不太合理,于是,需要考虑把这个控制台窗口去掉。
Win32项目
采用Win32类型项目构建,可以避免这个问题,我们可以在CMakeLists.txt文件中作如下设置(add_executable
指令中,加入WIN32
关键字):
cmake_minimum_required(VERSION 3.16)
project(calendar-win LANGUAGES CXX VERSION 1.0)# --------------------------------------------------------------------------------------------------------
# Create executable
# --------------------------------------------------------------------------------------------------------add_executable(${PROJECT_NAME} WIN32 "main.cpp")
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_23)
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 23 CXX_EXTENSIONS OFF CXX_STANDARD_REQUIRED ON)# --------------------------------------------------------------------------------------------------------
# Copy The HTML file
# --------------------------------------------------------------------------------------------------------file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/index.htmlDESTINATION ${CMAKE_CURRENT_BINARY_DIR})# --------------------------------------------------------------------------------------------------------
# Link libraries
# --------------------------------------------------------------------------------------------------------target_link_libraries(${PROJECT_NAME} PRIVATE saucer)
同时,我们修改main.cpp文件,使之支持Win32项目:
#include <saucer/smartview.hpp>#ifdef WIN32
#include <Windows.h>
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
#else
int main()
#endif
{auto app = saucer::application::init({.id = "calendar"});saucer::smartview webview{{.application = app}};// 设置webview尺寸及标题webview.set_size(360, 600);webview.set_title("日程提醒");// 指定页面文件webview.set_file("index.html");webview.show();app->run(); return 0;
}
这时候重新构建,刚才出现的控制台将消失,直接打开Windows窗口。
禁用最大化按钮
在开发过程中,我尝试禁用最大化按钮,例如,加入如下C++代码:
auto hwnd = GetActiveWindow();DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE);dwStyle ^= WS_MAXIMIZEBOX; // 设置窗体取消最大化按钮SetWindowLong(hwnd, GWL_STYLE, dwStyle);
一开始,我把上述代码放在程序开头,如下:
#include <saucer/smartview.hpp>#ifdef WIN32
#include <Windows.h>
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
#else
int main()
#endif
{auto hwnd = GetActiveWindow();DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE);dwStyle ^= WS_MAXIMIZEBOX; // 设置窗体取消最大化按钮SetWindowLong(hwnd, GWL_STYLE, dwStyle);auto app = saucer::application::init({.id = "calendar"});saucer::smartview webview{{.application = app}};// 设置webview尺寸及标题webview.set_size(360, 600);webview.set_title("日程提醒");// 指定页面文件webview.set_file("index.html");webview.show();app->run(); return 0;
}
然后并不生效,后来通过F5代码调试和实际试验,这段控制代码应该放在webview.show()
和app->run()
之间,从而保证能找到活动窗口,并且不离开主线程,修改后的main.cpp代码如下:
#include <saucer/smartview.hpp>#ifdef WIN32
#include <Windows.h>
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
#else
int main()
#endif
{auto app = saucer::application::init({.id = "calendar"});saucer::smartview webview{{.application = app}};// 设置webview尺寸及标题webview.set_size(360, 600);webview.set_title("日程提醒");// 指定页面文件webview.set_file("index.html");webview.show();// 在webview.show()之后,app->run()之前加入窗体按钮控制代码段// 实现对窗体按钮的控制auto hwnd = GetActiveWindow();DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE);dwStyle ^= WS_MAXIMIZEBOX; // 设置窗体取消最大化按钮SetWindowLong(hwnd, GWL_STYLE, dwStyle);app->run(); return 0;
}
生成并运行,禁用了窗体最大化按钮:
五、总结
以上是我一次使用Saucer的体验,通过Saucer,开发者既能发挥C++的硬件级性能优势,又能享受Web技术的高效界面开发能力,实现真正的"一次编写,多平台运行"。
相关文章:

C++ Saucer 编写Windows桌面应用
文章目录 一、背景二、Saucer 简介核心特性典型应用场景 三、生成自己的项目四、以Win32项目方式构建Win32项目禁用最大化按钮 五、总结 一、背景 使用Saucer框架,开发Windows桌面应用,把一个html页面作为GUI设计放到Saucer里,隐藏掉运行时弹…...
中国政务数据安全建设细化及市场需求分析
(基于新《政务数据共享条例》及相关法规) 一、引言 近年来,中国政府高度重视数字政府建设和数据要素市场化配置改革。《政务数据共享条例》(以下简称“《共享条例》”)的发布,与《中华人民共和国数据安全法》(以下简称“《数据安全法》”)、《中华人民共和国个人信息…...

【AI News | 20250609】每日AI进展
AI Repos 1、OpenHands-Versa OpenHands-Versa 是一个通用型 AI 智能体,通过结合代码编辑与执行、网络搜索、多模态网络浏览和文件访问等通用工具,在软件工程、网络导航和工作流自动化等多个领域展现出卓越性能。它在 SWE-Bench Multimodal、GAIA 和 Th…...

轻量安全的密码管理工具Vaultwarden
一、Vaultwarden概述 Vaultwarden主要作用是提供一个自托管的密码管理器服务。它是Bitwarden密码管理器的第三方轻量版,由国外开发者在Bitwarden的基础上,采用Rust语言重写而成。 (一)Vaultwarden镜像的作用及特点 轻量级与高性…...

SQLSERVER-DB操作记录
在SQL Server中,将查询结果放入一张新表可以通过几种方法实现。 方法1:使用SELECT INTO语句 SELECT INTO 语句可以直接将查询结果作为一个新表创建出来。这个新表的结构(包括列名和数据类型)将与查询结果匹配。 SELECT * INTO 新…...

开疆智能Ethernet/IP转Modbus网关连接鸣志步进电机驱动器配置案例
在工业自动化控制系统中,常常会遇到不同品牌和通信协议的设备需要协同工作的情况。本案例中,客户现场采用了 罗克韦尔PLC,但需要控制的变频器仅支持 ModbusRTU 协议。为了实现PLC 对变频器的有效控制与监控,引入了开疆智能Etherne…...

NineData数据库DevOps功能全面支持百度智能云向量数据库 VectorDB,助力企业 AI 应用高效落地
NineData 的数据库 DevOps 解决方案已完成对百度智能云向量数据库 VectorDB 的全链路适配,成为国内首批提供 VectorDB 原生操作能力的服务商。此次合作聚焦 AI 开发核心场景,通过标准化 SQL 工作台与细粒度权限管控两大能力,助力企业安全高效…...

代理服务器-LVS的3种模式与调度算法
作者介绍:简历上没有一个精通的运维工程师。请点击上方的蓝色《运维小路》关注我,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 我们上一章介绍了Web服务器,其中以Nginx为主,本章我们来讲解几个代理软件:…...
ubuntu清理垃圾
windows和ubuntu 双系统,ubuntu 150GB,开发用,基本不装太多软件。但是磁盘基本用完。 1、查看home目录 sudo du -h -d 1 $HOME | grep -v K 上面的命令查看$HOME一级目录大小,发现 .cache 有26GB,.local 有几个GB&am…...
学习 Hooks【Plan - June - Week 2】
一、React API React 提供了丰富的核心 API,用于创建组件、管理状态、处理副作用、优化性能等。本文档总结 React 常用的 API 方法和组件。 1. React 核心 API React.createElement(type, props, …children) 用于创建 React 元素,JSX 会被编译成该函数…...
宠物车载安全座椅市场报告:解读行业趋势与投资前景
一、什么是宠物车载安全座椅? 宠物车载安全座椅是一种专为宠物设计的车内固定装置,旨在保障宠物在乘车过程中的安全性与舒适性。它通常由高强度材料制成,具备良好的缓冲性能,并可通过安全带或ISOFIX接口固定于车内。 近年来&…...

解决MybatisPlus使用Druid1.2.11连接池查询PG数据库报Merge sql error的一种办法
目录 前言 一、问题重现 1、环境说明 2、重现步骤 3、错误信息 二、关于LATERAL 1、Lateral作用场景 2、在四至场景中使用 三、问题解决之道 1、源码追踪 2、关闭sql合并 3、改写处理SQL 四、总结 前言 在博客:【写在创作纪念日】基于SpringBoot和PostG…...
Neo4j 完全指南:从入门到精通
第1章:Neo4j简介与图数据库基础 1.1 图数据库概述 传统关系型数据库与图数据库的对比图数据库的核心优势图数据库的应用场景 1.2 Neo4j的发展历史 Neo4j的起源与演进Neo4j的版本迭代Neo4j在图数据库领域的地位 1.3 图数据库的基本概念 节点(Node)与关系(Relat…...
day51 python CBAM注意力
目录 一、CBAM 模块简介 二、CBAM 模块的实现 (一)通道注意力模块 (二)空间注意力模块 (三)CBAM 模块的组合 三、CBAM 模块的特性 四、CBAM 模块在 CNN 中的应用 一、CBAM 模块简介 在之前的探索中…...

使用VMware克隆功能快速搭建集群
自己搭建的虚拟机,后续不管是学习java还是大数据,都需要集群,java需要分布式的微服务,大数据Hadoop的计算集群,如果从头开始搭建虚拟机会比较费时费力,这里分享一下如何使用克隆功能快速搭建一个集群 先把…...

篇章一 论坛系统——前置知识
目录 1.软件开发 1.1 软件的生命周期 1.2 面向对象 1.3 CS、BS架构 1.CS架构编辑 2.BS架构 1.4 软件需求 1.需求分类 2.需求获取 1.5 需求分析 1. 工作内容 1.6 面向对象分析 1.OOA的任务 2.统一建模语言UML 3. 用例模型 3.1 用例图的元素 3.2 建立用例模型 …...
十二、【ESP32全栈开发指南: IDF开发环境下cJSON使用】
一、JSON简介 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,具有以下核心特性: 完全独立于编程语言的文本格式易于人阅读和编写易于机器解析和生成基于ECMAScript标准子集 1.1 JSON语法规则 {"name"…...

Qt/C++学习系列之列表使用记录
Qt/C学习系列之列表使用记录 前言列表的初始化界面初始化设置名称获取简单设置 单元格存储总结 前言 列表的使用主要基于QTableWidget控件,同步使用QTableWidgetItem进行单元格的设置,最后可以使用QAxObject进行单元格的数据读出将数据进行存储。接下来…...
【Pandas】pandas DataFrame dropna
Pandas2.2 DataFrame Missing data handling 方法描述DataFrame.fillna([value, method, axis, …])用于填充 DataFrame 中的缺失值(NaN)DataFrame.backfill(*[, axis, inplace, …])用于**使用后向填充(即“下一个有效观测值”)…...

基于django+vue的健身房管理系统-vue
开发语言:Python框架:djangoPython版本:python3.8数据库:mysql 5.7数据库工具:Navicat12开发软件:PyCharm 系统展示 会员信息管理 员工信息管理 会员卡类型管理 健身项目管理 会员卡管理 摘要 健身房管理…...

Yolo11改进策略:Block改进|FCM,特征互补映射模块|AAAI 2025|即插即用
1 论文信息 FBRT-YOLO(Faster and Better for Real-Time Aerial Image Detection)是由北京理工大学团队提出的专用于航拍图像实时目标检测的创新框架,发表于AAAI 2025。论文针对航拍场景中小目标检测的核心难题展开研究,重点解决…...
【系统架构设计师-2025上半年真题】综合知识-参考答案及部分详解(回忆版)
更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 【第1题】【第2题】【第3题】【第4题】【第5题】【第6题】【第7题】【第8题】【第9题】【第10题】【第11题】【第12题】【第13题】【第14题】【第15题】【第16题】【第17题】【第18题】【第19题】【第20~21题】【第…...

简单聊下阿里云DNS劫持事件
阿里云域名被DNS劫持事件 事件总结 根据ICANN规则,域名注册商(Verisign)认定aliyuncs.com域名下的部分网站被用于非法活动(如传播恶意软件);顶级域名DNS服务器将aliyuncs.com域名的DNS记录统一解析到shado…...
LTR-381RGB-01RGB+环境光检测应用场景及客户类型主要有哪些?
RGB环境光检测 功能,在应用场景及客户类型: 1. 可应用的儿童玩具类型 (1) 智能互动玩具 功能:通过检测环境光或物体颜色触发互动(如颜色识别积木、光感音乐盒)。 客户参考: LEGO(乐高&#x…...

循环语句之while
While语句包括一个循环条件和一段代码块,只要条件为真,就不断 循环执行代码块。 1 2 3 while (条件) { 语句 ; } var i 0; while (i < 100) {console.log(i 当前为: i); i i 1; } 下面的例子是一个无限循环,因…...

机器学习复习3--模型评估
误差与过拟合 我们将学习器对样本的实际预测结果与样本的真实值之间的差异称为:误差(error)。 误差定义: ①在训练集上的误差称为训练误差(training error)或经验误差(empirical error&#x…...

联邦学习带宽资源分配
带宽资源分配是指在网络中如何合理分配有限的带宽资源,以满足各个通信任务和用户的需求,尤其是在多用户共享带宽的情况下,如何确保各个设备或用户的通信需求得到高效且公平的满足。带宽是网络中的一个重要资源,通常指的是单位时间…...

今日行情明日机会——20250609
上证指数放量上涨,接近3400点,个股涨多跌少。 深证放量上涨,但有个小上影线,相对上证走势更弱。 2025年6月9日涨停股主要行业方向分析(基于最新图片数据) 1. 医药(11家涨停) 代表标…...

GC1808:高性能音频ADC的卓越之选
在音频处理领域,高质量的音频模数转换器(ADC)是实现精准音频数字化的关键。GC1808,一款96kHz、24bit立体声音频ADC,以其卓越的性能和高性价比脱颖而出,成为众多音频设备制造商的理想选择。 GC1808集成了64倍…...

生产管理系统开发:专业软件开发公司的实践与思考
生产管理系统开发的关键点 在当前制造业智能化升级的转型背景下,生产管理系统开发正逐步成为企业优化生产流程的重要技术手段。不同行业、不同规模的企业在推进生产管理数字化转型过程中,面临的挑战存在显著差异。本文结合具体实践案例,分析…...