C++ Saucer 编写Windows桌面应用

news2025/7/27 14:50:55

文章目录

  • 一、背景
  • 二、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.html
     DESTINATION ${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目标视图,可以看到这个项目:
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.html
     DESTINATION ${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技术的高效界面开发能力,实现真正的"一次编写,多平台运行"。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2406433.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【AI News | 20250609】每日AI进展

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

轻量安全的密码管理工具Vaultwarden

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

SQLSERVER-DB操作记录

在SQL Server中&#xff0c;将查询结果放入一张新表可以通过几种方法实现。 方法1&#xff1a;使用SELECT INTO语句 SELECT INTO 语句可以直接将查询结果作为一个新表创建出来。这个新表的结构&#xff08;包括列名和数据类型&#xff09;将与查询结果匹配。 SELECT * INTO 新…

开疆智能Ethernet/IP转Modbus网关连接鸣志步进电机驱动器配置案例

在工业自动化控制系统中&#xff0c;常常会遇到不同品牌和通信协议的设备需要协同工作的情况。本案例中&#xff0c;客户现场采用了 罗克韦尔PLC&#xff0c;但需要控制的变频器仅支持 ModbusRTU 协议。为了实现PLC 对变频器的有效控制与监控&#xff0c;引入了开疆智能Etherne…

NineData数据库DevOps功能全面支持百度智能云向量数据库 VectorDB,助力企业 AI 应用高效落地

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

代理服务器-LVS的3种模式与调度算法

作者介绍&#xff1a;简历上没有一个精通的运维工程师。请点击上方的蓝色《运维小路》关注我&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 我们上一章介绍了Web服务器&#xff0c;其中以Nginx为主&#xff0c;本章我们来讲解几个代理软件&#xff1a…

解决MybatisPlus使用Druid1.2.11连接池查询PG数据库报Merge sql error的一种办法

目录 前言 一、问题重现 1、环境说明 2、重现步骤 3、错误信息 二、关于LATERAL 1、Lateral作用场景 2、在四至场景中使用 三、问题解决之道 1、源码追踪 2、关闭sql合并 3、改写处理SQL 四、总结 前言 在博客&#xff1a;【写在创作纪念日】基于SpringBoot和PostG…

使用VMware克隆功能快速搭建集群

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

篇章一 论坛系统——前置知识

目录 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 建立用例模型 …

Qt/C++学习系列之列表使用记录

Qt/C学习系列之列表使用记录 前言列表的初始化界面初始化设置名称获取简单设置 单元格存储总结 前言 列表的使用主要基于QTableWidget控件&#xff0c;同步使用QTableWidgetItem进行单元格的设置&#xff0c;最后可以使用QAxObject进行单元格的数据读出将数据进行存储。接下来…

基于django+vue的健身房管理系统-vue

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.8数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat12开发软件&#xff1a;PyCharm 系统展示 会员信息管理 员工信息管理 会员卡类型管理 健身项目管理 会员卡管理 摘要 健身房管理…

Yolo11改进策略:Block改进|FCM,特征互补映射模块|AAAI 2025|即插即用

1 论文信息 FBRT-YOLO&#xff08;Faster and Better for Real-Time Aerial Image Detection&#xff09;是由北京理工大学团队提出的专用于航拍图像实时目标检测的创新框架&#xff0c;发表于AAAI 2025。论文针对航拍场景中小目标检测的核心难题展开研究&#xff0c;重点解决…

简单聊下阿里云DNS劫持事件

阿里云域名被DNS劫持事件 事件总结 根据ICANN规则&#xff0c;域名注册商&#xff08;Verisign&#xff09;认定aliyuncs.com域名下的部分网站被用于非法活动&#xff08;如传播恶意软件&#xff09;&#xff1b;顶级域名DNS服务器将aliyuncs.com域名的DNS记录统一解析到shado…

循环语句之while

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

机器学习复习3--模型评估

误差与过拟合 我们将学习器对样本的实际预测结果与样本的真实值之间的差异称为&#xff1a;误差&#xff08;error&#xff09;。 误差定义&#xff1a; ①在训练集上的误差称为训练误差&#xff08;training error&#xff09;或经验误差&#xff08;empirical error&#x…

联邦学习带宽资源分配

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

今日行情明日机会——20250609

上证指数放量上涨&#xff0c;接近3400点&#xff0c;个股涨多跌少。 深证放量上涨&#xff0c;但有个小上影线&#xff0c;相对上证走势更弱。 2025年6月9日涨停股主要行业方向分析&#xff08;基于最新图片数据&#xff09; 1. 医药&#xff08;11家涨停&#xff09; 代表标…

GC1808:高性能音频ADC的卓越之选

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

生产管理系统开发:专业软件开发公司的实践与思考

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

VASP软件在第一性原理计算中的应用-测试GO

VASP软件在第一性原理计算中的应用 VASP是由维也纳大学Hafner小组开发的一款功能强大的第一性原理计算软件&#xff0c;广泛应用于材料科学、凝聚态物理、化学和纳米技术等领域。 VASP的核心功能与应用 1. 电子结构计算 VASP最突出的功能是进行高精度的电子结构计算&#xff…