0. 屏保是个好项目!
先说个题外事——
屏幕保护程序的“保护”,有两种理解:
- 保护显示器,延续其老化;
- 保护屏幕上的显示内容。
显然,当 CRT (就是屁股大大的那种)退出历史舞台后,正确答案只能是是第二个:在你临时离开座位时,以为马上会回来,但其实拖了一段时间,于是你内心希望不要有人能看到你离开时,电脑屏幕上的内容……
现实生活中,已经越来越少人使用屏幕保护,但丝毫不改变,动作写屏幕保护程序,是一个非常好的 GUI 编程实践项目。
事实上,如果你的女朋友有电脑——我相信她有,但有些担心你没有女朋友——你完全可以为她写一个屏保护程序,借助屏保的内容,向她示爱……
一个 Windows 系统下的屏幕保护程序,最主要的功能是:当系统需要时(典型如系统空闲达到指定时长)并启动我们的屏保程序时,程序能够以全屏、置顶的方式,覆盖当前用户拥有的,所有显示器屏幕上 (毕竟,工作中拥有多台显示器的人越来越多了,特别是程序员),并能在接受到用户的鼠标、键盘输入后,迅速退出。
很多讲屏保程序编写的文章或教程,会只讲到这里。确实,这称得上是一个屏幕保护程序的主体功能,并且对应的实现代码“很干净”,跨平台。它能让我们学习或复习 wxWidgets 实现窗体可定制的绘图,包括颜色的生成、文本尺寸计算与输出,以及定时器的知识,并将各个技术点完整的组织起来,实现一个真实的可用的事物——屏保程序。
不过,我们还附加实现了 Windows 操作系统下,更加专业的教学内容:实现将我们写的屏保程序,和 Windows 系统提供的屏保设置界面结合起来。如果你正好使用的是 Windows 系统,那么这一块也许你也会感兴趣,但这并不是重点!
重点是,相比干净的主体业务,一个系统往往会有大量的附加功能,会显得很脏——在实际工作中,往往会表现为:你花了 10% 的时间完成一个系统最主要的, 90% 的功能,心里以为工期可以提前结束——结果,余下的 10% 的杂七杂八的事,最终费了你 90% 的时间……哦,我们说这个只是为了只为吐槽工作吗?不是,这种“破事”往往只能尽量减轻,很难完全避免,因此,任何一个想要走向工作岗位编程学习者,都应该早点真实接触、经历这样的事——永远只做“干净”的那 10%,要么这软件公司是你开的,要么,你就是只想在实验室里写代码……
尽管是一个非常好的教学案例项目,但我们并没有对这个项目做过份的提纯处理——提纯在这里的意思是:为了教学方便,而特意将实际编程中其实很难避免的小差错都“涂抹”掉,搞得像卖产品时的 “演示” 版。既然是实践项目,我们认为让大家有机会看到一个“老手”写程序时犯错和改错的过程,也有它的教学意义。
把分三个视频(总长接近 100 分钟,但几乎没有废话)展现,依据功能实现过程,依次是:
- 屏保的核心功能 —— 即上述的主体功能,完成后即可在 Windows 系统中实际使用;
- 屏保的小样示例功能 —— 让我们的程序可以在 Windows 的屏幕保护设置对话框上的那台“小显器”中显示小样内容;
- 屏保的配置功能 —— 用户选用我们的屏保后,可以通过Windows 的屏幕保护设置对话框上的“设置”按钮,配置该屏保。
其中两项附加功能相关视频,是收费的。5 块钱上下。除了完整三个视频之外,课文后还有主要代码,以及有作业(交卷后,老师会批改,回复)。
1. 屏保主体功能
2. 集成到 Windows
2.1 小样显示功能
第二段视频以及文字教程,我们用来实现如下效果的功能(注意图中的小显示器内显示的内容):
2.2 屏保设置功能
Code::Blocks 有一件事做得非常棒,它支持一个 wxWidgets 项目,仅部分窗体使用它自带的 wxSmith GUI 设计器 (而不是要求整个项目非此即彼)。
在第三个视频中,我们在学习屏保设置功能并与 Windows 系统的设置对话框如何集成时,也将快速掌握如何用 wxSmith 通过鼠标拖拖拉拉,设计出布局良好的图形用户界面(对话框),如下图:
- 设计页面:
3. 附加功能涉及知识点
知识点 | 示例代码 |
---|---|
01. wxWidgets 命令行参数简单判断 | arg.StartsWith(…) |
02. 见证与实践:在可复用性上,自由函数 > 成员函数的实例 | OnPaint(wxPaintEvent&) -> DoOnPaint(wxWindow*, wxPaintEvent&) |
03. 见证与实践:通过方法访问数据,可以更好地应对需求变化 | wxFont GetSloganFont() { if … else … } |
04. 如何纯手工写一个 wxWindow 的派生类 | class MyScreenSaverDemoWindow : public wxWindow |
05. wxWidget 如何让我们几乎无感地,完成读写 Windows 注册表 | config.Write(“Family”, family) |
06. C++ cast 的应用 | reinterpret_cast<WXHWND>(hwndParent) |
07. 通过Windows API 取得窗口的“祖宗” | ::GetAncestor(…) |
08. 如何把我们用wxWidget写的窗口,合丝无缝地嵌入微软程序员写的原生窗口中? | parentWindow->GetSize() |
09. lambda 的一处实际应用 | auto restore = [] (wxWindow* ptr) { … } |
10. 不得不用的 decltype | decltype(restore) |
11. 定制 unique_ptr 的释放器,实现任意RAII行为 | std::unique_ptr<wxWindow, decltype(f)> restoreGuard(&wnd, f); |
12. 为何以及如何将系统原生窗口,临时升级至 wxWindow ? | parentWindow->AssociateHandle(parentHWND) |
13. 如何在不是我们创建的系统窗口上,模拟弹出模态对话框? | parentWindow->Disable() |
14. 这个能嵌套+横竖的布局器,就是至简而无敌的布局器! | wxBoxSizer |
15. 学两个布局属性,就能胜任 99.9% 的窗口界面设计? | Expant、Proportion |
16. 如何使用 wxWidgets 的附加高级控件,比如超链接? | wxHyperlinkCtrl |
17. 如何让用户选择字体? | wxFontDialog |
18. 为什么一行代码未写,就拥有了一个“取消”按钮? | wxID_CANCEL |
19. 限制输入框的最大字符数? | Max length |
20. wxString::Trim() 和 ToLow() 方法的区别? | number.Trim() |
…… | … |
以下数据和学习无关,但是,现在是一个视频资源极大丰富的时代,如果你好奇,课程视频剪辑的大概工作量,此处附上本课数据。
Core(主体功能)37 分钟,Demo 成品视频长 20 分钟,Config 成品视频长 38 分钟,合计 95 分钟。
- 以 Config 为例:
- 项目准备 + PPT 制作 1.5 小时
- 原始视频录制 2 小时;
- 剪片,第一轮,3 小时
- 剪片,画面效果 2 小时
- 配字幕(已经使用AI的情况下)1 小时
- 复查及调整 2 小时
所以,最终时长 37 + 20 + 38 = 95 分钟的视频,大概是一个人坐电脑 30 小时无薪工作,算不上轻松——当然,最主要是你得觉得课程对你有帮助,请有学习需要,并觉得课程适合的网友,多支持小站。本课剩余内容不到 5 元,如果你之前常签到,还可积分兑换 1 元,实际扣费 4 元。