Thanks to visit codestin.com
Credit goes to github.com

Skip to content

kobolingfeng/qiangqiang

Repository files navigation

强强 (QiangQiang)

English | 中文 | LinuxDO


❤️ 这个项目由一个人利用业余时间开发和维护。如果它对你有用,请考虑赞助或贡献代码,让这个项目能继续发展下去!

PayPal 赞助

微信赞赏码

🙏 欢迎贡献! 无论是提 Issue、提交 PR、完善文档还是分享使用经验,都非常欢迎。一个人的精力有限,希望能和更多人一起把强强做得更好。


超轻量 Windows 桌面应用框架。C++ Win32 + WebView2 + Bun + TypeScript。

884KB 单 exe,90 个原生 API,零运行时依赖(WebView2 已内置于 Windows 10/11)。

特性

  • 极小体积 — 单 exe 884KB(含嵌入 HTML/JS/Config),无需任何外部文件
  • 极快编译 — 单文件 C++,增量编译 < 2s
  • 完整 API — 90 个原生命令 + 15 个事件 + 完整 TypeScript 类型
  • 真无边框窗口 — Composition 模式 WebView2(和 Wails/Tauri 同级),零像素边框 + DWM 阴影
  • 原生窗口动画 — 最小化、最大化、还原、打开、关闭走 Win32/DWM 过渡动画
  • Win11 主题联动 — 自动跟随系统深浅色和强调色,同步 DWM 边框与前端 CSS 变量
  • 文件查看器示例 — 默认示例已升级为桌面文件查看器,支持目录浏览、过滤、文本预览和属性面板
  • 热重载开发bun run dev 一键启动,支持 Vite HMR / 内置 Bun 热重载
  • 零依赖 — 不需要 Node.js、Electron、Tauri 等
  • 单 exe 分发bun run build:single,pak 打包 + 内存资源拦截,支持 Vite 多文件产物
  • 前端自由 — 支持 Vite / React / Vue / Svelte / Solid / 原生 TS,配置化接入
  • 仅 Windows — 专注 Windows 平台,API 直达系统底层

快速开始

前置要求

安装

bun install
bun run setup    # 下载 WebView2 SDK + JSON 库

开发

bun run dev      # 热重载开发模式(F12 打开 DevTools)

构建

bun run build            # 编译前端 + 原生壳
bun run build:native     # 仅编译原生壳(改了 main.cpp 时用)
bun run build:frontend   # 仅编译前端
bun run build:single     # 编译单 exe(HTML/JS 嵌入资源段)

打包

bun run package  # 生成 release/强强文件查看器-portable.zip
bun run package:single  # 生成 release/强强文件查看器-single.zip(仅包含单 exe)

内置示例:文件查看器

当前 src/ 默认实现了一个可直接运行的文件查看器应用,用来展示强强的窗口动画、系统主题联动和文件系统 API:

  • 左侧目录文件列表,支持过滤、排序、上一级和刷新
  • 中间文本/代码预览,支持常见源码、Markdown、JSON、日志等文本文件
  • 右侧属性面板,显示路径、类型、大小、修改时间
  • 支持系统对话框打开文件/文件夹、外部打开和资源管理器定位
  • 跟随 Windows 11 深浅色与强调色变化

使用 Vite / Vue / React

强强默认使用 Bun 打包前端。如果你想用 Vite + Vue/React,只需在 app.config.json 中配置:

{
    "dev": {
        "command": "npx vite",
        "port": 5173,
        "waitForPort": true
    },
    "build": {
        "command": "npx vite build"
    }
}

3 步接入 Vite + Vue:

# 1. 初始化 Vue 项目
bun create vite src --template vue-ts
# 2. 在 app.config.json 加上 dev.command 和 build.command
# 3. 开发
bun run dev

dev.commandbuild.command 支持任何命令(Vite、Webpack、Parcel 等)。不配置则走内置 Bun 打包。

API 总览

窗口管理 (16 命令 + 9 事件)

import { win } from './api';

await win.setTitle('我的应用');
await win.setSize(1280, 720);
await win.center();
await win.maximize();
await win.setAlwaysOnTop(true);
await win.startDrag();  // 自定义标题栏拖拽
await win.setBackgroundColor('#1a1a2e');  // 动态切换主题时同步 DWM 边框色
await win.setEffect('mica');  // Windows 11 Mica / Acrylic 特效

