目錄
前言
一、按鈕數據結構抽象
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 目錄,編譯測試: