UCgui

来源:互联网 发布:程序员老了没公司要 编辑:程序博客网 时间:2024/04/30 08:17

Graphical User Interface

返回上级目录Embedded Operating System/microCOS-II

目录

 [隐藏]
  • 1 GUI介绍
    • 1.1 简介
    • 1.2 特点
    • 1.3 GUI的组成部分
  • 2 μC/GUI介绍
    • 2.1 μC/GUI简介
    • 2.2 μC/GUI特点
  • 3 UCGUI接口函数
    • 3.1 文本显示
    • 3.2 显示数值
    • 3.3 字体选择
    • 3.4 2D图形
    • 3.5 视窗管理
  • 4 动手实验:基于LCD时钟显示的音频播放器

GUI介绍

Gui.jpg
图形用户界面(Graphical User Interface,简称 GUI,又称图形用户接口)是指采用图形方式显示的计算机操作用户界面。与早期计算机使用的命令行界面相比,图形界面对于用户来说在视觉上更易于接受。

简介

  1. 如Windows是以”wintel标准“方式操作的,因为你可以用鼠标来点击按钮来进行操作,很直观。而DOS就不具备GUI,所以他只能输入命令。DOS 的这种界面叫CLI (Command line User Interface ) 命令行模式的人机接口。
  2. GUI 是 Graphical User Interface 的简称,即图形用户界面,通常人机交互图形化用户界面设计经常读做“goo-ee”,准确来说 GUI 就是屏幕产品的视觉体验和互动操作部分。
  3. GUI 是一种结合计算机科学、美学、心理学、行为学,及各商业领域需求分析的人机系统工程,强调人—机—环境三者作为一个系统进行总体设计。这种面向客户的系统工程设计其目的是优化产品的性能,使操作更人性化,减轻使用者的认知负担,使其更适合用户的操作需求,直接提升产品的市场竞争力。
  4. GUI 即人机交互图形化用户界面设计。纵观国际相关产业在图形化用户界面设计方面的发展现状,许多国际知名公司早已意识到 GUI 在产品方面产生的强大增值功能,以及带动的巨大市场价值,因此在公司内部设立了相关部门专门从事 GUI 的研究与设计,同业间也成立了若干机构,以互相交流 GUI 设计理论与经验为目的。随着中国 IT 产业,移动通讯产业,家电产业的迅猛发展,在产品的人机交互界面设计水平发展上日显滞后,这对于提高产业综合素质,提升与国际同等业者的竞争能力等等方面无疑起了制约的作用。

特点

GUI的广泛应用是当今计算机发展的重大成就之一,他极大地方便了非专业用户的使用人们从此不再需要死记硬背大量的命令,取而代之的是可以通过窗口、菜单、按键等方式来方便地进行操作。而嵌入式GUI具有下面几个方面的基本要求:轻型、占用资源少、高性能、高可靠性、便于移植、可配置等特点。

GUI的组成部分

桌面:

  在启动时显示,也是界面中最底层,有时也指代包括窗口、文件浏览器在内的“桌面环境”。在桌面上由于可以重叠显示窗口,因此可以实现多任务化。一般的界面中,桌面上放有各种应用程序和数据的图标,用户可以依此开始工作。桌面与既存的文件夹构成里面相违背,所以要以特殊位置的文件夹的参照形式来定义内容。比如在微软公司的Windows XP系统中,各种用户的桌面内容实际保存在系统盘(默认为C盘):\Documents and Settings\[用户名]\桌面 文件夹里。   墙纸,即桌面背景。可以设置为各种图片和各种附件,成为视觉美观的重要因素之一。 

视窗:

  应用程序为使用数据而在图形用户界面中设置的基本单元。应用程序和数据在窗口内实现一体化。在窗口中,用户可以在窗口中操作应用程序,进行数据的管理、生成和编辑。通常在窗口四周设有菜单、图标,数据放在中央。   在窗口中,根据各种数据/应用程序的内容设有标题栏,一般放在窗口的最上方,并在其中设有最大化、最小化(隐藏窗口,并非消除数据)、最前面、缩进(仅显示标题栏)等动作按钮,可以简单地对窗口进行操作。 

单一文件界面:

  在窗口中,一个数据在一个窗口内完成的方式。在这种情况下,数据和显示窗口的数量是一样的。若要在其他应用程序的窗口使用数据,将相应生成新的窗口。因此窗口数量多,管理复杂。 

多文件界面:

  在一个窗口之内进行多个数据管理的方式。这种情况下,窗口的管理简单化,但是操作变为双重管理。 

标签:

  多文件界面的数据管理方式中使用的一种界面,将数据的标题在窗口中并排,通过选择标签标题显示必要的数据,这样使得接入数据方式变得更为便捷。上述中,多文件界面主要是微软视窗系统采用。而在其他环境中,通常多是单文件界面,所以无所谓单一/多文件界面的称呼问题。 

