在前几天调试通了字库芯片取模的代码部分,然后就想可不可以直接使用字库芯片而不再用emwin的字库工具生成的方式来设置控件的文字内容。网上搜索了一些资料,没有找到满意的答案,自己动手实现了一个按钮控件的。觉得有点麻烦,准备放弃了,毕竟对于按钮来说不会没事就更换按钮上的文字,还是采用传统的方式为好。反倒是像text,edit,multiedit等控件更需要能够支持字库芯片。那是后续的事情了,我先把按钮的实现方式发出来,给大家一个参考:其实说白了也没啥,就是自己实现按钮控件的回调函数,在WM_PAINT响应事件中按照自己的需求对按钮进行绘制。这里面涉及到一个问题,就是屏幕坐标的转换。我没有使用emwin提供的字符串显示接口函数,而是用自己写的函数替代,不知道有没有什么问题,下面是实现的代码。先贴一个直接向屏幕写字符串的函数,这个是不擦除背景图案直接写字符串的,可以中英文混合输入,可以通过space指定字符间距,参数ZTN是指定字号大小
uint8_t ShowStr2LCDWithBg(uint16_t x,uint16_t y,uint8_t ZTN,char*str,uint16_t clr,uint8_t space)
{//不擦除原有背景颜色,直接写文字
uint8_t w,detx;
uint16_t i,j;
uint8_t data;
uint8_t*lpData;
while(*str!=0)
{
//字库芯片bug,调用前必须对缓存清零,不清零会有错误,见上一篇文章
memset(&gFont16,0,sizeof(gFont16));
gFont16.size=ZTN;
gFont16.thick=(ZTN*3)/4;;
if((*str&0x80)==0x80)
{//这是汉字
if((*(str+1)&0x80)!=0x80)
{//半个汉字,不显示了
str++;
}else
{
gFont16.type=VEC_SONG_STY;
gFont16.fontCode=*str;
gFont16.fontCode<<=8;
str++;
gFont16.fontCode+=*str;
}
detx =ZTN;
}else
{//这是英文字符
gFont16.type=VEC_FT_ASCII_STY;
gFont16.fontCode=*str;
detx =ZTN/2;
}
str++;
//从字库芯片读取字模
w=get_font_st(&gFont16);
//获取字模的宽度w,一般会比要求的字体宽
lpData = gFont16.zkBuffer;
if((x+w)<lcddev.width)
{
for(i=0;i<ZTN;i++)
{
for(j=0;j<w;j++)
{
if((j&0x07)==0)
{
data = *lpData;
lpData++;
}
if(j<ZTN)
{//超出字体宽度部分不显示
if((data&0x80)==0x80)
{
lcd_draw_point(x+j,y+i,clr);
}
data<<=1;
}
}
}
}else
{
return 1;
}
x+=detx;
x+=space;
}
return 0;
}
如果需要擦除原有背景颜色,稍微修改一下上面的代码为if((data&0x80)==0x80)添加else部分就行了。
下面是按钮部分的代码实现,用BUTTON_CreateEx()函数创建一个button,指定回调函数,具体代码如下:
hItem=BUTTON_CreateEx(x,y,w,h,pageHand,WM_CF_SHOW,0,BUTTON_ID_USER);
if(hItem!=NULL)
{
BUTTON_SetText(hItem,"测试");
WM_SetHasTrans(hItem);
WM_SetCallback(hItem,_cb_MyBtn);
}
这样就在客户区的窗口位置x,y的位置创建了一个宽度为w,高度为h,ID为BUTTON_ID_USER的一个按钮,如果直接运行,按钮上是没有文字的。下面需要我们通过回调函数_cb_MyBtn()来画出我们的按钮,我的代码是实现一个圆角矩形按钮,选中时和非选中状态有不同的按钮颜色,具体实现如下:
static void _cb_MyBtn(WM_MESSAGE * pMsg)
{//有多个按钮,所有按钮共用这一个回调函数
WM_HWIN hSel;
GUI_RECT Rect;
uint16_t StrW;
uint16_t orgX,orgY;
uint16_t tColor;
char btnText[20];
switch(pMsg->MsgId)
{
case WM_PAINT:
//设置圆角区域之外的地方为背景色
GUI_SetBkColor(CLIENT_AREA_COLOR);
GUI_Clear();
//得到按钮的显示区域
WM_GetClientRect(&Rect);
//因为有很多按钮,用了一个全局数组存储了各个按钮的id,判断当前的按钮是否为选中状态
hSel = WM_GetDialogItem(gMPage.pageHand,MPagewgList[gMPage.selIndex]);
if(hSel==pMsg->hWin)
{//如果时选中的按钮
//设置按钮区域为选中的颜色
GUI_SetBkColor(MEASURE_SELECTED_COLOR);
GUI_SetColor(MEASURE_SELECTED_COLOR);
//填充圆角矩形区域
GUI_FillRoundedRect(Rect.x0, Rect.y0, Rect.x1, Rect.y1, 10);
//GUI_SetColor(GUI_WHITE);
//设置选中以后的文字颜色,注意emwin使用的时4字节带alpha信息测存储方式。而我这里使用的时RGB565的形式,所以单独用一个变量来存储颜色
tColor =WHITE;
}
else
{//非选中的按钮
GUI_SetBkColor(BUTTON_COLOR);
GUI_SetColor(BUTTON_COLOR);
GUI_FillRoundedRect(Rect.x0, Rect.y0, Rect.x1, Rect.y1, 10);
//GUI_SetColor(GUI_BLACK);
tColor =BLACK;
}
//获取按钮的文字信息
BUTTON_GetText(pMsg->hWin,btnText,20);
//GUI_SetFont(BUTTON_GetFont(pMsg->hWin));
//这里我要把文字现在在按钮靠上居中的位置,这里Rect中的坐标是控件内的相对坐标不是屏幕的绝对坐标
Rect.y0+=5;
//下面计算显示的字符串占多宽
StrW = GUI__strlen(btnText);
StrW*=18;//汉字宽度,根据实际情况自己修改
StrW/=4; //每个汉字占2字节,先除以2,然后再取显示的一半宽度,再次除以2
//获取当前按钮控件在屏幕上的绝对坐标
orgX = WM_GetWindowOrgX(pMsg->hWin);
orgY = WM_GetWindowOrgY(pMsg->hWin);
//直接到屏幕上显示汉字
ShowStr2LCDWithBg(orgX+(Rect.x1-Rect.x0)/2-StrW,Rect.y0+orgY,18,btnText,tColor,0);
//GUI_DispStringInRect(btnText, &Rect, GUI_TA_HCENTER | GUI_TA_TOP);
break;
default:
BUTTON_Callback(pMsg);
break;
}
}
通过以上的代码,就可以实现从字库芯片读取字模,然后更新emwin按钮控件的文本信息。
520

被折叠的 条评论
为什么被折叠?



