野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 15888|回复: 10

[emWin] 如何在VS2019的emwin模拟器中显示中文

[复制链接]
发表于 2020-4-29 23:13:11 | 显示全部楼层 |阅读模式
本帖最后由 ZZZ_XXJ 于 2020-5-18 00:25 编辑

由于软硬件平台的差异,emwin模拟器工程显示中文的方法与在stm32上用的方法有所不同。在VS2019中,根据想模拟的内容和实现方法大致可以分成两种方法,下面就来讲下具体怎么显示。


  • 准备工作

1. 在讲之前需要先对VS2019进行一些设置,首先打开emwin模拟器工程,在界面左上角点击文件->高级保存选项。如果没有这个选项的可以照这个链接进行设置:VS2019 设置显示”高级保存选项“
2020-04-29_21-42-02.bmp


2. 在高级保存选项中,选择编码为:Unicode(UTF-8带签名),这里设置的是包含待显示中文字符的文件,比如MainTask.c中要显示中文,则必须在VS2019主界面切换到该文件后再设置
2020-04-29_21-47-12.bmp


3. 右键模拟器工程名,在弹出的菜单中点击属性。
2020-04-29_22-01-57.bmp

4. 在弹出来的属性页面中,点击C/C++左边的箭头,找到命令行页面,然后在其他选项里添加:/utf-8
2020-04-29_22-05-12.bmp
到这准备工作就做完了。


  • 中文显示方法一:

第一种方法很简单,只需要用字体转换软件FontCvST生成.c格式字库,然后把字库文件添加到模拟工程中就可以了。如果能确定界面需要的中文字符个数,推荐方法一。如果不能确定中文字符个数,那只能用方法二。
FontCvST的使用方法已经在野火《emWin 应用开发实战》的第38章第1小节有详细讲解,在这里就不重复讲了。c字库文件的生成步骤和教程中基本一致,唯一不同的是保存。

1. 保存c格式字库到emwin模拟器工程的Sample文件夹下,保存类型选择c-files,文件名不能有中文和空格。
2020-04-29_21-10-55.bmp

2. 把生成好的字库文件添加模拟器工程中,添加步骤在野火《emWin 应用开发实战》第4章第4小节有详细介绍,在此不再重复。
    打开字库文件可以看到有个变量GUI_FontSiyuanheiti_Medium64,这个就是用来给其他文件调用的字体变量
2020-04-29_21-10-00.bmp


3. 把字体变量添加到需要显示中文的文件中,这里直接上代码。添加好之后在MainTask函数中启用UTF-8编码,然后像选择普通字体一样选择GUI_FontSiyuanheiti_Medium64,就可以显示中文了。
  1. #include "GUI.h"

  2. /*********************************************************************
  3. *
  4. *       Static data
  5. *
  6. **********************************************************************
  7. */
  8. GUI_CONST_STORAGE GUI_FONT GUI_FontSiyuanheiti_Medium64;

  9. /*********************************************************************
  10. *
  11. *       Static code
  12. *
  13. **********************************************************************
  14. */

  15. /**
  16.   * [url=home.php?mod=space&uid=41770]@brief[/url] GUI主任务
  17.   * @note 无
  18.   * @param 无
  19.   * @retval 无
  20.   */
  21. void MainTask(void)
  22. {
  23.         GUI_Init();

  24.         /* 启用UTF-8编码 */
  25.         GUI_UC_SetEncodeUTF8();

  26.         /* 选择字体 */
  27.         GUI_SetFont(&GUI_FontSiyuanheiti_Medium64);

  28.         GUI_SetColor(GUI_CYAN);
  29.         GUI_DispString("VS2019上的emwin模拟器中文显示示例");

  30.         while(1)
  31.         {
  32.                 GUI_Delay(100);
  33.         }
  34. }
复制代码

显示效果
2020-04-29_23-19-49.bmp

把stm32的emWin中文显示例程直接移植到模拟器上,就可以用第一种方法。
只添加MainTask.c到工程,把文件中所有跟emwin无关的头文件和代码全部删除,MainTask函数中创建字体的函数也删掉,然后按照上面的步骤即可。

  • 中文显示方法二:

如果不确定仿真界面的中文字符数量那么就只能用方法二。这种方法因为涉及到Win32 API, 所以要复杂些,但是好处是不限制字库文件格式,XBF、SIF,甚至TTF格式都能显示。其实说复杂也不复杂,就只是把外部字库显示例程里的GUIFont_Create.c的文件读取部分修改下即可,我就直接上代码了。