菜单:

  将系统可以执行的命令以阶层的方式显示出来的一个界面。一般置于画面的最上方或者最下方,应用程序能使用的所有命令几乎全部都能放入。重要程度一般是从左到右,越往右重要度越低。命定的层次根据应用程序的不同而不同,一般重视文件的操作、编辑功能,因此放在最左边,然后往右有各种设置等操作,最右边往往设有帮助。一般使用鼠标的第一按钮进行操作。   即时菜单(又称功能表)   与应用程序准备好的层次菜单不同,在菜单栏以外的地方,通过鼠标的第二按钮调出的菜单称为“即时菜单”。根据调出位置的不同,菜单内容即时变化,列出所指示的对象目前可以进行的操作。 

图标:

  显示在管理数据的应用程序中的数据,或者显示应用程序本身。   数据管理程序,即在文件夹中用户数据的管理、进行特定数据管理的程序的情况下,数据通过图标显示出来。通常情况下显示的是数据的内容或者与数据相关联的应用程序的图案。另外,点击数据的图标,一般可以之间完成启动相关应用程序以后再显示数据本身这两个步骤的工作。   应用程序的图标只能用于启动应用程序。 

按钮:

  菜单中,利用程度高的命令用图形表示出来,配置在应用程序中,成为按钮。   应用程序中的按钮,通常可以代替菜单。一些使用程度高的命令,不必通过菜单一层层翻动才能调出,极大提高了工作效率。但是,各种用户使用的命令频率是不一样的,因此这种配置一般都是可以由用户自定义编辑。 

μC/GUI介绍

μC/GUI简介

  μC/GUI 是一种用于嵌入式应用的图形支持软件。它被设计用于为任何使用一个图形LCD的应用提供一个有效的不依赖于处理器和LCD 控制器的图形用户接口。它能工作于单任务或多任务的系统环境下。μC/GUI 适用于使用任何LCD 控制和CPU 的任何尺寸的物理和虚拟显示。它的设计是模块化的,由在不同的模块中的不同的层组成。一个层,称作LCD 驱动程序,包含了对LCD 的全部访问。μC/GUI 适用于所有的CPU,因为它100%由的ANSI 的C 语言编写的。
  μC/GUI 很适合大多数的使用黑色/白色和彩色LCD 的应用程序。它有一个很好的颜色管理器,允许它处理灰阶。μC/GUI 也提供一个可扩展的2D 图形库和一个视窗管理器,在使用一个最小的RAM 时能支持显示窗口。

μC/GUI特点

μC/GUI 被设计用于给使用一个图形LCD 的任何应用程序提供一个高效率的,与处理器和LCD 控制器无关的图形用户界面。它适合于单一任务和多任务环境,专用的操作系统或者任何商业的实时操作系统(RTOS)。μC/GUI 以C 源代码形式提供。它可以适用于任何尺寸的物理和虚拟显示,任何LCD 控制器和CPU。其特点包括下列这些:

一般特点:
• 任何8/16/32 位CPU;只需要一个与ANSI 兼容的C 编译器。
• 任何控制器支持(如果有合适的驱动程序)的任何(单色的,灰度级或者彩色)LCD。
• 在较小显示屏上,可以不要LCD 控制器工作。
• 使用配置宏可以支持任何接口。
• 显示屏大小可配置。
• 字符和位图可能是写在LCD 上的任一点,而不仅仅局限于偶数的字节的地址。
• 程序对大小和速度都进行了最优化。
• 允许编译时的切换以获得不同的优化。
• 对于较慢的LCD 控制器,LCD 能够被存储到内存当中,减少访问的次数使其最小,从而得到非常高的速度。
• 清晰的结构。
• 支持虚拟显示;虚拟显示能够比实际的显示表现更大尺寸的内容。
图库:
• 支持不同颜色深度的位图。
• 有效的位图转换器。
• 绝对没有使用浮点运算。
• 快速线/点绘制(没有使用浮点运算)。
• 非常快的圆/多边形的绘制。
• 不同的绘画模式。
字体:
• 为基本软件提供了不同种类的字体:4*6,6*8,6*9,8*8,8*9,8*16,8*17,8*18,24*32,以及8,10,13,16 等几种高度(以象素为单位)的均衡字体。
• 可以定义和简便地链接新的字体。
• 只有用于应用程序的字体才实际上与执行结果链接,这样保证了最低的ROM 占用。
• 字体可以分别在X 轴和Y 轴方向上充分地缩放。
• 提供有效的字体转换器,任何在你的主系统(即Microsoft Windows)上的有效字体都可以转换。
字符串/数值输出程序:
• 程序支持任何字体的十进制,二进制,十六进制的数值显示。
• 程序支持任何字体的十进制,二进制,十六进制的数值编辑。
视窗管理器(WM):
• 完全的窗口管理器包括剪切在内。一个窗口的外部区域的改写是不可能的。
• 窗口能够移动和缩放。
• 支持回调函数(可选择用法)。
• WM 使用极小的RAM(大约每个窗口20 字节)。
可选择用于PC外观的控件:
• 控件(窗口对象)有效。它们一般自动运行,并且易于使用。
触摸屏和鼠标支持:
• 对于比如按钮控件之类的窗口对象,μC/GUI 提供触摸屏和鼠标支持。
PC工具:
• 模拟器及观察器。
• 位图转换器。
• 字体转换器。

