简介:
ucgui中,字符显示的底层函数是 GUICharP.c 中的 void GUIPROP_DispChar(U16P c) 函数,我们将这个函数修改如下:
/*********************************************************************
*
* GUIPROP_DispChar
*
* Purpose:
* This is the routine that displays a character. It is used by all
* other routines which display characters as a subroutine.
*/
void GUIPROP_DispChar(U16P c) {
int BytesPerLine
U8 BytesPerFont//一个字的字节数
U32 base,oft//字库的起始地址和偏移量
GUI_DRAWMODE DrawMode = GUI_Context.TextMode
const GUI_FONT_PROP GUI_UNI_PTR * pProp = GUIPROP_FindChar(GUI_Context.pAFont->p.pProp, c)
if (pProp) {
GUI_DRAWMODE OldDrawMode
const GUI_CHARINFO GUI_UNI_PTR * pCharInfo
//支持3种字体==
if((GUI_Context.pAFont == &GUI_FontHZ16)||(GUI_Context.pAFont == &GUI_FontHZ24)||(GUI_Context.pAFont == &GUI_FontHZ32))
{
pCharInfo = pProp->paCharInfo
base = (U32)pProp->paCharInfo->pData
BytesPerFont = GUI_Context.pAFont->YSize * pProp->paCharInfo->BytesPerLine//每个字模的数据字节数
if (BytesPerFont >BYTES_PER_FONT)
{
BytesPerFont = BYTES_PER_FONT
}
if (c <0x80) //英文字符地址偏移算法
{
oft = base + (c - 0x20) * BytesPerFont//计算出字码在flash中的偏移地址
} else //中文字符地址偏移算法 {
oft = base + (((c>>8) - 0xa1) * 94 + ((c&0xff) - 0xa1)) * BytesPerFont
}
LCD_ReadFlashBit(oft, GUI_FontDataBuf, BytesPerFont)//取出字模数据
BytesPerLine = pCharInfo->BytesPerLine
OldDrawMode = LCD_SetDrawMode(DrawMode)
LCD_DrawBitmap( GUI_Context.DispPosX,
GUI_Context.DispPosY,
pCharInfo->XSize,
GUI_Context.pAFont->YSize,
GUI_Context.pAFont->XMag,
GUI_Context.pAFont->YMag,
1, /* Bits per Pixel */
BytesPerLine,
GUI_FontDataBuf,
&LCD_BKCOLORINDEX
)
}
//--
else
{
pCharInfo = pProp->paCharInfo+(c-pProp->First)
BytesPerLine = pCharInfo->BytesPerLine
OldDrawMode = LCD_SetDrawMode(DrawMode)
LCD_DrawBitmap( GUI_Context.DispPosX,
GUI_Context.DispPosY,
pCharInfo->XSize,
GUI_Context.pAFont->YSize,
GUI_Context.pAFont->XMag,
GUI_Context.pAFont->YMag,
1, /* Bits per Pixel */
BytesPerLine,
pCharInfo->pData,
&LCD_BKCOLORINDEX
)
}
/* Fill empty pixel lines */
if (GUI_Context.pAFont->YDist >GUI_Context.pAFont->YSize) {
int YMag = GUI_Context.pAFont->YMag
int YDist = GUI_Context.pAFont->YDist * YMag
int YSize = GUI_Context.pAFont->YSize * YMag
if (DrawMode != LCD_DRAWMODE_TRANS) {
LCD_COLOR OldColor = GUI_GetColor()
GUI_SetColor(GUI_GetBkColor())
LCD_FillRect(GUI_Context.DispPosX,
GUI_Context.DispPosY + YSize,
GUI_Context.DispPosX + pCharInfo->XSize,
GUI_Context.DispPosY + YDist)
GUI_SetColor(OldColor)
}
}
LCD_SetDrawMode(OldDrawMode)/* Restore draw mode */
GUI_Context.DispPosX += pCharInfo->XDist * GUI_Context.pAFont->XMag
}
}
然后再加入FLASH *** 作的底层驱动(这里用的是SPI FLASH)
/*********************************************************************
*
* Static code
*
**********************************************************************
*/
//字模数据的暂存数组,以单个字模的最大字节数为设定值
#define BYTES_PER_FONT 4*32 //最大支持32*32的汉字
static U8 GUI_FontDataBuf[BYTES_PER_FONT]
/*********************************************************************
*
* 读FLASH中的字库
*/
#include "spi_flash.h"
#include "ssp.h"
void LCD_ReadFlashBit(U32 addr,U8* buf,U8 Bytes)
{
U8 i
SPI_FLASH_StartReadSequence(addr)//设置起始地址
for(i=0i<Bytesi++)
{
buf[i] = SPI_FLASH_SendByte(0xa5)
}
SPI_FLASH_CS_HIGH()
}
我们知道,ucgui访问字库的时候,是根据字库文件的索引表来查找汉字数据地址的,因此汉字库文件中的索引也要修改,以汉字库32为例
/*
******************************************************
File Name : hzk32.C
Compiler :
Author : Liu_xf
Version : V1.0
Date : 2011-3-28 11:25:54
Description :
ucgui的中文字库,与uc工具生成的字库文件不同的是,可以将
大容量的汉字数组存入到外部的FALSH里
当然这个也是由uc工具生成的文件修改而来的。
*******************************************************
Structure :
History:
*******************************************************
*/
#include "..\core\GUI.H"
#ifndef GUI_FLASH
#define GUI_FLASH
#endif
extern GUI_FLASH const GUI_FONT GUI_FontHZ32
/*
GUI_FLASH const GUI_CHARINFO GUI_FontHZ32_CharInfo[] = {
{ 10, 10, 1, (void GUI_FLASH *)0}, // 字符在FLASH中的偏移量
{ 16, 16, 2, (void GUI_FLASH *)3840}, //汉字在FLASH中的偏移量
}
*/
GUI_FLASH const GUI_CHARINFO GUI_FontHZ32_CharInfo[] = {
// Y X X_BYTE
{ 16, 8, 1, (void GUI_FLASH *)0}, // FLASH里没有存字符,这里为0
{ 32, 32, 4, (void GUI_FLASH *)GUI_FontHZ32_Flash_BaseAddr}, //GUI_FontHZ32_Flash_BaseAddr在GUI.h中定义
}
//汉字和字符索引表//////////////////////////////////
/*鳌--齄*/
GUI_FLASH const GUI_FONT_PROP GUI_FontHZ32_Propf7a1= {
0xf7a1,
0xf7fe,
&GUI_FontHZ32_CharInfo[1],
(void *)0
}
//.....这里省略若干,详见符件里的代码
/* --〓*/
GUI_FLASH const GUI_FONT_PROP GUI_FontHZ32_Propa1a1= {
0xa1a1,
0xa1fe,
&GUI_FontHZ32_CharInfo[1],
(void *)&GUI_FontHZ32_Propa2a1
}
//ASC字符
/* --*/
GUI_FLASH const GUI_FONT_PROP GUI_FontHZ32_Prop0020= {
0x0020,
0x007f,
&GUI_FontHZ32_CharInfo[0],
(void *)&GUI_FontHZ32_Propa1a1
}
GUI_FLASH const GUI_FONT GUI_FontHZ32 = {
GUI_FONTTYPE_PROP_SJIS,
32,
32,
1,
1,
(void GUI_FLASH *)&GUI_FontHZ32_Prop0020
}
在GUI.H中添加汉字库在flash中的首地址,及字库声明
/*汉字*/
//汉字库在FLASH中的首地址
#define GUI_FontHZ16_Flash_BaseAddr 0x0
#define GUI_FontHZ24_Flash_BaseAddr 0x00045080
#define GUI_FontHZ32_Flash_BaseAddr 0x000E05A0
extern GUI_CONST_STORAGE GUI_FONT GUI_FontHZ16
extern GUI_CONST_STORAGE GUI_FONT GUI_FontHZ24
extern GUI_CONST_STORAGE GUI_FONT GUI_FontHZ32
然后将字库下载到SPI FLASH中,注意三个字库的起始地址与GUI.h中定义的应该是一样的。还有字库生成时,也应该是标准的汉字库,满足 oft = base + (((c>>8) - 0xa1) * 94 + ((c&0xff) - 0xa1)) * BytesPerFont的计算方式。
结语:
有了将汉字库定义到外部FLASH的方法,则可以定义任意汉字库,不受程序FLASH大小的限制了。
举个例子,你要生成汉字“你好”;
在左编辑框内输入你好,选择你喜欢的字体,大小。
选择你要生成的字模的大小,即右边的宽和高。
至于要不要加ASCII表,看你有没有需求。
然后点击转换。
#include "GUI.H"
/* char: 好 code:0xBAC3 */
unsigned char acFontHZ_BAC3[24] = {
__X_____,________,
__X__XXX,XXX_____,
__X_____,_X______,
XXXXX___,X_______,
_X__X___,X_______,
_X__XXXX,XXXX____,
X___X___,X_______,
_X_X____,X_______,
__X_____,X_______,
_X_X____,X_______,
X___X___,X_______,
_______X,X_______
}
/* char: 你 code:0xC4E3 */
unsigned char acFontHZ_C4E3[24] = {
___X__X_,________,
___X__X_,________,
__X___XX,XXXX____,
__X__X__,___X____,
_XX_X__X,__X_____,
X_X____X,________,
__X__X_X,_X______,
__X__X_X,__X_____,
__X_X__X,___X____,
__XX___X,___X____,
__X____X,________,
__X___XX,________
}
GUI_CHARINFO GUI_FontHZ_12x12_CharInfo[2] = {
{ 12, 12, 2, (unsigned char *)&acFontHZ_BAC3 }, /*0: 好*/
{ 12, 12, 2, (unsigned char *)&acFontHZ_C4E3 }, /*1: 你*/
}
GUI_FONT_PROP GUI_FontHZ_12x12_Prop2 = {
0xC4E3, /*start :你*/
0xC4E3, /*end :你, len=1*/
&GUI_FontHZ_12x12_CharInfo[ 1 ],
(void*)0
}
GUI_FONT_PROP GUI_FontHZ_12x12_Prop1 = {
0xBAC3, /*start :好*/
0xBAC3, /*end :好, len=1*/
&GUI_FontHZ_12x12_CharInfo[ 0 ],
&GUI_FontHZ_12x12_Prop2
}
GUI_FONT GUI_FontHZ12x12 = {
GUI_FONTTYPE_PROP_SJIS,
12,
12,
1,
1,
&GUI_FontHZ_12x12_Prop1
}
这是转换后的文件,把他保存为*.c文件。
然后在要用汉字的文件中声明
extern GUI_FONT GUI_FontHZ12x12
然后调用即可。
BUTTON_SetDefaultFont(&GUI_FontHZ12x12)
UCGUI多级菜单设计1 建立UCGUI主菜单
1.1 利用建立窗口函数来建立主菜单界面
用户通过利用UCGUI中WM_CreateWindow函数建立一个指定大小的窗口。
窗口对话框建立函数
GUI_CreateDialogBox(const GUI_WIDGET_CREATE_INFO* paWidget, int NumWidgets, WM_CALLBACK* cb, WM_HWIN hParent, int x0, int y0)
paWidge,对话框信息结构体,包含了对话框所有的信息,对话框中的各个部件都在该信息结构体中被设置好。
NumWidgets,对话框中所有部件的个数。
cb,窗口回调函数。
hParent,窗口父窗口的句柄。
x0,y0,窗口建立时起始位置。
扩展型窗口对话框建立函数:
GUI_ExecDialogBox(const GUI_WIDGET_CREATE_INFO* paWidget,int NumWidgets, WM_CALLBACK* WM_HWIN hParent, int x0, int y0)
paWidget,窗口信息。
NumWidgets,窗口部件数目。
cb,,窗口回调函数。
hParent,父窗口句柄。
x0,y0,窗口建立时起始位置。
1.2 回调函数
一般来说,每一个窗口的建立都会附带有一个属于该窗口的回调函数,利用回调函数来实时更新窗口的内容。
UCGUI中为窗口和窗口对象(控件)提供的回调机制实质上是一个事件驱动系统。正如在大多数视窗系统中一样,原则是控制流程不只是从用户程序到图形系统(用户程序调用图形系统函数来更新窗口),而且可以从用户程序到图形系统,同时也可以从图形系统回到用户程序,意思是图形系统也可以调用用户程序提供的回调函数来达到更新窗口的目的。这种机制常常表现好莱坞法则的特点(“不要打电话给我们,我们会打电话给你”)---主要是视窗管理器为了启动窗口重绘的需要。与传统程序比较有差异,但它使对视窗管理器的无效逻辑开发成为可能。
回调函数的执行行为依赖于它收到的消息类型。上面的函数原型通常带有一个开关声明,用于定义了对于不同的使用一个或者更多的事件声明的消息所采用的不同的处理方式(典型的至少有对WM_PAINT()的处理)。
回调函数需要获得的信息包括有:目标窗口、目标窗口的消息、源窗口、源窗口下部件的ID等信息。
回调函数中可以通过获取目标窗口,然后在获取目标窗口下的各个部件的ID,这时可以根据窗口的消息类型来初始化各个部件,如消息是WM_INIT_DIALOG时,可以直接对窗口进行初始化设置,例如设置按钮按下之后的背景色、设置窗口的字体大小等。如果要使用回调函数实时更新各个窗口,必须要运行GUI_Exec()或WM_Exec函数。
1.3 常用窗口初始化函数解析
窗口初始化方式有两种,一种是在新建窗口时初始化,第二种则是利用回调函数初始化窗口。使用在新建窗口时初始化的方法与回调函数中初始化窗口差不多,在新建窗口时给窗口一个指定的句柄,在利用常用的窗口初始化函数对窗口句柄进行初始化即可。
在回调函数中对窗口初始化应该注意,进入回调函数就立即获取窗口句柄,同时必须要用缓存保存从窗口中获取的各个部件的ID。
获取窗口部件函数如下:
WM_HWIN _GetDialogItem(WM_HWIN hWin, int Id)函数从窗口中获取各个部件的ID。
hWin,为部件所在窗体的源窗口句柄,Id为建立控件时为控件设置的ID。在窗体回调函数中必须要注意WM_HWIN _GetDialogItem函数调用的位置,在WN_INIT_DIALOG前调用还是在其后调用所得到的结果不同。通过调整该函数在回调函数中所在的位置来确定程序能否正常运行。
对于窗口名的设置用FRAMEWIN的相关函数。常用的函数原型如下有:
设置窗口标题的字体大小函数:
FRAMEWIN_SetFont(FRAMEWIN_Handle hObj, const GUI_FONT GUI_UNI_PTR * pFont)。
FRAMEWIN_Handle,为所建立的窗口的句柄,不需要调用窗口部件获取函数去获取其部件ID,只需要在进入回调函数时调用获取源窗口句柄函数(pMsg->hWin)即可实现。
* pFont为窗口标题的字体,一般用GUI.H中UCGUI自带的字体即可,用户也可自定义GUI支持的字体,GUI自带的字体只支持英文的,不支持中文字体,如果需要显示中文字体,用户要用GUI字库生成软件生成,在添加进工程才行。
设置窗口标题字体显示的对齐方式函数:
FRAMEWIN_SetTextAlign(FRAMEWIN_Handle hObj, int Align)
hObj为源窗口句柄,Align为窗体标题显示对齐方式,其取值一般有:左对齐,右对齐,居中等,这些参数在GUI.H函数中已经被定义为宏,用户根据需要直接使用即可。
设置窗口标题的显示颜色:
FRAMEWIN_SetTextColor (FRAMEWIN_Handle hObj, GUI_COLOR Color)
hObj为源窗口句柄,Color为标题颜色,参数在GUI.H中被定义为宏。
设置窗口标题栏高度:
FRAMEWIN_SetTitleHeight (FRAMEWIN_Handle hObj, int Height)
hObj为窗口句柄,Height为标题栏高度
为窗口中添加关闭窗口按钮:
FRAMEWIN_AddCloseButton(FRAMEWIN_Handle hObj, int Flags, int Off)。
hObj为要添加按钮的窗口句柄。Flags为添加的按钮的显示方式,基本参数为FRAMEWIN_BUTTON_RIGHT或FRAMEWIN_BUTTON_LEFT,即将该关闭窗口按钮显示在窗口的最左端或是最右端。
为窗口添加最大化显示按钮:
FRAMEWIN_AddMaxButton(FRAMEWIN_Handle hObj, int Flags, int Off)与上述添加关闭窗口按钮原理相同。
为窗口添加最小化按钮:
FRAMEWIN_AddMinButton(FRAMEWIN_Handle hObj, int Flags, int Off),如上同理。一般情况下,这三个函数在窗体初始化时同时使用。
窗口BUTTON部件常用设置函数如下:
设置按钮显示的字体
BUTTON_SetFont(BUTTON_Handle hObj, const GUI_FONT GUI_UNI_PTR * pfont)
hObj为BUTTON部件句柄,在设置之前应该从窗口中获取,pfont按钮显示字体,GUI默认只能支持英文。
设置按钮按下或没有按下时的背景色
BUTTON_SetBkColor(BUTTON_Handle hObj,unsigned int Index, GUI_COLOR Color)
hObj为BUTTON部件句柄,Index为索引,0表示按钮没有按下,1表示按钮按下,Color为BUTTON的背景色。
设置按钮按下或是没有按下时,按钮上的文字的颜色:
BUTTON_SetTextColor(BUTTON_Handle hObj,unsigned int Index, GUI_COLOR Color)
hObj为BUTTON部件句柄,Index为索引,0表示按钮没有按下,1表示按钮按下,Color为文字颜色。
常用LISTBOX设置函数如下。
设置LISTBOX显示内容的字体:
LISTBOX_SetFont(LISTBOX_Handle hObj, const GUI_FONT GUI_UNI_PTR * pFont)
hObj为LISTBOX部件句柄,pFont为在LISTBOX中显示内容的字体,GUI默认只支持英文,中文字体需要用户自己添加。
往LISTBOX中添加内容:
LISTBOX_AddString (LISTBOX_Handle hObj, const char* s)
hObj为LISTBOX部件句柄,*s为要添加的内容,一般为字符串。
高亮LISTBOX中的上一个目录:
LISTBOX_DecSel (LISTBOX_Handle hObj)
高亮LISTBOX中的下一个目录:
LISTBOX_IncSel (LISTBOX_Handle hObj)
hObj为LISTBOX部件句柄。
获取LISTBOX中高亮目录:
LISTBOX_GetSel (LISTBOX_Handle hObj)
hObj,LISTBOX部件句柄,返回的是该目录在LISTBOX中的序号。获取LISTBOX中高亮目录的内容
LISTBOX_GetItemText (LISTBOX_Handle hObj, unsigned Index, char * pBuffer, int MaxSize)
hObj为LISTBOX部件句柄,Index为高亮目录在LISTBOX中的序号,* pBuffer为该目录内容的缓存区,MaxSize为高亮目录最大字节数。
设置LISTBOX的水平自动滚动步进:
LISTBOX_SetAutoScrollH (LISTBOX_Handle hObj, int OnOff)
hObj为LISTBOX部件句柄,OnOff为点击LISTBOX滑动条时,窗口目录自动水平滚动步进的大小。
设置LISTBOX的垂直自动滚动步进:
LISTBOX_SetAutoScrollV (LISTBOX_Handle hObj, int OnOff)
hObj为LISTBOX部件句柄,OnOff为点击LISTBOX滑动条时,窗口目录自动垂直滚动步进的大小。
设置LISTBOX目录水平卷动步进:
LISTBOX_SetScrollStepH (LISTBOX_Handle hObj, int Value)
hObj为LISTBOX部件句柄,Value为步进大小。
在执行回调函数中响应源窗口下的各个部件动作的时候,一般是在WM_NOTIFY_PARENT消息下来进行。在WM_NOTIFY_PARENT消息下,获取源窗口各个部件的ID以及窗口部件的数值。
如图所示,先判断目标窗口返回的消息是否是WM_NOTIFY_PARENT,如果是则获取源窗口返回的Id和消息的数值。根据消息的数值再去判断Id属于哪个部件,然后根据部件的动作,实现不同的 *** 作。
2 主菜单下子菜单的添加与功能设置
2.1建立菜单
MENU_CreateEx(int x0, int y0, int xSize, int ySize, WM_HWIN hParent, int WinFlags, int ExFlags, int Id)
x0,y0,菜单起始坐标;
xSize,ySize,菜单框的宽度与高度;
hParent,菜单所在父窗口句柄;
WinFlags,菜单显示属性;
ExFlags,菜单框属性;
Id,菜单框ID;
先利用直接建立菜单函数建立一个空菜单框,然后再往空菜单框中添加子菜单,来实现一个菜单栏下有多级子菜单的效果。
在主菜单栏下添加子菜单实现方法
先建立一个菜单栏结构体(MENU_ITEM_DATA 为菜单结构体),然后对结构体内的各个成员初始化赋值即可。
hMenu, 为主菜单句柄,即该子菜单所在的菜单栏的句柄。
hSubmenu,为该子菜单的句柄。
*pText, 为子菜单名称。
Id, 为当前子菜单的ID。
Flags,为当前子菜单的附加属性。
常用建立添加有子菜单栏的菜单栏方法
先建立一个主菜单,然后在该主菜单栏下添加子菜单即可实现。添加完子菜单之后,用户只需要点击相应的菜单该菜单下的子菜单会自动d出,无需用户自己写d出函数。
在前一子菜单与后一子菜单之间加一条分隔线:
_AddTaskMenuItem(hMenuStart,0,0,0,MENU_IF_SEPARATOR)
将已经准备好的菜单粘贴到指定的窗口上:
MENU_Attach(MENU_Handle hObj, WM_HWIN hDestWin, int x, int y, int xSize, int ySize, int Flags)
hObj,菜单句柄。
hDestWin,窗口句柄。
x,y,xSize,ySize,为菜单在窗口中的位置及菜单的高度与宽度。
Flags,菜单显示属性。
2.2 菜单回调函数
菜单回调函数通常写法
菜单建立之后返回的消息
MENU_ON_ITEMSELECT,当该菜单被选择时所收到的消息。
MENU_ON_INITMENU,对建立的菜单初始化。
MENU_ON_ITEMSELECT,当前菜单被选择时所收到的消息,根据该消息再来判断该菜单下子菜单的ID。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)