首先是XBF格式的文件读取部分:
  1. /* 字库文件路径,最长不超过260字符 */
  2. char   FONT_XINSONGTI_18_ADDR[_MAX_PATH] = { "Sample\\新宋体18.xbf" };
  3. char   FONT_SIYUANHEITI_36_ADDR[_MAX_PATH] = { "Sample\\思源黑体36_2bpp.xbf" };
  4. /**
  5.   * @brief  获取字体数据的回调函数
  6.   * @param  Offset:要读取的内容在XBF文件中的偏移位置
  7.   * @param  NumBytes:要读取的字节数
  8.         * @param  pVoid:自定义数据的指针
  9.   * @param  pBuffer:存储读取内容的指针
  10.   * @retval 0 成功, 1 失败
  11.   */
  12. static int _cb_FONT_XBF_GetData(U32 Offset, U16 NumBytes, void* pVoid, void* pBuffer)
  13. {
  14.         HANDLE hFile;
  15.         DWORD NumBytesRead;

  16.         /* 打开文件 */
  17.         hFile = CreateFile((char*)pVoid, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  18.         if (hFile != INVALID_HANDLE_VALUE)
  19.         {
  20.                 /* 指针偏移 */
  21.                 if (SetFilePointer(hFile, Offset, 0, FILE_BEGIN) == 0xFFFFFFFF) {
  22.                         return 1; // Error
  23.                 }
  24.                 /* 读取文件内容 */
  25.                 if (!ReadFile(hFile, pBuffer, NumBytes, &NumBytesRead, 0)) {
  26.                         return 1; // Error
  27.                 }
  28.                 if (NumBytesRead != NumBytes) {
  29.                         return 1; // Error
  30.                 }
  31.                 CloseHandle(hFile);
  32.                 return 0;   // Ok
  33.         }
  34.         else
  35.                 return 1;
  36. }
复制代码



然后是SIF格式:
  1. /* 字库文件路径,最长不超过260字符 */
  2. char   FONT_XINSONGTI_18_ADDR[_MAX_PATH] = { "Sample\\新宋体18_4bpp.sif" };
  3. char   FONT_SIYUANHEITI_36_ADDR[_MAX_PATH] = { "Sample\\思源黑体36_4bpp.sif" };
  4. /* 字库缓冲区 */
  5. char* SIFbuffer36;
  6. char* SIFbuffer18;
  7. /**
  8.   * @brief  加载字体数据到SDRAM
  9.   * @note 无
  10.   * @param  res_name:要加载的字库文件名
  11.   * @retval Fontbuffer:已加载好的字库数据
  12.   */
  13. void* FONT_SIF_GetData(const char* res_name)
  14. {
  15.         char* Fontbuffer;
  16.         GUI_HMEM hFontMem;

  17.         HANDLE hFile;
  18.         DWORD NumBytesRead;
  19.         DWORD FileSize;

  20.         /* 打开文件 */
  21.         hFile = CreateFile(res_name, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  22.         if (hFile != INVALID_HANDLE_VALUE)
  23.         {
  24.                 /* 获取文件大小 */
  25.                 FileSize = GetFileSize(hFile, NULL);
  26.                 /* 申请一块动态内存空间 */
  27.                 hFontMem = GUI_ALLOC_AllocZero(FileSize);
  28.                 /* 转换动态内存的句柄为指针 */
  29.                 Fontbuffer = GUI_ALLOC_h2p(hFontMem);
  30.                 /* 读取文件内容 */
  31.                 if (!ReadFile(hFile, Fontbuffer, FileSize, &NumBytesRead, 0)) {
  32.                         return 1; // Error
  33.                 }
  34.                 CloseHandle(hFile);
  35.                 return Fontbuffer; //OK
  36.         }
  37.         else
  38.                 return 1;
  39. }
复制代码



最后是TTF格式:
  1. /* 字库文件路径,最长不超过260字符 */
  2. char   FONT_TTF_ADDR[_MAX_PATH] = { "Sample\\DroidSansFallbackFull.ttf" };

  3. /**
  4.   * @brief  获取字体数据
  5.   * @note 无
  6.   * @param res_name:要读取的文件名
  7.   * @retval 无
  8.   */
  9. static char FONT_TTF_GetData(const char* res_name)
  10. {
  11.     HANDLE hFile;
  12.     DWORD NumBytesRead;
  13.     DWORD FileSize;


  14.     /* 打开文件 */
  15.     hFile = CreateFile(res_name, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  16.     if (hFile != INVALID_HANDLE_VALUE)
  17.     {
  18.         /* 获取文件大小 */
  19.         FileSize = GetFileSize(hFile, NULL);
  20.         /* 申请一块动态内存空间 */
  21.         hFontMem = GUI_ALLOC_AllocZero(FileSize);
  22.         /* 转换动态内存的句柄为指针 */
  23.         TTFfont_buffer = GUI_ALLOC_h2p(hFontMem);
  24.         /* 读取文件内容 */
  25.         if (!ReadFile(hFile, TTFfont_buffer, FileSize, &NumBytesRead, 0)) {
  26.             return 1; // Error
  27.         }
  28.         CloseHandle(hFile);

  29.         /* 配置属性 */
  30.         ttf_data.pData = TTFfont_buffer;
  31.         ttf_data.NumBytes = FileSize;

  32.         /* 配置字体参数 */
  33.         cs0.pTTF = &ttf_data;
  34.         cs0.PixelHeight = 24;
  35.         cs0.FaceIndex = 0;

  36.         cs1.pTTF = &ttf_data;
  37.         cs1.PixelHeight = 48;
  38.         cs1.FaceIndex = 0;

  39.         cs2.pTTF = &ttf_data;
  40.         cs2.PixelHeight = 72;
  41.         cs2.FaceIndex = 0;

  42.         cs3.pTTF = &ttf_data;
  43.         cs3.PixelHeight = 96;
  44.         cs3.FaceIndex = 0;

  45.         cs4.pTTF = &ttf_data;
  46.         cs4.PixelHeight = 120;
  47.         cs4.FaceIndex = 0;
  48.     }
  49.     else
  50.         return 1;
  51. }
复制代码



如果觉得自己改太麻烦,还可以到这里下载源文件,和stm32例程是兼容的,通过GUIFont_Create.h里的宏USE_WIN32来切换
emwin模拟器中文显示程序.7z (4.5 KB, 下载次数: 56)




下面是VS2019模拟器跑XBF、SIF和TTF格式字库例程的效果
截屏2020-05-17 下午10.43.10.png 截屏2020-05-18 上午12.00.02.png 截屏2020-05-17 下午11.57.04.png



WIN32 API的一些参考资料:
ReadFile function
CreateFileA function
Win32 文件的读写操作
[API档案] ReadFile 函数说明
[WinAPI] API 10 [创建、打开、读写文件,获取文件大小]
回复

使用道具 举报

发表于 2020-4-30 09:16:47 | 显示全部楼层
谢谢~
回复

使用道具 举报

 楼主| 发表于 2020-5-18 08:50:09 | 显示全部楼层
中文显示方法二施工完毕
回复 支持 反对

使用道具 举报

发表于 2020-5-18 22:37:44 | 显示全部楼层

回复

使用道具 举报

发表于 2020-5-27 15:11:22 | 显示全部楼层
牛,非常的牛
回复 支持 反对

使用道具 举报

发表于 2020-6-11 13:10:04 | 显示全部楼层
谢谢分享!
回复

使用道具 举报

发表于 2020-12-5 17:11:47 | 显示全部楼层
楼主, emwin模拟器中文显示程序.7z 下载不了了,<哭脸>
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-12-7 14:12:01 | 显示全部楼层
peng1557 发表于 2020-12-5 17:11
楼主, emwin模拟器中文显示程序.7z 下载不了了,

可能是论坛问题,我这里也下不了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-12-7 14:19:34 | 显示全部楼层
ZZZ_XXJ 发表于 2020-12-7 14:12
可能是论坛问题,我这里也下不了

似乎是修复了
回复 支持 反对

使用道具 举报

发表于 2020-12-7 20:52:12 | 显示全部楼层
主要就是字库转换为UTF -8格式 并且Main_Task里加上UTF-8函数使能
回复 支持 反对

使用道具 举报

发表于 2020-12-7 23:08:41 | 显示全部楼层

嗯嗯,是的,谢谢
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-4-26 04:42 , Processed in 0.042713 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表