基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(三)
1 引言
对话框编程是一个快速构建用户界面的技术。通常,我们编写简单的图形用户界面时,可以通过调用 CreateWindow 函数直接创建所有需要的子窗口,即控件。但在图形用户界面比较复杂的情况下,每建立一个控件就调用一次 CreateWindow 函数,并传递许多复杂参数的方法很不可取。主要原因之一,就是程序代码和用来建立控件的数据混在一起,不利于维护。为此,一般的 GUI 系统都会提供一种机制,利用这种机制,通过指定一个模板,GUI 系统就可以根据此模板建立相应的主窗口和控件。MiniGUI 也提供这种方法,通过建立对话框模板,就可以建立模态或者非模态的对话框。
本文首先讲解组成对话框的基础,即控件的基本概念,然后讲解对话模板的定义,并说明模态和非模态对话框之间的区别以及编程技术。
2 控件和控件类
许多人对控件(或者部件,widget)的概念已经相当熟悉了。控件可以理解为主窗口中的子窗口。这些子窗口的行为和主窗口一样,即能够接收键盘 和鼠标等外部输入,也可以在自己的区域内进行输出――只是它们的所有活动被限制在主窗口中。MiniGUI 也支持子窗口,并且可以在子窗口中嵌套建立子窗口。我们将 MiniGUI 中的所有子窗口均称为控件。
在 Windows 或 X Window 中,系统会预先定义一些控件类,当利用某个控件类创建控件之后,所有属于这个控件类的控件均会具有相同的行为和显示。利用这些技术,可以确保一致的人机操 作界面,而对程序员来讲,可以像搭积木一样地组建图形用户界面。MiniGUI 使用了控件类和控件的概念,并且可以方便地对已有控件进行重载,使得其有一些特殊效果。比如,需要建立一个只允许输入数字的编辑框时,就可以通过重载已有 编辑框而实现,而不需要重新编写一个新的控件类。
如果读者曾经编写过 Windows 应用程序的话,应该记得在建立一个窗口之前,必须确保系统中存在新窗口所对应的窗口类。在 Windows 中,程序所建立的每个窗口,都对应着某种窗口类。这一概念和面向对象编程中的类、对象的关系类似。借用面向对象的术语,Windows 中的每个窗口实际都是某个窗口类的一个实例。在 X Window 编程中,也有类似的概念,比如我们建立的每一个 Widget,实际都是某个 Widget 类的实例。
这样,如果程序需要建立一个窗口,就首先要确保选择正确的窗口类,因为每个窗口类决定了对应窗口实例的表象和行为。这里的表象指窗口的外观,比如窗 口边框宽度,是否有标题栏等等,行为指窗口对用户输入的响应。每一个 GUI 系统都会预定义一些窗口类,常见的有按钮、列表框、滚动条、编辑框等等。如果程序要建立的窗口很特殊,就需要首先注册一个窗口类,然后建立这个窗口类一个 实例。这样就大大提高了代码的可重用性。
在 MiniGUI 中,我们认为主窗口通常是一种比较特殊的窗口。因为主窗口代码的可重用性一般很低,如果按照通常的方式为每个主窗口注册一个窗口类的话,则会导致额外不必 要的存储空间,所以我们并没有在主窗口提供窗口类支持。但主窗口中的所有子窗口,即控件,均支持窗口类(控件类)的概念。MiniGUI 提供了常用的预定义控件类,包括按钮(包括单选钮、复选钮)、静态框、列表框、进度条、滑块、编辑框等等。程序也可以定制自己的控件类,注册后再创建对应 的实例。表 1 给出了 MiniGUI 预先定义的控件类和相应类名称定义。
表 1 MiniGUI 预定义的控件类和对应类名称
控件类 | 类名称 | 宏定义 | 备注 |
静态框 | "static" | CTRL_STATIC | |
按钮 | "button" | CTRL_BUTTON | |
列表框 | "listbox" | CTRL_LISTBOX | |
进度条 | "progressbar" | CTRL_PRORESSBAR | |
滑块 | "trackbar" | CTRL_TRACKBAR | |
单行编辑框 | "edit"、"sledit" | CTRL_EDIT、CTRL_SLEDIT | |
多行编辑框 | "medit"、"mledit" | CTRL_MEDIT、CTRL_MLEDIT | |
工具条 | "toolbar" | CTRL_TOOLBAR | |
菜单按钮 | "menubutton" | CTRL_MENUBUTTON | |
树型控件 | "treeview" | CTRL_TREEVIEW | 包含在 mgext 库,即MiniGUI 扩展库中。 |
月历控件 | "monthcalendar" | CTRL_MONTHCALENDAR | 同上 |
旋钮控件 | "spinbox" | CTRL_SPINBOX | 同上 |
在 MiniGUI 中,通过调用 CreateWindow 函数,可以建立某个控件类的一个实例。控件类既可以是表 1 中预定义 MiniGUI 控件类,也可以是用户自定义的控件类。与 CreateWindow 函数相关的几个函数的原型如下(include/window.h):
|
CreateWindow 函数建立一个子窗口,即控件。它指定了控件类、控件标题、控件风格,以及窗口的初始位置和大小。该函数同时指定子窗口的父窗口。 CreateWindowEx 函数的功能和 CreateWindow 函数一致,不过,可以通过 CreateWindowEx 函数指定控件的扩展风格。DestroyWindow 函数用来销毁用上述两个函数建立的控件或者子窗口。
清单 1 中的程序,利用预定义控件类创建控件。其中hStaticWnd1 是建立在主窗口 hWnd 中的静态框;hButton1、hButton2、hEdit1、hStaticWnd2则是建立在 hStaicWnd1 内部的几个控件,并作为 hStaticWnd1 的子控件而存在,建立了两个按钮、一个编辑框和一个静态按钮;而 hEdit2 是 hStaicWnd2 的子控件,是 hStaticWnd1 的子子控件。
清单1 利用预定义控件类创建控件
|
用户也可以通过 RegisterWindowClass 函数注册自己的控件类,并建立该控件类的控件实例。如果程序不再使用某个自定义的控件类,则应该使用 UnregisterWindowClass 函数注销自定义的控件类。上述两个函数以及和窗口类相关函数的原型如下(include/window.h):
|
RegisterWindowClass 通过 pWndClass 结构注册一个控件类;UnregisterWindowClass 函数则注销指定的控件类;GetClassName 活得窗口的对应窗口类名称,对主窗口而言,窗口类名称为"MAINWINDOW";GetWindowClassInfo 分别用来获取和指定特定窗口类的属性。
清单 2 中的程序,定义并注册了一个自己的控件类。该控件用来显示安装程序的步骤信息,MSG_SET_STEP_INFO 消息用来定义该控件中显示的所有步骤信息,包括所有步骤名称及其简单描述。MSG_SET_CURR_STEP 消息用来指定当前步骤,控件将高亮显示当前步骤。
清单2 定义并注册自定义控件类
|
3 控件子类化
采用控件类和控件实例的结构,不仅可以提高代码的可重用性,而且还可以方便地对已有控件类进行扩展。比如,在需要建立一个只允许输入数字的编辑框 时,就可以通过重载已有编辑框控件类而实现,而不需要重新编写一个新的控件类。在 MiniGUI 中,这种技术称为子类化或者窗口派生。子类化的方法有三种:
- 一种是对已经建立的控件实例进行子类化,子类化的结果是只影响这一个控件实例;
- 一种是对某个控件类进行子类化,将影响其后创建的所有该控件类的控件实例;
- 最后一种是在某个控件类的基础上新注册一个子类化的控件类,不会影响原有控件类。在 Windows 中,这种技术又称为超类化。
在 MiniGUI 中,控件的子类化实际是通过替换已有的窗口过程实现的。清单 3 中的代码就通过控件类创建了两个子类化的编辑框,一个只能输入数字,而另一个只能输入字母:
清单 3 控件的子类化
|
4 对话框和对话框模板
在 MiniGUI 中,对话框是一类特殊的主窗口,这种主窗口只关注与用户的交互――向用户提供输出信息,但更多的是用于用户输入。对话框可以理解为子类化之后的主窗口类。 它针对对话框的特殊性(即用户交互)进行了特殊设计。比如用户可以使用 TAB 键遍历控件、可以利用 ENTER 键表示默认输入等等。在 MiniGUI 当中,在建立对话框之前,首先需要定义一个对话框模板,该模板中定义了对话框本身的一些属性,比如位置和大小等等,同时定义了对话框中所有控件的初始信 息,包括位置、大小、风格等等。在 MiniGUI 中,用两个结构来表示对话框模板(src/window.h):
|
结构 CTRLDATA 用来定义控件,DLGTEMPLATE 用来定义对话框本身。在程序中,应该首先利用 CTRLDATA 定义对话框中所有的控件,并用数组表示。控件在该数组中的顺序,也就是对话框中用户按 TAB 键时的控件切换顺序。然后定义对话框,指定对话框中的控件数目,并指定 DLGTEMPLATE 结构中的 controls 指针指向定义控件的数组。如清单 4 所示。
清单 4 对话框模板的定义
|
在定义了对话框模板数据之后,需要定义对话框的回调函数,并调用DialogBoxIndirectParam 函数建立对话框,如清单 5 所示,所建立的对话框如图 1 所示。
清单 5 定义对话框回调函数,并建立对话框
|
图 1 清单 5 程序建立的对话框
DialogBoxIndirectParam 以及相关函数的原型如下:
|
在 DialogBoxIndirectParam 中,需要指定对话框模板(pDlgTemplate)、对话框的托管主窗口句柄(hOwner)、对话框回调函数地址(DlgProc),以及要传递到对 话框过程的参数值(lParam)。EndDialog 用来结束对话框过程。DestroyAllControls 用来销毁对话框(包括主窗口)中的所有子控件。
在清单 5 中,对话框回调函数并没有进行任何实质性的工作,当用户按下"确定"按钮时,调用 EndDialog 函数直接返回。
5 MSG_INITDIALOG 消息
对话框回调函数是一类特殊的主窗口回调函数。用户在定义自己的对话框回调函数时,需要处理 MSG_INITDIALOG 消息。该消息是在 MiniGUI 建立根据对话框模板建立对话框以及控件之后,发送到对话框回调函数的。该消息的 lParam 参数包含了由 DialogBoxIndirectParam 函数的第四个参数传递到对话框回调函数的值。用户可以利用该值进行对话框的初始化,或者保存起来以备后用。例如,清单 7 中的程序将 MSG_INITDIALOG 消息的 lParam 参数保存到了对话框窗口句柄的附加数据中,这样可以确保在任何需要的时候,方便地从对话框窗口的附加数据中获取这一数据。
|
通常而言,传递到对话框回调函数中的参数是一个结构的指针,该结构包含一些初始化对话框的数据,同时也可以将对话框的输入数据保存下来并传递到对话框之外使用。
6 模态和非模态对话框
简单而言,模态对话框就是显示之后,用户不能再切换到其他主窗口进行工作的对话框,而只能在关闭之后,才能使用其他的主窗口。MiniGUI 中,使用 DialogBoxIndirectParam 函数建立的对话框就是模态对话框。实际上,该对话框首先根据模板建立对话框,然后禁止其托管主窗口,并在主窗口的 MSG_CREATE 消息中创建控件,并发送 MSG_INITDIALOG 消息给回调函数,最终建立一个新的消息循环,并进入该消息循环,直到程序调用 EndDialog 函数为止。
实际上,我们也可以在 MiniGUI 中利用对话框模板建立普通的主窗口,即非模态对话框。这时,我们使用 CreateMainWindowIndirect 函数。该函数以及相关函数的原型如下(src/window.h):
|
使用 CreateMainWindowIndirect 根据对话框模板建立的主窗口和其他类型的普通主窗口没有任何区别。
7 小结
对话框编程是 MiniGUI 应用开发中使用最为常见的一种技术。通过定义一个对话框模板,就可以自动创建一个具有复杂输入输出界面的对话框。本文讲述了 MiniGUI 中的控件类和控件实例的关系,并举例说明控件子类化的概念及应用;然后讲解了 MiniGUI 对话框的编程技术,包括对话框模板的定义和对话框回调函数的编程;最后说明了模态对话框和非模态对话框之间的区别。
转载于:https://www.cnblogs.com/weifuqin530/archive/2009/05/17/1458623.html
基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(三)相关推荐
- 基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(一)(转)
自 MiniGUI 从 1998 年底推出以来,越来越多的人开始选择 MiniGUI 在 Linux 上开发实时嵌入式系统.为了帮助嵌入式软件开发人员使用 MiniGUI编写出更好的应用程序,我们将撰 ...
- 基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南题八——MiniGUI 和其他嵌入式 Linux 上的图形及图形用户界面系统
简介: 为了让读者对嵌入式 Linux 当中能够使用的图形及图形用户界面有个较为全面的认识,本文将为读者介绍一些嵌入式 Linux 系统中常见的图形及图形用户界面系统,并作为<基于 Linux ...
- 基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南
内容: 1 Linux 图形领域的基础设施 2 Linux 图形领域的高级函数库 3 面向嵌入式Linux 系统的图形用户界面 4 小结 关于作者 相关内容: 主题一:选择MiniGUI-Thread ...
- 基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(八)
基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(八) MiniGUI 和其他嵌入式 Linux 上的图形及图形用户界面系统 魏永明 (ymwei@minigui.org) 自由撰稿人 ...
- 10001.基于Linux和MiniGUI的嵌入式系统软件开发指南(转载)
1 Linux 图形领域的基础设施 2 Linux 图形领域的高级函数库 3 面向嵌入式Linux 系统的图形用户界面 4 小结 关于作者 相关内容: 主题一:选择MiniGUI-Threads 或者 ...
- 基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(六) MiniGUI 提供的非 GUI/GDI 接口...
1 引言 一般而言,GUI 系统的应用程序编程接口主要集中于窗口.消息队列.图形设备等相关方面.但因为 GUI 系统在处理系统事件时通常会提供自己的机制,而这些机制往往会和操作系统本身提供的机制不相兼 ...
- 基于Linux和MiniGUI的嵌入式系统软件开发指南(五)
MiniGUI 1.1.0 版本引入的新 GDI 功能和函数 本文向读者展现了 MiniGUI 的最新开发成果,即在 MiniGUI 1.1.0Pre4 版本中引入的新的 GAL 和新的 GDI 功能 ...
- 基于Linux和MiniGUI的嵌入式系统软件开发指南(六)
本文讲述了 MiniGUI 为应用程序提供的非 GUI/GDI 接口,这些接口能够帮助应用程序更好地和操作系统交互,扩展应用程序功能,并提高应用程序的可移植性.内容主要涉及到如下几个方面:MiniGU ...
- 基于Linux和MiniGUI的嵌入式系统软件开发指南(七)
1 引言 我们在本系列主题五中曾经详细描述了在 MiniGUI 1.1.0 版本开发过程中添加的新 GDI 功能和函数.这些接口首次出现在版本 1.1.0Pre4 当中.目前 MiniGUI 1.1. ...
最新文章
- linux C 内存管理方式之半动态
- os.clock()导致的bug
- python中对象和变量的关系_浅析python中的类变量和对象变量
- [VsCode] 开发所使用的VsCode的插件
- java 对象引用传递
- SpringBoot集成Dubbo+Zookeeper
- 【Transformer】Transformer中16个注意力头一定要比1个注意力头效果好吗?
- SourceTree使用笔记 ssh-key配置
- conda install labelimg 预定标签类别
- [数学建模]马尔萨斯的人口模型及感性认识
- 小胖子日记之扯淡的生活2
- MFC软件欢迎界面(基于对话框,VS2013)
- 拉钩网前端项目实战04
- 移动拨号上网开热点(不是360开热点,而是使用电脑自带的热点功能)详解
- 2021年大庆高考成绩查询,2021年大庆高考状元是谁分数多少分,历年大庆高考状元名单...
- 什么是最好的UML在线免费软件
- 如何在 微软Microsoft 官网 下载 office365
- qq_seconds.html,qq英语签名
- Mean Shift Segmentation Assessment for Individual Forest Tree Delineation from Airborne Lidar Data
- 北京邮电大学 信通院 计算机原理与应用笔记(一)
热门文章
- MySQL8单表记录多少_mysql学习笔记之8(单表数据记录查询)_mysql
- PHP案例:实现数据库增删改查功能
- 英语学习笔记2019-11-15
- Java Web学习笔记02:在Intellij里创建Web项目
- 【codevs3044】矩形面积求并【POJ1151】Atlantis,第一次的扫描线
- vex夹球机器人_汕头市4名中学生获2020年VEX机器人世锦赛初中组亚军
- 2017.10.8 球形空间产生器sphere 思考记录
- javascript官方文档_基于Javascript编写的开源Markdown和HTML相互转换器——showdown
- 【英语学习】【Level 08】U04 What I love L6 Information overload
- 【英语学习】【Level 07】U03 Amazing wonders L5 Modern structures in China