发帖时提示:主题内容不能超过 20000 个字符,故拆成〖上、下〗两篇;此文为下篇
番外:意料之外
分享一下喜悦
在 v1.3 发布的那天晚上,记得 downloads 是 900+ 的样子;发布完了就去睡觉了。
第二天早上一看下载量就是 1k ,1.1k ;中午再看一眼就是 1.2k ;晚上再看就是 1.3k ;
第三天是 1.4k ,
第四天是 1.5k ,
... ...哈哈哈哈哈哈哈哈哈, 放假回家过年了,也没怎么看
约大大前天回来一看,嗯,还是 1.5k ,大家玩的开心愉快
大前天到了 1.6k
前天到了 1.7k
昨天号到了 1.7k
今天的到了 1.8k , 纪念打卡(--写这篇时)
在写过的所有软件中,总的下载量虽然不是最大的,但短时间增速率长是最快的 ヾ(≧▽≦*)o 。
截图作品系列
很久之前就想些一个软件截图的软件,目前一共写如下三个层级的难度作品,提供大家参考
[td]项目[/td]
[td]描述[/td]
[td]开发经验[/td]
ShotX
功能极简的截图工具
简易,新手级的截图,适合初学 Qt/C++ 入门
FLIPPED
简洁且漂亮,功能完整的截图软件;隐私安全,无任何联网功能
高级难度,属 Qt/C++ 数年经验的进阶作品,在借鉴同类作品的代码时,可于探索中独立完成的一个大的软件
Sunny
一款简洁且漂亮的截图的软件工具。亦支持图片翻译和 OCR ;已上架微软商店,深度/统信商店,及三方的星火商店等
专业级作品,适合已多年沉浸研究 Qt/C++ 经验,随心所欲写任意所需功能,属于商业级的成熟作品,是本截图系列的最高水准之作
Ⅰ. 新手之作 ShotX
Ⅱ. 高级之作 FLIPPED
Ⅲ. 商业级别的成熟之作 Sunny (推荐)
注: ShotX ,FLIPPED ,Sunny 这三款均支持跨平台 Windows / MacOS / Linux 。
Sunny = FLIPPED 的功能重构 + 代码重构 + UI 重构 + 网络功能(图片翻译+OCR )+ 上架应用商店 + 后续新功能;而 ShotX 是最早的练手探索
如何开发一款截图软件呢?
在写和发布的后的期间,也遇到很多私聊请教 、 邮件沟通某个功能实现?反馈 Bug 和给出使用心得和建议;都给答疑了,但想来可写为一整篇,中间遇到的困难点都写出来,公开出来提供后来者参考。
编译环境
💻 MacOS 13 📎 Qt 5.15.2 📎 gcc/g++ 9.2 📎 gdb8.3
💻 Ubuntu 22.04 📎Deepin 20.9-23+ 📎 Qt 5.15.2 📎 gcc/g++ 9.0 📎 gdb8.0
💻 win10 22H2 📎 Qt 5.15.2 📎 Visual Studio 2022 📎 C++17
[整体思路]
功能思路: 时刻判断当前所处模式:Wait / Select / Move / Draw / Stretch 标记;根据模式标记,对鼠标的 Press / Move / Release 事件进行对应的操作;重点是鼠标放下和松开时的 QPoint
[如何购买代码签名]
『问题』写的 EXE 如何进行代码签名?如何购买代码签名,怎么买最便宜? EV / Standard / Open Source Signing Certificates 的区别是什么?
详细解答这些问题 《分享如何拥有一份私人的『开源代码签名证书』》,并且指导最后如何签名。
[如何上架应用商城]
『问题』如何上架到微软的 Microsoft Store ?如何上架 Linux 的深度/统信/麒麟商城,以及如三方的星火商店呢?
篇幅太长,单写了一篇,包含详细上架 Windows Store ,Deepin/UOS Store, 三方 星火商店等。
👉 《Sunny 截图上架 Microsoft Store 及 Linux 商店流程的指北》
Note:
个人作品上架微软商店的流程很折磨,最后上架成功后也是拨开云雾;
若是文章对你有价值,亦可帮我积累 Sunny 的微软信誉,或者在深度商店的好评,甚至感谢🙇 ;
Windows 用户推荐的下载 👉 Sunny_setup_msvc_1.3.0_x64.exe
[打包发布 Windows / MacOS / Linux 上]
介绍多种平台和格式:①Windows:绿色便携版和安装包 .exe ②MacOS:.app 和 .img ③Linux: 绿色版、 .deb 和 .AppImage
『问题』 Windows 如何构建打包为 .exe 文件?如何生成构绿色版和安装版?
《QT 项目在 Windows 平台上面发布成可执行程序》
『问题』 MacOS 如何构建打包为 .dmg 文件?
《QT 项目在 MacOS 平台上面发布成可执行程序》
『问题』 Linux 如何构建打包为 .deb 文件、如何打包为通用的 .AppImage 格式?
Linux 下又多种打包 .deb 打包方法:
〖方法一〗通过 ldd.sh + Sunny.sh 两个脚本打包依赖,参考《QT 项目在 Linux 平台上面发布成可执行程序》
〖方法二〗通过 dh_make + dpkg-buildpackage 命令《Linux 中用 dh_make 将 Qt + CMake 项目打包为 deb 文件》
〖方法三,最推荐〗通过 CMake 的 cpack 命令,那样就不需要填写 debian 文件夹下的 control 等文件,直接拷贝相关资源文件过去。CMakeLists.txt 底部加上 CPack 的相关代码,核心如下:
# CPACK: General Settings
set (CPACK_GENERATOR "TBZ2")
set (CPACK_PACKAGE_NAME "${project_name}")
set (CPACK_PACKAGE_VERSION "${project_version}")
set (CPACK_PACKAGE_VENDOR "https://github.com/XMuli")
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Simple and beautiful screenshot software tool for Windows, MacOS and Linux")
set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
set (CPACK_PACKAGE_CONTACT "https://sunny.xmuli.tech")
# 设置 Debian 软件包的依赖关系
set (CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5x11extras5, libqt5svg5")
set (CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
set (CPACK_DEBIAN_PACKAGE_SHILIBDEPS ON)
include(CPack)
Linux 下有多种打包 .AppImage 打包方法
# [方式四] 使用 linuxdeployqt 方式打包,在 Ubuntu 22.04 打包,不可以使用 -----------------------------
####linuxdeployqt-continuous-x86_64.AppImage 方案可在 Ubuntu 22.04 上面不可行####
$ ../linuxdeployqt-continuous-x86_64.AppImage Sunny -appimage
$ sudo apt install libfuse2
但是由于过于作者的固执坚守旧的版本,所以无法使用,理由和可能的解决如下:
https://github.com/probonopd/linuxdeployqt/issues/340#issuecomment-932712016
即:使用 linuxdeploy 和 linuxdeploy-plugin-qt
#####linuxdeploy-x86_64.AppImage + linuxdeploy-plugin-qt-x86_64.AppImage 下面方案可行#####
https://github.com/BearKidsTeam/thplayer/blob/master/.github/workflows/linux.yml#L54
$ sudo apt update
$ sudo apt install qtbase5-dev qtmultimedia5-dev libqt5multimedia5-plugins
$ sudo add-apt-repository universe
$ sudo apt install libfuse2
$ wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
$ wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
$ chmod +x linuxdeploy*.AppImage
$ mkdir build && cd build
$ cmake ..
$ cmake --build . -j$(nproc)
$ cd ..
$ ../linuxdeploy-x86_64.AppImage --appdir AppDir -e bin/Sunny -d bin/resources/cpack/tech.xmuli.sunny.desktop -i bin/resources/logo/logo.svg --icon-filename tech.xmuli.sunny -p qt -o appimage
$ ./linuxdeploy-x86_64.AppImage --appdir AppDir -e build/thplayer -d assets/thplayer.desktop -i assets/thplayer.svg --icon-filename thplayer -p qt -o appimage
$ mv TouHou_Player*.AppImage thplayer-linux.AppImage
『问题』如何书写 .yml 的脚本,通过 GitHub 的 Action 资源,自动打包构建生成 Release 呢?
通过写三个系统的 .yml 脚本,路径必须是 .github/workflows ,随着时间的流逝⌛,想要持续构建对应的云系统和 Kit 也必须更新,文档和版本参见 images ,直接往 .yml 修改;这是一个实际可跑的脚本 *.yml 都是可以编译成功的,失败可能是额度时间不够了,如某次成功的示例,可看到头像是 GitHub 的头像发布的 Release-v6.1 ;
[ UI / UX 设计的效果]
『问题』截图的一级二级的菜单工具栏,如何实现 Windows7 的透明磨砂 / Windows 的亚克力的效果,且能够支持 Windows / Linux / MacOS ?
单纯实现亚克力效果不难,难在 Linux 和 MacOS 上也能实现这个效果?这是当时的一些探索和经验,总结了四种方法放置于 GitHub - AcrylicWindow
『问题』如何实现一个完美的无边框窗口跨平台,且还要占用低,没有瑕疵 BUG ,还能白嫖?
也折腾过,难度也很大,后来发现对于截图,费力可以实现,但是没必要,成本太大;结论:这样现成的没有,目前效果和跨平台都最佳的方案是framelesshelper, 有时放弃也是一种解决方案。
『问题』如何实现国际化多语言的切换?尤其是未使用 Qt Designer 来创建 .ui 文件,遇到无 ui->retranslateUi(this) 函数?不重启软件便可以切换语言
对于有有 .ui 的部分,可以通过 《Qt 项目(CMake)设置国际化支持》来解决。对于存手写的控件实现的,且大致实现的思路是:
下拉框中切换语言时,发射信号 → 全局单例 → 信号和槽函 → 到主窗口的槽函数,在里面进行重新加载语言,所有相关的控件的默认文本,都写在这个函数里面,便可以不重启软件,直接实现语言切换成功
[用户体验细节]
『问题』是否需要管理员权限才能运行?
全程不会弹 UAC 弹窗,不需要管理员权限就可以使用所有功能,也不会中途提权,仅普通用户权限即可,包括导向安装,静默安装,使用卸载;
『问题』 Windows 和 Linux 支持一次截多个屏幕,MacOS 仅只能截图单个屏幕,如何实现呢?
MacOS 除了系统自带的截图支持外,至今没有任何一个三方软件可以做到这点,包括大厂等某企鹅的截图的,无解。根原是属于此苹果接口没公开,至少没人能够发现。
『问题』如何确保 MacOS 上的效果和 Window 上面保持外观的一致?
一个难点是再 MacOS 上也要和再 Windows 的效果保持一致,于是对不同风格进行对比,但 Fusion 又会倒是 Setting 窗口非原生的样式,但好在十分接近;选取一个平衡点。另外还手绘画了一个二十多个自定义或者复杂控件。
[看不见的优化]
『问题』如何解决使用 ESC 取消截图后的内存泄露问题? QPointer 、智能指针、还是单例?
也花了大力气来探究,在完成一次截图之后,内存的占用会在合适时机自动释放出来;这是定位在消耗内存的变量;开发环境显示器为 4K 27 寸 + 3K 笔记本双屏;
『问题』对于使用单例模式不止一处时,有序需要多个单例用来传递或者保存数值时候,重复写很容易
可采用奇异递归模板的方式,然后添加一个宏展开为友元类;多个单例都只用写一份,而前提是需要对 《C++ 类的六个特殊成员函数》 很熟悉,才能理解,属于优雅的一种实现。
『问题』日志和崩溃生成 DUMP 记录?
日志可以通过配置文件修改,若是遇到传说的崩溃,亦会自动生成 .dmp 和 崩溃原因;
转储文件存放: C:/Users/用户名/AppData/Local/XMuli/Sunny/cache/Sunny_Dumps/dump_2024_02_29_11_31_30_714.dmp
实现方法可通过 WIN API 来实现
#ifdef _MSC_VER
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);//注冊异常捕获函数
#endif
额,你没接触过 DUMP ,完全不会对其进行解剖分析?也简单写了一个使用 WinDbg 进行入门
《WinDbg:入门分析 dmp 文件『一』》、《WinDbg:调试之附加进程生成 dmp 『二』》
『问题』希望单例运行 EXE ,确保全局唯一性?
可以通过共享内存 QSharedMemory 和系统信号量 QSystemSemaphore ,双重保证程序在一台终端上,仅会运行一个;
也能杜绝很罕见的一种情况,即使上次程序崩溃之后,但仍有残留的僵死进程,被误判当前没有启动。严谨(中指推一下眼镜)
QString uniqueKey = "SunnyUniqueKey"; // 使用唯一的标识符来创建共享内存和系统信号量
QSharedMemory sharedMemory;
sharedMemory.setKey(uniqueKey);
// 尝试附加到现有的共享内存并分离
if (sharedMemory.attach()) {
sharedMemory.detach();
}
// 尝试创建共享内存,如果已经存在,表示已经有一个实例在运行, 判断是为了确保在同一台计算机上只能运行一个相同实例的程序。
if (!sharedMemory.create(1)) {
qDebug()
[ Qt / C++ 编码问题]
『问题』截图项目运行直接置顶显示后,按下按键后,窗口无任何响应,需额外点击一下才能开始截图?
分析和解决方案《Qt 新弹窗不响应键盘按键,难道也是无焦点?》
『问题』热键输入框控件,输入后显示的方块 ■◆ 乱码?
分析和解决方案《创建 QKeySequenceEdit() 后,显示方块■◆乱码》,还是多看下 Qt Assistant 解围粗心。
『问题』使用 VS2022 和 QtCreator 如何调试 Qt 5.15 的源代码?
解决方案为《VS2022 And QtCreator10 调试 Qt 源码教程》、《VS2017 调试 Qt 源码》
『问题』截图会有很多个属性的校验和“且”的属性使用?
虽简单,但移除标志位容易忘却,这里简单列举一下《C++ 标志位使用:校验、添加、删除》
『问题』 Qt Creator 报警告⚠ Misleading indentation ; statement is not part of the previous ‘if‘
那日强迫症,且需要删除空格才能解决,属实比较稀少;记录下解决方案 《Misleading indentation ; statement is not part of the previous ‘if‘》
『问题』重构此版时候,也会大量使用 Lambda 表达式
展开讲解一下,若未接触过,属会用会看即可《Lambda 表达式详解》
『问题』 Visual Studio 断点偶遇进不去相关函数?
Release 实际也是可以调试的,新手容易不知晓,知晓的亦可能会翻车,值得记录下;属于 Release / Release with Debug Info / Debug 的差异《Visual Studio 断点调试之箭头偏移进错函数,捉虫记》
『问题』源码不能外发的情况下,如何进行调试?
详细示例《Visual Studio 2019 进行远程调试》
[项目杂项]
『问题』 Sunny 截图在在不同系统、编译器上开发、使用不同的 Kit Tools 上面如何解决乱码问题?且有时调试窗口乱码?还有 ANSI ,UTF8 ,UTF8-BOM 采用哪种?
参考《 愿编程不再乱码(含 Qt)-根因深究》,以及 QtExamples 的 "「第 6 章」 QT / IDE 乱码根因和解决"
『问题』 遇到需要使用的开源三方库,如何优雅的使用 Git 管理,确保拉取三方库即最新,又不会打乱本仓库的历史线?
开源三方库引入,想要优雅,基本 git submodule 或 git treemodule 命令之间二选一;推荐前者,理由为 《git submodule 基本用法》
『问题』 如何选用 LOG 日志库?自己简单封装一套,还是选用开源库?便于后面定位和分析
比较犹豫和纠结的一个问题,两种都试过;现总结为:项目初期使用自带的 QDebug 即,不够用再写一个类,和宏封装一套,满足需求即可,勿跑偏,功能才是重点。最后期可以选用三方库引入:
一点经验参考 《Log:日志选型调研『一』》、《Log:日志之 Spdlog 极简用法示范『二』》、《Log:日志之 Spdlog 核心构成『三』》
『问题』 CMake 管理跨平台项目,生各平台的 IDE 的解决方案?以及 Window 上自带一些基础宏的数据类型含义?
现在已经幸福多了,ChatGPT 横空出世,已经可以解答了,故介绍一些高频或者重点宏,自己结合去搜🔍
CMake 的重要宏:《CMake 设置 Target 输出目录和后缀名》、《CMake 之 BUILD_SHARED_LIBS 和 CMAKE_BUILD_TYPE 用法教程》
Windows 的重要宏:《LPSTR/LPCSTR/LPTSTR/HWND/HANDLE/HMODULE/HINSTANCE 等含义和区别》
系列地址
QtExamples 欢迎 star ⭐ 和 fork 🍴 这个系列的 C++ / QT / DTK 学习,附学习由浅入深的目录,这里你可以学到如何亲自编写这类软件的经验,这是一系列完整的教程,并且永久免费!