在《
Windows编程
》中,我们讲解了如何使用 Windows API 来创建控件,例如按钮、静态文本框、编辑框等,这些控件是 Windows 自带的,已经封装好了,只需要调用 API 即可。
Windows 支持的控件非常丰富,可以满足企业级应用程序的开发,Windows 本身也在使用这些控件。但这些控件是和 Windows 主题风格绑定的,比较传统,甚至略显丑陋,不能做出像QQ、360、迅雷等如此漂亮的界面。由于这些控件已经封装好了,想要修改它们的样式和行为非常困难,甚至无能为力。
如果不希望使用系统自带的控件,就必须自己完成控件的绘制,并为它们绑定事件,例如鼠标点击时改变颜色、鼠标移入是切换 Tab等。这些是非常复杂的工作,不但要保证控件尽量丰富、行为易于理解、样式便于修改等,还要保证绘制的高效以及动画的流畅。
任何平台都提供了图形绘制函数,例如画点、画线、画面等,Qt 就是利用这些基本函数将所有控件画出来。不同操作系统的控件样式不同,有时甚至连行为都有所差异,考虑到跨平台,Qt 要模拟不同风格的控件,例如在 Windows 下的控件要尽量表现得像Windows原生控件,这样用户才不会觉得别扭,程序才更加 native。
其实,Qt 5 提供了两种控件的绘制方式:
1) 一种是上面所说的模拟原生控件,这种方式从 Qt 诞生以来就一直存在,程序员需要使用C++代码来创建界面、处理业务逻辑。虽然界面风格也比较传统,但控件样式容易修改。
2) 另外一种是 Qt 4.7 推出的 QML,使用它可以创建个性化的、大气漂亮的界面,例如QQ、360、迅雷等,适合现代的审美观。Qt 5 以后官方主推 QML。
QML 是 Qt 专门为界面设计推出的一种描述性的脚本语言,语法非常像CSS或JSON,但又支持JavaScript形式的编程控制。
QML 是解释执行的脚本语言,程序在执行时将 .qml 文件加载进去,解析完成后再渲染成界面。这虽然比编译成本地程序慢,但它的好处是更新界面时不需要重新编译和更新整个程序,只要加载新的 QML 文件就可以。
Windows 支持的控件非常丰富,可以满足企业级应用程序的开发,Windows 本身也在使用这些控件。但这些控件是和 Windows 主题风格绑定的,比较传统,甚至略显丑陋,不能做出像QQ、360、迅雷等如此漂亮的界面。由于这些控件已经封装好了,想要修改它们的样式和行为非常困难,甚至无能为力。
如果不希望使用系统自带的控件,就必须自己完成控件的绘制,并为它们绑定事件,例如鼠标点击时改变颜色、鼠标移入是切换 Tab等。这些是非常复杂的工作,不但要保证控件尽量丰富、行为易于理解、样式便于修改等,还要保证绘制的高效以及动画的流畅。
任何平台都提供了图形绘制函数,例如画点、画线、画面等,Qt 就是利用这些基本函数将所有控件画出来。不同操作系统的控件样式不同,有时甚至连行为都有所差异,考虑到跨平台,Qt 要模拟不同风格的控件,例如在 Windows 下的控件要尽量表现得像Windows原生控件,这样用户才不会觉得别扭,程序才更加 native。
其实,Qt 5 提供了两种控件的绘制方式:
1) 一种是上面所说的模拟原生控件,这种方式从 Qt 诞生以来就一直存在,程序员需要使用C++代码来创建界面、处理业务逻辑。虽然界面风格也比较传统,但控件样式容易修改。
2) 另外一种是 Qt 4.7 推出的 QML,使用它可以创建个性化的、大气漂亮的界面,例如QQ、360、迅雷等,适合现代的审美观。Qt 5 以后官方主推 QML。
QML 是 Qt 专门为界面设计推出的一种描述性的脚本语言,语法非常像CSS或JSON,但又支持JavaScript形式的编程控制。
如果你有Web开发经验,将很容易理解 QML,甚至会感到欣喜和熟悉;如果没有,上面的解释你可能感到晦涩,不过没关系,后续会详细讲解。这种方式使前端和后台分开:QML 用来创建界面和处理事件,完成“用户看得到”的工作;C++ 用来处理业务逻辑,完成“用户看不到”的工作。
QML 是解释执行的脚本语言,程序在执行时将 .qml 文件加载进去,解析完成后再渲染成界面。这虽然比编译成本地程序慢,但它的好处是更新界面时不需要重新编译和更新整个程序,只要加载新的 QML 文件就可以。
QML 和 JavaScript 虽然都是解释执行的脚本语言,但没有想象中的那么慢。浏览器渲染网页就是采用的这种机制,几乎是瞬间完成的,大家可以放心使用。下面,我们使用 Windows API 来自己绘制一个简单的按钮控件,让它响应鼠标点击事件。代码如下:
- #include <windows.h>
- LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
- int WINAPI WinMain(
- HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- PSTR szCmdLine,
- int iCmdShow
- ){
- static TCHAR szClassName[] = TEXT("HelloWin"); //窗口类名