UCGUI接口函数

文本显示

使用μC/GUI 显示字体是很容易的。仅仅需要很少的的函数知识就能让我们在任何有效的字体当中进行文本书字,然后显示在任何一个位置。在这里我们只对一些常用的函数进行分析

  1. GUI_DispChar()

描述:在当前视窗使用当前字体在当前文本坐标处显示单个字符。
函数原型:void GUI_DispChar(U16 c);

参数含义C显示的字符

这是显示字符的基本函数。所有其它显示函数(GUI_DispCharAt(),GUI_DispString()等)都要调用这个函数输出单个字符。字符是否有效取决于所选择的字体,如果在当前字体中该字符无效,则不会有任何显示。
范例:
在屏幕上显示一个大写“A”: 
GUI_DispChar(‘A');

  2. GUI_DispCharAt()

描述:在当前视窗使用当前字体在指定坐标处显示单个字符。
函数原型:void GUI_DispCharAt(U16 c, I16P x, I16P y);

参数含义C显示的字符xX轴坐标(以像素为单位)yy轴坐标(以像素为单位)

显示字符的左上角在指定的(X,Y)坐标。使用函数GUI_DispChar()写字符。如果在当前字体中该字符无效,则不会有任何显示。
范例: 
在屏幕左上角显示一个大写“A”:
GUI_DispCharAt('A',0,0);

  3. GUI_DispString()

描述:在当前视窗的当前坐标,使用当前字体显示作为参数的字符串。
函数原型:void GUI_DispString(const char GUI_FAR *s);

参数含义s显示的字符串

字符串包括控制字符“\n”。该控制字符把当前文本坐标移到下一行的开始处。
范例:
在屏幕上显示“Hello world”及在下一行显示“Next line”:
GUI_DispString("Hello world"); // 显示文本
GUI_DispString("\nNext line"); // 显示文本

  4. GUI_DispStringAt()

描述:在当前视窗,使用当前字体在指定坐标显示作为参数的字符串。
函数原型:void GUI_DispStringAt(const char GUI_FAR *s, int x, int y);

参数含义s显示的字符串xX轴坐标(以像素为单位)yy轴坐标(以像素为单位)

范例:
在屏幕上坐标(50,20)处显示“Position 50,20”
GUI_DispStringAt("Position 50,20", 50, 20); // 显示文本

  5. GUI_Clear()

描述:清除当前视窗。 
函数原型:void GUI_Clear(void);
如果没有定义视窗,当前视窗为整个显示区。这样的话,整个显示区都会被清除。

范例:
在屏幕上显示“Hello world”,等待1秒种,然后清除显示内容:
GUI_DispStringAt("Hello world", 0, 0); // 显示文本
GUI_Delay(1000); // 等待1秒钟(非μC/GUI部分)
GUI_Clear(); // 清屏

每个任务都有一个当前文本坐标,该坐标以视窗的原点(通常是(0,0))为参考,如果调用了文本输出函数,下一个字符会写在这个坐标上。初始化时,该坐标是(0,0),即当前视窗的左上角。在三个函数可能用来设置当前文本坐标。 

  6. GUI_GotoXY(), GUI_GotoX(), GUI_GotoY()

描述:设置当前写文本的坐标。 函数原型:
char GUI_GotoXY(int x, int y);
char GUI_GotoX(int x);
char GUI_GotoY(int y);

模式描述x新的X轴坐标(以像素为单位,0为视窗左边界)y新的Y轴坐标(以像素为单位,0为视窗顶部边界)

返回值通常为0。如果返回数值非0,则当前文本坐标超出视窗范围(到了右边或下边),这样紧接着的写操作可能被忽略。
GUI_GotoXY()对当前视窗文本坐标的X坐标和Y坐标两部分同时设置。
GUI_GotoX()只对当前视窗文本坐标的X坐标部分进行设置,Y坐标保持不变。
GUI_GotoY()只对当前视窗文本坐标的Y坐标部分进行设置,X坐标保持不变。
范例:
在屏幕上坐标(20,20)处显示“(20,20)”:
GUI_GotoXY(20,20)
GUI_DispString("The value is");

显示数值

前面章节说明了如何在屏幕上显示字符串。当然你也可以用字符串和标准C库函数显示数值。然而,有时候这会是件困难的事。通常最容易(最有效)的是调用一个函数显示你所需要结构的数值。μC/GUI提供了不同的十进制,十六进制和二进制输出函数。 

  1. GUI_DispDec()

描述:在当前视窗的当前文本坐标,使用当前字体显示一个十进制数值,指定显示字符的数量。
函数原型:void GUI_DispDec(I32 v, U8 Len);

参数含义v用于显示的数值。len显示数字的数量

不支持首位为0的格式(如0)。如果数值为负,则会显示一个减号。
范例

//以分秒的格式显示时间 GUI_DispString(“Min:);GUI_DispDec(Min,2);GUI_DispString(“Sec:);GUI_DispDec(Sec,2);

  2. GUI_DispDecAt()

描述:在当前视窗的当前文本坐标,使用当前字体显示十进制数值,指定显示字符的数量。
函数原型:void GUI_DispDecAt(I32 v, I16P x, I16P y, U8 Len);

参数含义v用于显示的数值。x写入的x轴坐标。y写入的y轴坐标。len显示数字的数量

不支持首位为0的格式。如果数值为负,则会显示一个减号。
范例:
//在左上角更新秒 
GUI_DispDecAT(Sec, 200, 0, 2);

  3. GUI_DispFloat() 

描述:在当前视窗的当前文本坐标,使用当前字体显示一个浮点数,指定显示字符数量。
函数原型:void GUI_DispFloat(float v, char Len);

参数含义v用于显示的数值。len显示数字的数量

不支持首位为0的格式。小数点当作一个字符处理。如果数值为负数,会显示一个减号。
范例:

//浮点数的显示<br/>void DemoFloat(void){float f = 123.45678;GUI_Clear()GUI_SetFont(&GUI_Font8x8);GUI_DispStringAt(“GUI_DispFloat:\n”,0,0);GUI_DispFloat (f,9);}

  4. GUI_DispBin() 

描述:在当前视窗的当前文本坐标,使用当前字体显示一个二进制数。
函数原型:void GUI_DispBin(U32 v, U8 Len);

参数含义v用于显示的数值。len显示数字的数量

与十进制及十六进制一样,最低有效位在最右边。
范例:
// 显示二进制数“7”,结果为:000111
U32 Input = 0x7;
GUI_DispBin(Input, 6);

  5. GUI_DispHex() 

描述:在当前视窗的当前文本坐标,使用当前字体显示一个十六进制数值。
函数原型:void GUI_DispHex(U32 v, U8 Len);

参数含义v用于显示的数值。len显示数字的数量

与十进制及二进制一样,最低有效位在最右边。
范例:
//显示一个十六进制的数值
GUI_DispHex(Input, 4);

字体选择

μC/GUI 支持ASCII,ISO 8859-1 及 Unicode。通常,μC/GUI 按8 位字符进行编译,允许最大为256 的不同的字符代码,32 之前的编码除外,这部分字符作为控制字符保留。字符是否有效取决所选择的字体(即该字体是否包括有所需的字符)。 
所有的字体会与你的应用相连接,而字体的选择在GUIConf.h 中定义。我们推荐编译所有的字体并将它们作为一个库模块进行连接,或者将所有的字体工程文件放入一个你能与你的应用相连接的库当中。这种方法可以让你确定那些你在应用中需要的字体被真正连接。字体转换器(在一本独立的手册中描述)用于创建附加的字体。
为了能在你的应用中使用一种字体,你必须要做到下面几点:

• 字体在与μC/GUI 规范相兼容的“C”文件,工程文件或库这三种文件中任一种当中。
• 字体文件与你的应用链接。
• 字体的描述要包含在GUIConf.h 中(这很必要,这是为了避免由于没有声明的外部常量而产生的编译警告)

一旦你连接过一个如上面所描述的字体文件,将要连接的字体声明为一个外部常量GUI_FONT,如下面范例所显示的那样:

extern const GUI_FONT GUI_FontNew;int main (void){GUI_Init () ;GUI_Clear();GUI_SetFont(&GUI _FontNew);GUI_DispString("Hello world\n");return 0;}

μC/GUI 提供不同的字体。可以通过调用函数GUI_SetFont()改变所选择的字体,该函数选择字体用于伴随当前任务的文字输出。如果在你的应用中没有字体被选择,则使用默认字体。该默认值由GUIConf.h 配置,可以进行修改。你应该确认默认字体是你的应用中真正用到的字体,因为默认字体会与你的应用连接,因此可能会耗尽ROM 存储空间。

2D图形

μC/GUI包括有一个完整的2-D图形库,在大多数场下应用是足够了。μC/GUI提供的函数既可以与裁剪区一道使用也可以脱离裁剪区使用(参考“视窗管理器”),这些函数基于快速及有效率的算法建立。目前,只有绘制圆弧函数要求浮点运算支持。 
μC/GUI提供两种绘图模式,NORMAL模式及XOR模式。默认为NORMAL模式,即显示屏的内容被绘图所完全覆盖。在XOR模式,当绘图覆盖在上面时,显示屏的内容反相显示。
与GUI_DRAWMODE_XOR有关的限制:

• XOR模式通常用于在活动视窗或屏幕中使用两种颜色进行显示的场合。
• 一些μC/GUI的绘图函数并不能正确地工作在这种模式。通常情况下,这模式只是工作于一个像素大小的笔尖尺寸。这意味着在使用类似GUI_DrawLine ,

GUI_DrawCircle,GUI_DrawRect等等这样的函数之前,你必须确定在XOR模式下,笔尖尺寸已经设为1。

• 当使用颜色的深度大于1位/像素(bpp)进行位图绘制,该模式无效。
• 当使用诸如GUI_DrawPolyLine这样的函数或多次调用GUI_DrawLineTo函数,转角点会反相两次。结果是这些像素保持背景颜色。
  1. GUI_SetDrawMode() 

描述:选择指定的绘图模式
函数原型:GUI_DRAWMODE GUI_SetDrawMode(GUI_DRAWMODE mode);

参数含义mode设置的绘图模式。可以是任意设置绘图模式的函数的返回值或是下表中的任一个。

参数mode允许的数值

GUI_DRAWMODE_NORMAL设置的绘图模式。可以是任意设置绘图模式的函数的返回值或是下表中的任一个。GUI_DRAWMODE_XOR当在屏幕上另一个物体上用颜色覆盖时对点,线,区域进行反相显示

作为设置绘图模式的附加功能,该函数也可以用于恢复原先被修改的绘图模式。
如果使用颜色,一个反相的像素由下式算出:
新像素颜色 = 颜色的数值 - 实际像素颜色 - 1
范例:

// 显示两个圆,其中第二个以XOR模式与第一个结合GUI_Clear();GUI_SetDrawMode(GUI_DRAWMODE_NORMAL);GUI_FillCircle(120, 64, 40);GUI_SetDrawMode(GUI_DRAWMODE_XOR);GUI_FillCircle(140, 84, 40);

上面范例程序运行结果的屏幕截图
两个圆.jpg


基本绘图函数允许在显示屏上的任何位置进行单独的点,水平和垂直线段和形状的绘制。使用任何有效的绘图模式。因为这些函数在大多数应用中被频繁调用,因此它们已经被尽量地优化以获得尽可能快的速度。例如,水平和垂直线段绘制函数不需要使用单个点绘制函数。

  2. GUI_ClearRect()

描述:在当前视窗的指定位置通过向一个矩形区域填充背景色来清除它。
函数原型:void GUI_ClearRect(int x0, int y0, int x1, int y1);

参数含义x0左上角X坐标y0左上角y坐标x1右下角X坐标y1右下角y坐标
  3. GUI_DrawPixel()

描述:在当前视窗的指定坐标绘一个像素点。
函数原型:void GUI_DrawPixel(int x, int y);

参数含义xX轴坐标yy轴坐标
  4. GUI_DrawPoint

描述:在当前视窗使用当前尺寸笔尖绘一个点。
函数原型:void GUI_DrawPoint(int x, int y);

参数含义xX轴坐标yy轴坐标


  5. GUI_DrawBitmap

描述:在当前视窗的指定位置绘一幅位图。 函数原型:void GUI_DrawBitmap(const GUI_BITMAP*pBM, int x, int y);

参数含义pBM左上角X坐标x位图在屏幕上位置的左上角X坐标y位图在屏幕上位置的左上角Y坐标

位图数据必须定义为像素×像素。每个像素等同于一位。最高有效位(MSB)定义第一个像素;图片数据以位流进行说明,以第一个字节的MSB作为起始。新的一行总是在一个偶数地址开始,而位图的第N行在地址偏移量n* BytesPerLine处开始。位图可以在客户区中任意一点显示,位图转换器用于产生位图。

  6. GUI_DrawLine()

描述:在当前视窗的指定始点到指定终点绘一条直线。 函数原型:void GUI_DrawLine(int x0, int y0, int x1, int y1);

参数含义x0x轴开始坐标y0y轴开始坐标x1x轴结束坐标y1y轴结束坐标

如果线的一部分是不可见的,因为它不在当前视窗内,或者如果当前视窗的一部分是不可见的,由于裁剪的原因,这些部分将不会绘出。

  6. GUI_DrawCircle()

描述:在当前视窗指定坐标以指定的尺寸绘制一个圆。 函数原型:void GUI_DrawCircle(int x0, int y0, int r);

参数含义x0圆心的X轴坐标y0圆心的y轴坐标r圆的半径

该函数不能处理超过180的半径,因为那样将使用到导致溢出错误的整数运算。但是,对于大多数嵌入式应用,这不算是一个问题,因为一个直径为360的圆无论如何都会比显示屏要大。 范例:

// 画同心圆void ShowCircles(void){int i;for (i=10; i<50; i++)GUI_DrawCircle(120,60,i);}

上面范例程序运行结果的屏幕截图
同心圆.jpg


视窗管理

使用μC/GUI 管理器(WM)时,在显示屏上显示的的所有内容包括在一个窗口里面——屏幕上的一块区域,该区域作为一个绘制或显示对象的用户接口部件。窗口可以是任意大小,你可能在屏幕上同时显示多个窗口,甚至在其它窗口的上面部分或完全地显示。 
视窗管理器提供了一套函数,使你能很容易地对许多窗口进行创建,移动,调整大小及其它操作。它也可以提供更低层的支持,这通过管理显示屏上的窗口的层,及通过给你的应用程序发送信号以显示影响它的窗口的修改来完成。
μC/GUI 的视窗管理器是一个独立的(可选的)的软件项目,它没有包括进μC/GUI 基本软件包里。视窗管理器的软件位于子目录“GUI\WM”下。

窗口外形是矩形,由它们的原点(左上角的 X 和Y 坐标)及它们的X 和Y 尺寸(分别是宽和高)所定义。μC/GUI 中一个窗口:
· 是一个矩形
· 有一个Z 坐标
· 可能是隐藏的或可见的
· 可能拥有有效/或无效区域
· 可以或者不可以有透明区域
· 可以或者不可以有一个回调函数
活动窗口

当前正在使用进行绘图操作的窗口被当作活动窗口。与最顶层窗口一样,它不是必需的。

回调函数

回调函数在用户程序中定义,当一个指定的事件发生时,通知图形系统调用指定的函数。通常应用于一个窗口内容改变时自动重绘的场合。

子/父窗口,同胞

一个子窗口的定义是相对于另一个窗口,该窗口称为父窗口。无论什么时候,一个父窗口移动了,它的子窗口会相应随之移动。一个子窗口总是完全包含在它的父窗口里面,如果需要,它会被剪切。从属于同一个父窗口的多个子窗口相互间的关系称为“同胞”。

客户区

一个窗口的客户区简单地说是它的可使用区。如果一个窗口包括一个边框或标题栏,则客户区是内部的矩形区域。如果没有这样一个边框,则客户区等同于窗口本身。剪切,剪切区域剪切是一种限制窗口或它的部分输出的操作。剪切区域是一个窗口的原有可见区域。由于被更高Z 序列的同胞窗口遮挡,或者不在父窗口可见区域范围之内的缘故,这些部分就会被剪切掉。

桌面窗口

桌面窗口由视窗管理器自动创建,总是覆盖整个显示区域。它始终是一个最底层的窗口。如果没有定义其它窗口,它就是默认(活动)窗口。所有窗口都是桌面窗口的继承窗口。

句柄

当一个新的窗口被创建,WM 会给它分配一个唯一的标识符,称为句柄。句柄将用于对特定窗口更进一步操作的执行。

隐藏/显示窗口

一个隐藏的窗口是不可见的,尽管它仍然存在(有句柄)。当创建一个窗口时,如果没有创建指定的标识的话,默认状态是隐藏。使一个窗口可见则可以将其显示;使其不可见则可以隐藏它。

透明

带有透明部分的窗口包括有窗口静止时不被重绘的区域。这些区域的操作就仿佛是下面的窗口可以透过它们显示出来。在这种情况下,下面的窗口在这个透明窗口之前重绘就显得很重要了。WM 能自动处理正确的重绘顺序。

有效/无效

一个有效的窗口是一个完全更新了的窗口,它不需要重绘。一个无效的窗口不再对所有的更新有反应,因此需要完全或部分重绘。当改变影响一个特定的窗口时,WM 标记该窗口无效。下一次窗口重绘(手动或通过回调函数)后,它将有效。

Z-序,底层/顶层

尽管一个窗口是在一个只有 X 和Y 坐标构成的二维的屏幕上显示,WM 也管理被认为是Z序,或者深度的座标——一个虚拟的三维的坐标,决定窗口从背景到前景放置。因此窗口可以在另一窗口的上面或下面显示。将一个窗口设置到底层将会把它放在所有同胞窗口(如果存在)的下面;设置为顶层将会把它放在所有同胞窗口的上面。创建一个窗口时,如果没有指定创建标识符,默认情况下它会被设置在顶层。

回调机制

uC/GUI 提供给窗口和窗口控件的回调机制的背后,是一个事件驱动标志。在大多数的窗口系统中,流控不仅仅时从用户程序到图形系统,而且还要能够从用户程序到图形系统,并且能够通过用户程序提供的回调函数,返回到用户程序。这个机制,就称为回调机制。在uC/GUI 中,回到机制用来在窗口管理中出控制窗口的重绘操作,这使得窗口管理的有效性成为可能。 

回调函数的使用

为了使用一个回调函数创建窗口,你必需要有一个回调函数。函数的名称将与创建窗口时对应的回调函数指针参数名称相一致(即WM_CreateWindow() 中的 cb 参数)。所有的回调函数必须具有以下函数原型
函数原型:void callback(WM_MESSAGE* pMsg);

模式描述pMsg消息的指针

回调函数的执行行为依赖于它收到的消息类型。上面的函数原型通常带有一个开关声明,用于定义了对于不同的使用一个或更多的事件声明的消息所采用的不同的处理方式(典型的至少有对WM_PAINT()的处理)。
范例:

//创建一个回调函数自动重绘一个窗口void WinHandler(WM_MESSAGE* pMsg){    switch (pMsg->MsgId)    {       case WM_PAINT:       GUI_SetBkColor(0xFF00);       GUI_Clear();       GUI_DispStringAt(“Hello world”,0,0);       break;    } }

WM_MESSAGE 元素

MsgId消息的类型(参照下表)HWin目标窗口hWinSrc源窗口Data.p数据指针Data.v数据数值

MsgId 元素使用的消息类型

WM_PAINT重绘窗口(因为内容至少部分无效)WM_CREATE一个窗口创建后产即发送WM_DELETE告诉窗口释放它的数据结构(如果有的话),然后它将会被删除WM_SIZE当一个窗口的大小改变后发送到它WM_MOVE当一个窗口移动后发送到它WM_SHOW当一个窗口收到显示命令后发送到它WM_HIDE当一个窗口收到隐藏命令后发送到它WM_TOUCH触摸屏消息

应用程序可以为它自己的用途定义附加消息。为了保证它们使用的消息ID 不会与μC/GUI使用的消息ID 同名,用户定义的消息的编号以WM_USER 为开始。你应该像下面所展示的一样

  1. define MY_MESSAGE_AAA WM_USER+0
  2. define MY_MESSAGE_BBB WM_USER+

下面的范例展示了使用或不使用回调函数进行重绘之间的区别。它也展示了如何设置你自己的回调函数。范例文件是随μC/GUI 一起发布的范例当中WM_Redraw.c:

/*--------------------------------------------------------------------------文件: WM_Redraw.c目的: 展示视窗管理器的重绘机制--------------------------------------------------------------------------*/#include “GUI.H”/**************************************************************************** 背景窗口的回调函数 ****************************************************************************/static void cbBackgroundWin(WM_MESSAGE* pMsg){    switch (pMsg->MsgId)    {         case WM_PAINT:         GUI_Clear();         default:         WM_DefaultProc(pMsg);     }}/**************************************************************************** 前景窗口的回调函数 ****************************************************************************/static void cbForegroundWin(WM_MESSAGE* pMsg){     switch (pMsg->MsgId)     {          case WM_PAINT:          GUI_SetBkColor(GUI_GREEN);          GUI_Clear();          GUI_DispString(“Foreground window”);          break;          default:          WM_DefaultProc(pMsg);     }}/**************************************************************************** μC/GUI 重绘机制展示 ****************************************************************************/static void DemoRedraw(void){     GUI_HWIN hWnd;     while(1)     {         /* 创建前景窗口 */         hWnd = WM_CreateWindow( 10, 10, 100, 100,         WM_CF_SHOW,         cbForegroundWin, 0); /* 显示前景窗口 */         GUI_Delay(1000);         /* 删除前景窗口 */         WM_DeleteWindow(hWnd);         GUI_DispStringAt(“Background of window has not been redrawn”, 10, 10);         /* 等待一会,背景不会重绘 */         GUI_Delay(1000);         GUI_Clear();         /* 设置背景窗口的回调函数 */         WM_SetCallback(WM_HBKWIN, cbBackgroundWin);         /* 创建前景窗口 */         hWnd = WM_CreateWindow( 10, 10, 100, 100,WM_CF_SHOW,cbForegroundWin, 0); /* 显示前景窗口 */         GUI_Delay(1000);         /* 删除前景窗口 */         WM_DeleteWindow(hWnd);         /* 等待一会,背景不会重绘 */         GUI_Delay(1000);         /* 删除背景窗口的回调函数 */         WM_SetCallback(WM_HBKWIN, 0);     }}/**************************************************************************** 主函数 ****************************************************************************/void main (void){    GUI_Init ();    DemoRedraw();}


动手实验:基于LCD时钟显示的音频播放器


Audio Player based on LCD Clock Display

目录

 [隐藏]
  • 1 基于LCD时钟显示的音频播放器
    • 1.1 实验目的
    • 1.2 实验原理
    • 1.3 实验分析
    • 1.4 实验现象

基于LCD时钟显示的音频播放器

实验目的

  1. 掌握μC/GUI的基本用法
  2. 掌握cortex-M3 RTC的使用
  3. 熟悉多任务间的调度

实验原理

  1. RTC工作原理
  2. WM8978工作原理
  3. DMA工作原理
  4. FATFS文件系统原理

实验分析

本实验是在基于第5章的音频播放器的基础之上加入了LCD时钟的显示。在程序中创建了一个用于显示时钟的任务程序如下:

void MyTask2(void * data){INT8U Error=0;GUI_Init();   //GUI初始化 GUI_SetBkColor(GUI_BLUE); //设置背景为蓝色GUI_Clear();  //清屏GUI_SetColor(GUI_WHITE); //设置字体为白色GUI_SetFont(&GUI_Font8x16); //字体格式8x16GUI_DrawPoint(X0,Y0);  //在(X0,Y0)处画点,表示表盘中心GUI_DrawCircle(X0,Y0,r1);  //以(X0,Y0)为圆心,r1为半径画圆             (1)//for中实现表盘中各时刻的数值for(num=1;num<=12;num++)                                             (2){    x = r1 * sin(5*num*3.1415926/30) + X0 - 18;    y = Y0 - r1 * cos(5*num*3.1415926/30)-2;  //确定数字的写入位置   GUI_DispStringAt(" ",x,y);   GUI_DispDec(num,2); }while(1){OSSemPend(SEM_RTC,0,&Error);//判断是否有信号量,无信号量则将本任务挂起       (3)DataValue_temper =  ADC_GetConversionValue(ADC1); //读出温度对应的电压值Data_T = (DataValue_temper * Vref / 4095 - 0.6) * 100; //转化成温度值     change = Data_T * 10; //乘以10去掉小数点//用于得到各位的数值datat[0] = change/100;datat[1] = change%100/10;datat[2] = change%10;                                                  (4)MainTask();                                                            (5)}}

程序以(X0,Y0)为圆心,r1为半径画圆(1)。依次根据正弦、余弦公式和圆的半径求出刻度盘得坐标(2)。等待SEM_RTC信号量而挂起任务,该信号量会在RTC时钟中断中释放。RTC中断的周期为1s。(3)。将读出的温度值经过转化保存到数组中,在LCD刷屏的时候跟新(4)。MainTask()为刷屏的函数,刷新时钟和温度值(5)。 
MainTask()程序分析:

void MainTask(void) {    //显示温度值GUI_DispStringAt("Temperature is: ",40,270);GUI_DispDec(datat[0],1);GUI_DispDec(datat[1],1);GUI_DispString(".");GUI_DispDec(datat[2],1);    //显示时间值GUI_DispStringAt("Time is: ",50,250);    GUI_DispDec(hour,2);    GUI_DispString(":");    GUI_DispDec(minute,2);    GUI_DispString(":");    GUI_DispDec(second,2);    //if中用于将上一秒的秒针痕迹清除    if(second >= 0){    GUI_SetColor(GUI_BLUE);if(second == 0) //如果为零时刻,则清除59秒时刻的位置线{//确定上一时刻的位置xs = r0 * sin(59*P/30) + X0;ys = Y0 - r0 * cos(59*P/30);}else //同上{xs = r0 * sin((second-1)*P/30) + X0;ys = Y0 - r0 * cos((second-1)*P/30);}GUI_DrawLine(X0,Y0,xs,ys);}GUI_SetColor(GUI_RED); //秒针用红色表示//该时刻秒针的位置xs = r0 * sin(second*P/30) + X0;ys = Y0 - r0 * cos(second*P/30);GUI_DrawLine(X0,Y0,xs,ys);//同上if(minute >= 0){GUI_SetColor(GUI_BLUE);    if(minute == 0)    {    xm = (r0-20) * sin(59*P/30) + X0;    ym = Y0 - (r0-20) * cos(59*P/30);    }    else    {    xm = (r0-20) * sin((minute-1)*P/30) + X0;    ym = Y0 - (r0-20) * cos((minute-1)*P/30);    }    GUI_DrawLine(X0,Y0,xm,ym);}GUI_SetColor(GUI_BLACK); //分针用黑色线表示xm = (r0-20) * sin(minute*P/30) + X0;ym = Y0 - (r0-20) * cos(minute*P/30);GUI_DrawLine(X0,Y0,xm,ym);GUI_SetColor(GUI_WHITE); //时针用白色线表示xh = (r0-40) * sin((5*hour+minute/12)*P/30) + X0;yh = Y0 - (r0-40) * cos((5*hour+minute/12)*P/30);GUI_DrawLine(X0,Y0,xh,yh);//下面是实现时间的更新,因为是在RTC秒级中断中调用的,所以每秒更新一次second++;if(second==60) //秒值到60就归零,分值加一{second=0;minute++;}if(minute==60)//分值到60就归零,时值加一{minute=0;hour++;}if(hour==24)//时值到24就归零{hour=0;}}

RTC时钟中断程序分析:

void RTC_IRQHandler(void){OSIntEnter (); if (RTC_GetITStatus(RTC_IT_SEC) != RESET)  { OSSemPost(SEM_RTC);      //释放信号量  } RTC_ClearITPendingBit(RTC_IT_SEC);//清中断标志位 OSIntExit();}

实验现象

在对开发板上电后,会在播放SD卡的同时在LCD屏幕上显示时钟

来源:http://wiki.emsym.com/wiki/Graphical_User_Interface#.E7.AE.80.E4.BB.8B


0 0
原创粉丝点击