当前位置: 首页 > ops >正文

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

http://www.xdnf.cn/news/13086.html

相关文章:

  • AI——DeepSeek+LangChain+streamlit 实现智能汽车维修服务
  • 视觉slam十四讲实践部分记录——ch2、ch3
  • 字节开源代码模型——Seed-Coder 本地部署教程,模型自驱动数据筛选,让每行代码都精准落位!
  • ​第八章:漏洞里的人间烟火
  • Linux线程与进程关系及底层实现
  • 瑞数信息入选Gartner《中国API管理市场指南》
  • 亚马逊测评,采购环境安全需要解决哪些问题,提高成功率
  • 验证redis数据结构
  • 课堂笔记:吴恩达的AI课(AI FOR EVERYONE)-第一周part2 人工智能术语人工智能公司应该怎么做
  • 恶补电源:1.电桥
  • 【第一章:人工智能基础】01.Python基础及常用工具包-(3)常用数据科学工具包
  • 性能测试分析
  • 深度剖析Diffusion与Transformer在图像生成中的计算逻辑与融合之道
  • 火山引擎云服务器使用感怎么样
  • HarmonyOS运动开发:打造你的专属运动节拍器
  • python打卡day49
  • 大数据学习(135)-Linux系统性指令
  • Windows 环境下,使用 ESP32 JTAG 接口进行固件下载
  • 浅谈互联网主流通信协议
  • 【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
  • 【堆垛策略】设计方法
  • SAP软件年结科目余额结转详解
  • ShuffleNet 改进:与通道注意力机制(CAM)的结合实现
  • 如何用Coze+Fetch快速构建结构化文档
  • deepbayes lecture2:变分推断
  • 【实证分析】上市公司企业风险承担水平数据集(2000-2022年)
  • Houdini POP入门学习06 - 物理属性2
  • 十二、MySQL 8 新特性底层原理
  • 角色塑造江湖秘籍
  • 火绒弹窗拦截6.0.6.1\5.0.77.1绿色独立版_WinAll