// 事件监听
win.onResized(({ w, h }) => console.log(`${w}×${h}`));
win.onFocus(() => console.log('获得焦点'));
win.onFileDrop(({ files }) => console.log('拖入文件:', files));

对话框 (5 命令)

import { dialog } from './api';

const path = await dialog.openFile({
    filters: [{ name: '图片', extensions: ['png', 'jpg'] }],
    multiple: true
});
const savePath = await dialog.saveFile({ defaultName: 'output.txt' });
const ok = await dialog.confirm('确认', '是否继续?');

文件系统 (8 命令)

import { fs } from './api';

const content = await fs.readTextFile('C:\\data\\config.json');
await fs.writeTextFile('C:\\data\\output.txt', 'Hello');
const entries = await fs.readDir('C:\\Users');
const stat = await fs.stat('C:\\Windows\\notepad.exe');

HTTP 客户端 (绕过 CORS)

import { http } from './api';

const res = await http.get('https://api.github.com/repos/user/repo');
console.log(JSON.parse(res.body));

const res2 = await http.post('https://httpbin.org/post', 
    JSON.stringify({ key: 'value' }),
    { 'Content-Type': 'application/json' }
);

全局快捷键

import { hotkey, MOD, VK } from './api';

await hotkey.register(1, MOD.CONTROL | MOD.SHIFT, VK.A);
hotkey.onTriggered(({ id }) => {
    if (id === 1) console.log('Ctrl+Shift+A 触发!');
});

右键菜单

import { menu } from './api';

const idx = await menu.popup([
    { label: '复制' },
    { label: '粘贴' },
    '-',  // 分隔线
    { label: '删除', disabled: true },
]);
if (idx === 0) { /* 复制 */ }

系统托盘

import { tray } from './api';

await tray.create('我的应用');
tray.onClick(() => win.show());
tray.onRightClick(async () => {
    const idx = await menu.popup([
        { label: '显示' },
        { label: '退出' },
    ]);
    if (idx === 1) app.exit();
});

系统通知

import { notification } from './api';

await notification.show('下载完成', '文件已保存到桌面');

文件监听

import { watcher } from './api';

const id = await watcher.start('C:\\my-project\\src');
watcher.onChange(({ action, path }) => {
    console.log(`${action}: ${path}`);
});
// 不需要时停止
await watcher.stop(id);

注册表

import { registry } from './api';

// 读写注册表
const value = await registry.read('HKCU', 'Software\\MyApp', 'setting');
await registry.write('HKCU', 'Software\\MyApp', 'setting', 'hello');
await registry.delete('HKCU', 'Software\\MyApp', 'setting');
const exists = await registry.exists('HKCU', 'Software\\MyApp');

深度链接

import { protocol } from './api';

// 注册自定义 URL 协议 → myapp://action/param
await protocol.register('myapp', '我的应用协议');
// 取消注册
await protocol.unregister('myapp');

日志系统

import { log } from './api';

await log.setFile();  // 默认 data/app.log
await log.info('应用已启动');
await log.warn('配置缺失');
await log.error('操作失败');

其他 API

import { os, path, env, clipboard, shell, devtools } from './api';

// 系统信息
await os.version();   // "10.0.22631"
await os.hostname();  // "MY-PC"
await os.username();  // "admin"
await os.locale();    // "zh-CN"

// 特殊目录
await path.home();       // "C:\Users\admin"
await path.documents();  // "C:\Users\admin\Documents"
await path.downloads();  // "C:\Users\admin\Downloads"
await path.desktop();    // "C:\Users\admin\Desktop"
await path.temp();       // "C:\Users\admin\AppData\Local\Temp\"

// 环境变量
await env.get('PATH');
await env.getAll();

// 剪贴板
await clipboard.writeText('Hello!');
const text = await clipboard.readText();

// Shell
await shell.open('https://github.com');
await shell.execute('notepad.exe', ['file.txt']);

// DevTools (开发模式)
await devtools.open();

配置文件

app.config.json:

{
    "window": {
        "title": "我的应用",
        "width": 1024,
        "height": 768,
        "minWidth": 400,
        "minHeight": 300,
        "frameless": true,
        "titleBarHeight": 40,
        "borderSize": 6,
        "backgroundColor": "#1a1a2e",
        "followSystemTheme": true,
        "lightBackgroundColor": "#f6f6f9",
        "darkBackgroundColor": "#1a1a2e",
        "singleInstance": true,
        "splash": true
    },
    "dev": {
        "port": 3000,
        "command": "npx vite",
        "waitForPort": true
    },
    "build": {
        "command": "npx vite build",
        "outDir": "dist"
    }
}
字段 说明
frameless 启用无边框 Composition 模式(WebView2 填满窗口,零边框)
borderSize 窗口边缘 resize 手柄的 hit-test 宽度(像素)
backgroundColor 窗口默认背景色
followSystemTheme 跟随 Windows 主题深浅色和强调色变化
lightBackgroundColor / darkBackgroundColor 跟随系统主题时的亮色/暗色窗口背景
dev.command 自定义开发服务器命令(Vite、Webpack 等),不设则用内置 Bun
build.command 自定义构建命令,不设则用内置 Bun
window.effect 窗口特效:"none" "mica" "acrylic" "micaAlt"(Win11)

项目结构

├── native/
│   ├── main.cpp        # C++ 壳(WebView2 Composition 模式)
│   ├── app.rc          # 资源文件
│   └── app.ico         # 应用图标(替换此文件自定义图标)
├── src/
│   ├── ipc.ts          # IPC 通信桥
│   ├── api.ts          # 全部 90 个命令的 TypeScript 类型封装
│   ├── main.ts         # 文件查看器示例前端
│   └── index.html      # 入口页面
├── scripts/
│   ├── setup.ts        # 下载依赖
│   ├── build.ts        # 编译前端 + 原生壳
│   ├── dev.ts          # 开发服务器 + 热重载
│   └── package.ts      # 打包
├── app.config.json     # 应用配置
└── package.json

IPC 协议

前端通过 window.chrome.webview.postMessage 与原生壳通信:

请求: { id: number, cmd: string, args: object }
响应: { id: number, result: any } | { id: number, error: string }
事件: { event: string, data: any }

全部命令列表 (88 个)

分类 命令 说明
窗口 window.setTitle window.minimize window.maximize window.restore window.close window.show window.hide window.size window.setSize window.position window.setPosition window.center window.setAlwaysOnTop window.isMaximized window.setBackgroundColor window.setEffect window.setOpacity window.setProgress window.startDrag window.isFrameless 窗口管理
多窗口 window.createChild window.closeChild window.listChildren 子窗口
窗口配置 window.getConfig window.saveState window.loadState 配置 + 持久化
对话框 dialog.openFile dialog.saveFile dialog.openFolder dialog.message dialog.confirm 系统对话框
文件系统 fs.readTextFile fs.writeTextFile fs.exists fs.readDir fs.mkdir fs.remove fs.rename fs.stat 文件操作
剪贴板 clipboard.readText clipboard.writeText 剪贴板
Shell shell.open shell.execute shell.run Shell 操作
应用 app.exit app.dataDir app.checkUpdate app.downloadUpdate app.installUpdate 应用控制
托盘 tray.create tray.setTooltip tray.remove 系统托盘
环境变量 env.get env.getAll 环境变量
快捷键 hotkey.register hotkey.unregister hotkey.unregisterAll 全局热键
通知 notification.show 系统通知
菜单 menu.popup 右键菜单
HTTP http.request 原生 HTTP (绕过 CORS)
OS os.platform os.arch os.version os.hostname os.username os.locale os.isDarkMode os.theme os.accentColor 系统信息
路径 path.home path.documents path.desktop path.downloads path.appData path.localAppData path.temp 特殊目录
文件监听 watcher.start watcher.stop 文件系统监听
DevTools devtools.open devtools.close 开发者工具
注册表 registry.read registry.write registry.delete registry.exists Windows Registry
深度链接 protocol.register protocol.unregister 自定义 URL 协议
日志 log.setFile log.write log.clear log.getPath 结构化日志

事件列表

