目录
前言
一、按钮数据结构抽象
1.ui.h
二、按键处理
2.disp_manager.c
3.disp_manager.h
三、单元测试
1.ui_test.c
2.上机测试
前言
前面我们实现了显示系统框架,输入系统框架和文字系统框架,链接:
- 量产工具一一显示系统(一)-CSDN博客
- 量产工具一一输入系统(二)-CSDN博客
- 量产工具一一文字系统(三)-CSDN博客
接下来我们来实现UI系统框架。
一、按钮数据结构抽象
1.所谓UI,就是User Interface(用户界面),有图像界面(GUI)等。
2.我们的UI系统,就是构造各类GUI元素,比如按钮(目前只实现按钮)。
3.怎么描述一个按钮呢?
- 它的位置、大小怎么表示?
- 怎么绘制它?
- 用户点击它之后,如何处理?
1.ui.h
#ifndef _UI_H
#define _UI_H
#include <common.h>
#include <disp_manager.h>
#include <input_manager.h>
/* 定义按钮的默认颜色、按下时的颜色和文本颜色 */
#define BUTTON_DEFAULT_COLOR 0xff0000 // 默认颜色,设置为红色
#define BUTTON_PRESSED_COLOR 0x00ff00 // 按下时的颜色,设置为绿色
#define BUTTON_PERCENT_COLOR 0x0000ff // 百分比颜色,设置为蓝色
#define BUTTON_TEXT_COLOR 0x000000 // 文本颜色,设置为黑色
struct Button;
typedef int (*ONDRAW_FUNC)(struct Button *ptButton, PDispBuff ptDispBuff);
typedef int (*ONPRESSED_FUNC)(struct Button *ptButton, PDispBuff ptDispBuff, PInputEvent ptInputEvent);
typedef struct Button {
char *name;
int iFontSize;
int status;
Region tRegion;
ONDRAW_FUNC OnDraw;
ONPRESSED_FUNC OnPressed;
}Button, *PButton;
void InitButton(PButton ptButton, char *name, PRegion ptRegion, ONDRAW_FUNC OnDraw, ONPRESSED_FUNC OnPressed);
#endif
二、按键处理
1.点击按钮后怎么处理,是业务系统的事情
2.所以应该提供一个InitButton函数,让用户可以提供OnPressed函数
3.上层代码通过下面3个函数使用按钮
1.button.c
- 绘制按钮:通过
DefaultOnDraw
函数,按钮在未按下时显示默认颜色和文本。 - 响应按钮按下:通过
DefaultOnPressed
函数处理按钮的按下事件,改变按钮的状态和颜色。 - 初始化按钮:通过
InitButton
函数用于初始化按钮的各项属性,包括名称、区域、绘制函数和按下处理函数。
#include <ui.h>
static int DefaultOnDraw(struct Button *ptButton, PDispBuff ptDispBuff)
{
/* 绘制底色 */
DrawRegion(&ptButton->tRegion, BUTTON_DEFAULT_COLOR);
/* 居中写文字 */
SetFontSize(ptButton->iFontSize);
DrawTextInRegionCentral(ptButton->name, &ptButton->tRegion, BUTTON_TEXT_COLOR);
/* flush to lcd/web */
FlushDisplayRegion(&ptButton->tRegion, ptDispBuff);
return 0;
}
static int DefaultOnPressed(struct Button *ptButton, PDispBuff ptDispBuff, PInputEvent ptInputEvent)
{
unsigned int dwColor = BUTTON_DEFAULT_COLOR;
ptButton->status = !ptButton->status;
if (ptButton->status)
dwColor = BUTTON_PRESSED_COLOR;
/* 绘制底色 */
DrawRegion(&ptButton->tRegion, dwColor);
/* 居中写文字 */
DrawTextInRegionCentral(ptButton->name, &ptButton->tRegion, BUTTON_TEXT_COLOR);
/* flush to lcd/web */
FlushDisplayRegion(&ptButton->tRegion, ptDispBuff);
return 0;
}
void InitButton(PButton ptButton, char *name, PRegion ptRegion, ONDRAW_FUNC OnDraw, ONPRESSED_FUNC OnPressed)
{
ptButton->status = 0;
ptButton->name = name;
if (ptRegion)
ptButton->tRegion = *ptRegion;
ptButton->OnDraw = OnDraw ? OnDraw : DefaultOnDraw;
ptButton->OnPressed = OnPressed ? OnPressed : DefaultOnPressed;
}
2.disp_manager.c
新增函数 void DrawRegion(PRegion ptRegion, unsigned int dwColor) 用于绘制一个指定颜色和区域的矩形。
void DrawRegion(PRegion ptRegion, unsigned int dwColor)
{
int x = ptRegion->iLeftUpX;
int y = ptRegion->iLeftUpY;
int width = ptRegion->iWidth;
int heigh = ptRegion->iHeigh;
int i,j;
for (j = y; j < y + heigh; j++)
{
for (i = x; i < x + width; i++)
PutPixel(i, j, dwColor);
}
}
在一个区域ptRegion中间将位置居中,并且设置字体颜色
新增函数 void DrawTextInRegionCentral(char *name, PRegion ptRegion, unsigned int dwColor),将位置区域居中。
void DrawTextInRegionCentral(char *name, PRegion ptRegion, unsigned int dwColor)
{
/* 计算文本字符串长度 */
int n = strlen(name);
/* 计算每个字符的宽度 */
int iFontSize = ptRegion->iWidth / n / 2;
FontBitMap tFontBitMap;
int iOriginX, iOriginY;
int i = 0;
int error;
/* 如果计算出的字体大小超过了区域的高度,则将字体大小设置为区域的高度 */
if (iFontSize > ptRegion->iHeigh)
iFontSize = ptRegion->iHeigh;
iOriginX = (ptRegion->iWidth - n * iFontSize)/2 + ptRegion->iLeftUpX;
iOriginY = (ptRegion->iHeigh - iFontSize)/2 + iFontSize + ptRegion->iLeftUpY;
SetFontSize(iFontSize);
while (name[i])
{
/* get bitmap */
tFontBitMap.iCurOriginX = iOriginX;
tFontBitMap.iCurOriginY = iOriginY;
error = GetFontBitMap(name[i], &tFontBitMap);
if (error)
{
printf("SelectAndInitFont err\n");
return;
}
/* draw on buffer */
DrawFontBitMap(&tFontBitMap, dwColor);
/* 更新下一个字符的起始坐标 */
iOriginX = tFontBitMap.iNextOriginX;
iOriginY = tFontBitMap.iNextOriginY;
i++;
}
}
3.disp_manager.h
#ifndef _DISP_MANAGER_H
#define _DISP_MANAGER_H
#include <common.h>
#include <font_manager.h>
typedef struct DispBuff {
int iXres;
int iYres;
int iBpp;
char *buff;
}DispBuff, *PDispBuff;
typedef struct DispOpr {
char *name;
int (*DeviceInit)(void);
int (*DeviceExit)(void);
int (*GetBuffer)(PDispBuff ptPDispBuff);
int (*FlushRegion)(PRegion ptRegion, PDispBuff ptPDispBuff);
struct DispOpr *ptNext;
}DispOpr, *PDispOpr;
int PutPixel(int x, int y, unsigned int dwColor);
void RegisterDisplay(PDispOpr ptPDispOpr);
int SelectDefaultDisplay(char *name);
int InitDefaultDisplay(void);
PDispBuff GetDisplayBuffer(void);
int FlushDisplayRegion(PRegion ptPRegion, PDispBuff ptPDispBuff);
void DisplaySystemRegister(void);
void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor);
void DrawRegion(PRegion ptRegion, unsigned int dwColor);
void DrawTextInRegionCentral(char *name, PRegion ptRegion, unsigned int dwColor);
#endif
三、单元测试
1.ui_test.c
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <disp_manager.h>
#include <font_manager.h>
#include <ui.h>
int main(int argc, char **argv)
{
PDispBuff ptBuffer;
int error;
Button tButton;
Region tRegion;
if (argc != 2)
{
printf("Usage: %s <font_size>\n", argv[0]);
return -1;
}
/* FB Init*/
DisplaySystemRegister();
SelectDefaultDisplay("fb");
InitDefaultDisplay();
ptBuffer = GetDisplayBuffer();
/* Font Init*/
FontSystemRegister();
error = SelectAndInitFont("freetype", argv[1]);
if (error)
{
printf("SelectAndInitFont err\n");
return -1;
}
tRegion.iLeftUpX = 200;
tRegion.iLeftUpY = 200;
tRegion.iWidth = 300;
tRegion.iHeigh = 100;
InitButton(&tButton, "test", &tRegion, NULL, NULL);
tButton.OnDraw(&tButton, ptBuffer);
while (1)
{
tButton.OnPressed(&tButton, ptBuffer, NULL);
sleep(2);
}
return 0;
}
2.上机测试
上电开发板,挂载 Ubuntu 的 NFS 目录,编译测试: