电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
STemWin开发过程中遇到的二三事
分 享
扫描二维码分享
STemWin开发过程中遇到的二三事
STemWin
STM32
GUI
IAMLIUBO
关注
发布时间: 2020-04-01
丨
阅读: 2718
# 前言 最近负责的产品是一个小型网关,搭载了一块3.5寸的显示屏,需要实时显示一部分数据,还能进行参数设置,为了方便的管理多个窗口和界面的内容展示,所以这里采用了STemWin,因为使用的主控芯片是STM32F29,所以可以免费使用STemWin,开发过程中遇到了部分问题,这里记录一下,方便自己查阅,也希望可以帮助到正在看文章的你。 # 记录 ## 1.Keil字符编码对中文显示的影响 在开发过程中发现中文字符显示有问题,但是中文字库都是已经转换好的,刚开始不知道是什么原因,通过与同事探讨才发现了问题所在。 ### 原因 文件默认的字符编码格式与字库索引的编码格式不同导致的。 大家应该知道我们平常使用Keil的时候中文注释会出现乱码,一个中文字符会被拆分成两个字符,因为这是使用的 **Encode in ANSI** 编码格式,我们来看一下 **Encode in ANSI** 编码格式的百科: >ANSI是一种字符代码,为使计算机支持更多语言,通常使用 0x00~0x7f 范围的1 个字节来表示 1 个英文字符。超出此范围的使用0x80~0xFFFF来编码,即扩展的ASCII编码。 >为使计算机支持更多语言,通常使用 0x80~0xFFFF 范围的 2 个字节来表示 1 个字符。比如:汉字 '中' 在中文操作系统中,使用 [0xD6,0xD0] 这两个字节存储。 可以看出,由于一个中文符号被拆分成两个字节来保存,所以就导致假如你用中文注释的时候,会因为删除中间的一个字符导致后面的字符全乱码,大家可以自己尝试下。 正式由于这个原因,导致我想要在显示屏上显示中文字符的时候没法正确索引到正确汉字的位置,从而无法显示出中文来。 ### 解决办法 解决办法也很简单,我们只需要将字符的编码格式修改一下即可,如下图:  将**Encode in ANSI**修改为**Encode in UTF-8 without signature**即可,下面是中文显示效果:  不过还有几个字没有制作进字库当中去,所以没有显示,大家能猜出是哪几个字吗? ## 2.DialogBox窗口不支持定时器 因为想在某个子窗口上实时更新一些数据,原本以为直接用STemWin的定时器就可以搞定了,由于子窗口是通过 **GUI_CreateDialogBox** 函数创建的,也就是我们常说的对话框,但是居然不起作用!但是安富莱的例程也是这样用的,这就有点让我摸不到头脑了。 搜索了一下,发现大家也都遇到类似的问题,但是都没有很好的解决方案,经过跟领导的探讨,终于通过另一种方式将这个问题解决掉了,这里分享出来给大家参考,当然不一定是最好的方案,但是因为项目急,暂且先用着吧。 ### 解决办法 建立一个子窗口,当然这个子窗口是一个空窗口,我们在这个子窗口的定时器中不断无效化你要定时刷新的界面,从而达到窗口重绘的效果,下面展示部分代码: ```C //主要处理定时器的回调 static void _cbTimerWindow(WM_MESSAGE *pMsg) { static WM_HTIMER hTimerTime2; switch(pMsg->MsgId) { case WM_CREATE: /@@* Create timer */ hTimerTime2 = WM_CreateTimer(pMsg->hWin, ID_TIMER_TIME2, 1000, 0); break; case WM_TIMER: /@@* Reset Timer */ //我们通过无效化你要刷新数据界面,从而进入窗口重绘选项,之所以这样做,是因为直接在Dialog中定时器不起作用 WM_InvalidateWindow(WM_GetClientWindow(TempWin)); WM_RestartTimer(pMsg->Data.v, 1000); break; case WM_DELETE: WM_DeleteTimer(hTimerTime2); break; default: WM_DefaultProc(pMsg); } } //下图左侧的按钮界面的回调函数 static void _cbDeviceInfoMenuDialog(WM_MESSAGE *pMsg) { WM_HWIN hItem; int NCode; int Id; // USER START (Optionally insert additional variables) // USER END switch(pMsg->MsgId) { case WM_INIT_DIALOG: // // Initialization of 'DeviceInfo' // hItem = pMsg->hWin; FRAMEWIN_SetTitleVis(hItem, 0); // USER START (Optionally insert additional code for further widget initialization) BUTTON_SetFont(WM_GetDialogItem(hItem, ID_BUTTON_0), &GUI_FontHeiTi_12); BUTTON_SetFont(WM_GetDialogItem(hItem, ID_BUTTON_1), &GUI_FontHeiTi_12); BUTTON_SetFont(WM_GetDialogItem(hItem, ID_BUTTON_2), &GUI_FontHeiTi_12); BUTTON_SetFont(WM_GetDialogItem(hItem, ID_BUTTON_3), &GUI_FontHeiTi_12); //下面这条语句就是建立的子窗口,其中区域建议大家选在你要更新的界面区域中,我们在_cbTimerWindow这个回调函数中处理定时器 WM_CreateWindowAsChild(80, 45, 200, 40, pMsg->hWin, WM_CF_SHOW | WM_CF_HASTRANS, _cbTimerWindow, 0); // USER END break; case WM_NOTIFY_PARENT: Id = WM_GetId(pMsg->hWinSrc); NCode = pMsg->Data.v; switch(Id) { case ID_BUTTON_0: // Notifications sent by 'DateTime' switch(NCode) { // USER START (Optionally insert additional code for further notification handling) case WM_NOTIFICATION_GOT_FOCUS: //按钮0获取到焦点展示界面1 BUTTON_SetTextColor(WM_GetDialogItem(pMsg->hWin, ID_BUTTON_0), BUTTON_CI_UNPRESSED, GUI_RED); TempWin = GUI_CreateDialogBox(_aDatetimeCreate, GUI_COUNTOF(_aDatetimeCreate), _cbDatetimeDialog, WM_GetParent(pMsg->hWin), 0, 0); break; case WM_NOTIFICATION_LOST_FOCUS: //按钮0失去焦点结束界面1 BUTTON_SetTextColor(WM_GetDialogItem(pMsg->hWin, ID_BUTTON_0), BUTTON_CI_UNPRESSED, GUI_BLACK); GUI_EndDialog(TempWin, 0); break; // USER END } break; } break; // USER START (Optionally insert additional message handling) case WM_KEY: switch(((WM_KEY_INFO *)(pMsg->Data.p))->Key) { case GUI_KEY_ESCAPE: brea; } break; // USER END default: WM_DefaultProc(pMsg); break; } } //主要处理界面的刷新 static void _cbDatetimeDialog(WM_MESSAGE *pMsg) { WM_HWIN hItem; // USER START (Optionally insert additional variables) char dateTimeTemp[48] = {0}; // USER END hItem = pMsg->hWin; switch(pMsg->MsgId) { case WM_INIT_DIALOG: // // Initialization of 'Datetime' // // FRAMEWIN_SetTitleVis(hItem, 0); // // Initialization of 'Date' // hItem = WM_GetDialogItem(hItem, ID_TEXT_YEAR); TEXT_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER); // USER START (Optionally insert additional code for further widget initialization) // USER END break; // USER START (Optionally insert additional message handling) case WM_KEY: case WM_PAINT: //每次进入更新当前时间 GUI_DrawBitmap(&bmdate, 10, 10); sprintf(dateTimeTemp, "%4d年", pClock_DateTime->TYY); TEXT_SetFont(WM_GetDialogItem(hItem, ID_TEXT_YEAR), &GUI_FontHeiTi_20); TEXT_SetText(WM_GetDialogItem(hItem, ID_TEXT_YEAR), dateTimeTemp); sprintf(dateTimeTemp, "%02d月", pClock_DateTime->TMD); TEXT_SetFont(WM_GetDialogItem(hItem, ID_TEXT_MONTH), &GUI_FontHeiTi_20); TEXT_SetText(WM_GetDialogItem(hItem, ID_TEXT_MONTH), dateTimeTemp); sprintf(dateTimeTemp, "%02d日", pClock_DateTime->TDD); TEXT_SetFont(WM_GetDialogItem(hItem, ID_TEXT_DATE), &GUI_FontHeiTi_20); TEXT_SetText(WM_GetDialogItem(hItem, ID_TEXT_DATE), dateTimeTemp); sprintf(dateTimeTemp, "%02d时", pClock_DateTime->THH); TEXT_SetFont(WM_GetDialogItem(hItem, ID_TEXT_HOURS), &GUI_FontHeiTi_20); TEXT_SetText(WM_GetDialogItem(hItem, ID_TEXT_HOURS), dateTimeTemp); sprintf(dateTimeTemp, "%02d分", pClock_DateTime->TMM); TEXT_SetFont(WM_GetDialogItem(hItem, ID_TEXT_MINUTE), &GUI_FontHeiTi_20); TEXT_SetText(WM_GetDialogItem(hItem, ID_TEXT_MINUTE), dateTimeTemp); sprintf(dateTimeTemp, "%02d秒", pClock_DateTime->TSS); TEXT_SetFont(WM_GetDialogItem(hItem, ID_TEXT_SECOND), &GUI_FontHeiTi_20); TEXT_SetText(WM_GetDialogItem(hItem, ID_TEXT_SECOND), dateTimeTemp); //系统自上电依赖运行的时间,以天数为最小单位 GUI_SetFont(&GUI_FontHeiTi_20); GUI_SetColor(GUI_BLACK); sprintf(dateTimeTemp, "系统已运行%3d天", 48); GUI_DispStringAt(dateTimeTemp, 40, 125); break; // USER END default: WM_DefaultProc(pMsg); break; } } ``` 经过测试,上面的代码是可以正常运行并使用的,目前只能通过这种方式先解决了,后面有时间再研究一下,下面是效果演示:  ## 3.批量转换图标到代码脚本 项目用到了不少图标,这些图标都是我从[iconfont](https://www.iconfont.cn/)上下载的,这上面有很多不错的图标,建议大家有需求也可以去看一下,由于我下载的小图标有点多,而且一个个的转换起来有点复杂,所以就用Python写了个小脚本,批量将图片转换成C代码,当然脚本也很简单,主要就是调用了一下**BmoCvt.exe**这个官方给的工具,下面分享给大家: ```python # -*- coding: utf-8 -*- # author: IAMLIUBO # blog: https://blogs.oopswow.com import os import sys,time from PIL import Image IMAGE_FILTE = ".PNG .png .JPEG .jpeg .jpg .BMP .bmp" CODE_DIR = "C_CODE/" def ConvertImage2Code(path): image_list = os.listdir(path) if not os.path.exists(path + "/../" + CODE_DIR): os.mkdir(path + "/../" + CODE_DIR) for i in image_list: if os.path.splitext(i)[1] in IMAGE_FILTE: code_save_path = CODE_DIR + i.split('.')[0] command = "BmpCvt.exe " + i + " -saveas" + code_save_path + ",1,16 -exit" os.system(command) print("Convert done!") def main(): if len(sys.argv) < 2: print("\r\nNo image folder path provided\r\n" "Usage:\r\n" " python Image2Code4STemWin.py [image folder path]") exit() if not os.path.exists("BmpCvt.exe"): print("\r\nPlease put BmpCvt.exe to this folder.\r\n") exit() print("\r\nImage to C code script for STemWin by IAMLIUBO.\r\n" " 1.Convert the image to C code(true color with alpha channel use BmpCvt.exe).\r\n") ConvertImage2Code(sys.argv[1]) if __name__ == '__main__': main() ``` 记得使用的时候将**BmpCvt.exe**这个工具放到当前目录下,然后指定图像文件的路径即可,像下面一样: ```bash python Image2Code4STemWin.py images ``` 完成后会在当前目录下生成一个**C_CODE**文件夹,里面就是转换完成后的代码文件了。 自动化思想很重要呀,有时候程序要比人更可靠,而且非常适合重复性工作。 # 随时更新... >Post author: IAMLIUBO >Post date: Wed Mar 25 2020 15:10:52 GMT+0800 >Post link: https://blogs.oopswow.com/2020/03/25/STemWin-development-issue-record/ >Copyright Notice: All articles in this blog are licensed under CC BY-NC-ND 4.0 unless stating additionally.Commercial reprint please contact me by email.
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
1
)
IAMLIUBO
擅长:工控电子 能源电源 光电显示 设计,制造及服务 智能硬件
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交