事件 数据 说明
window.focus 窗口获得焦点
window.blur 窗口失去焦点
window.maximized 窗口最大化
window.minimized 窗口最小化
window.restored 窗口还原
window.resized { w, h } 窗口大小改变
window.moved { x, y } 窗口位置改变
window.closing 窗口即将关闭
window.fileDrop { files, x, y } 文件拖放到窗口
hotkey.triggered { id } 全局快捷键触发
watcher.changed { id, action, path } 文件变更
window.childClosed { id } 子窗口关闭
tray.click 托盘单击
tray.doubleClick 托盘双击
tray.rightClick 托盘右击

安全权限

通过 permissions 配置限制前端可调用的 API:

{
    "permissions": {
        "registry.*": false,
        "shell.execute": false,
        "fs.*": true
    }
}

支持命名空间通配符(fs.* 匹配所有 fs.xxx 命令)。未列出的命令默认允许。

自动更新

import { app } from './api';

const info = await app.checkUpdate('https://example.com/version.json');
if (info.version > currentVersion) {
    await app.downloadUpdate(info.downloadUrl);
    await app.installUpdate(); // 热替换 exe 并重启
}

多窗口

import { win } from './api';

const id = await win.createChild({
    title: '设置',
    width: 500,
    height: 400,
    url: 'https://app.local/settings.html'
});
win.onChildClosed(({ id }) => console.log('关闭:', id));
await win.closeChild(id);

系统主题 & 窗口控制

import { os, win } from './api';

// 检测系统暗色模式
const dark = await os.isDarkMode();

// 读取并监听 Windows 主题/强调色
const theme = await os.theme();
os.onThemeChanged((theme) => {
    document.documentElement.style.setProperty('--accent', theme.accentColor);
    win.setBackgroundColor(theme.backgroundColor);
});

// 窗口透明度 (0.0 ~ 1.0)
await win.setOpacity(0.9);

// 任务栏进度条 (-1 隐藏, 0~1 进度)
await win.setProgress(0.5);
await win.setProgress(-1); // 隐藏

// 执行命令并获取输出
import { shell } from './api';
const { exitCode, stdout, stderr } = await shell.run('git', ['status']);

CSS 拖拽区域

支持 CSS app-region 属性,无需手动调用 window.startDrag()

.titlebar {
    app-region: drag;        /* 可拖拽区域 */
}
.titlebar button {
    app-region: no-drag;     /* 按钮等交互元素排除 */
}

窗口特效

Windows 11 支持 Mica / Acrylic 材质特效:

{
    "window": {
        "effect": "mica"
    }
}

或运行时切换:

await win.setEffect('mica');     // Mica 材质
await win.setEffect('acrylic');  // Acrylic 亚克力
await win.setEffect('micaAlt');  // MicaAlt (标签页风格)
await win.setEffect('none');     // 关闭特效

使用特效时,WebView2 背景自动设为透明。前端 CSS 需要用 background: transparent 或半透明色才能看到效果。

自定义图标

替换 native/app.ico 为你的图标文件,重新 bun run build 即可。

推荐包含以下尺寸:16×16, 32×32, 48×48, 256×256。

对比

强强 Wails Tauri Electron
单 exe 大小 884 KB ~9 MB ~2 MB ~120 MB
内存占用 ~30 MB ~50 MB ~40 MB ~150 MB
启动速度 ~0.5s ~1s ~0.5s ~2s
编译速度 ~2s ~10s ~10s N/A
跨平台 仅 Windows
前端自由度 完全自由 完全自由 完全自由 完全自由
原生 API 88 个 ~30+ ~70+ ~50+
单 exe 分发
运行时开销 零(纯 C++) Go 运行时 ~5MB Rust 运行时 ~2MB Chromium
资源加载 零拷贝内存映射 Go embed include_bytes! asar

以上数据基于同一个 Vue 3 前端应用(墨线编辑器)的对比测试。

示例应用

examples/墨线.exe — 一个基于强强构建的 Markdown 编辑器,仅 884 KB 单 exe。双击即可运行(需要 Windows 10/11)。

同样的应用使用 Wails 构建单文件需要 ~9 MB,强强仅需不到 1/10 的体积,同时启动更快、内存占用更少。

License

MIT

About

超轻量 Windows 桌面应用框架 | Ultra-lightweight Windows desktop app framework. C++ Win32 + WebView2 + Bun + TypeScript. 638KB exe, 66 native APIs.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors