• 【第3版emWin教程】第28章 emWin6.x的C文件格式的汉字生成和实现(Unicode编码)


    教程不断更新中:http://www.armbbs.cn/forum.php?mod=viewthread&tid=98429

    第28章       emWin6.x的C文件格式的汉字生成和实现(Unicode编码)

    本章节主要为大家讲解官方的字体生成软件FontCvt的使用方法,使用此软件可以生成C文件格式的汉字全字库,也可以生成C文件格式的小字库,所谓小字库就是需要显示什么汉字就仅生成这些汉字。

    FontCvt全称Font Converter。

    28.1 初学者重要提示

    28.2  使用FontCvt生成字库C文件的方法

    28.3 C文件格式汉字的使用方法

    28..4生成的是Unicode编码字体,而使用时为什么是UTF-8

    28.5 MDK4.X,MDK5.X和IAR的UTF-8编码问题

    28.6 实验例程说明(RTOS)

    28.7 实验例程说明(裸机)

    28.8 总结

     

     

    28.1 初学者重要提示

    1、  emWin官方提供的字体生成软件FontCvt不支持GB编码,所以只能使用FontCvt支持的Unicode编码。

    2、  字体小工具需要使用此贴提供的,其它大部分是Demo版本:

    http://www.armbbs.cn/forum.php?mod=viewthread&tid=107218

    3、  教程中让大家将要显示汉字的C文件转换为UTF-8编码,指的是将这个汉字所在的C文件转换为UTF-8编码,这点要切记,详情请看28.4小节的说明。

    另外特别注意MDK5编译错误missing closing quote,解决办法看本章教程第28.6.2小节。

    4、  FontCvt的使用方法在emWin手册中有讲解,这个只有英文版手册进行了详细说明:

     

    28.2 使用FontCvt生成C文件格式小字库的方法

    所谓小字库就是需要显示什么汉字就仅生成什么汉字,下面为大家讲解如何生成C文件格式的小字库。这里以生成“安富莱电子”五个字为例进行说明。

    •   第1步:在电脑桌面右击鼠标->新建->文本文档,即新建一个txt文本。

     

    创建了文本文档后,输入“安富莱电子”五个字:

     

    然后点击菜单选项文件->另存为:

     

    弹出如下窗口:

     

    注:Win10选择的是UTF-16 LE

    此时桌面上就会生成一个名字为FontSong16的文本文档。

    •   第2步:打开字体生成软件FontCvt,选择字体类型Standard,编码选择16bit Unicode

     

    点击OK后,弹出如下窗口:

     

    再点击确定后弹出FontCvt界面变成如下效果:

     

    •   第3步:点击EDIT->Disable all characters

     

    禁止所有字符后,字符区就全部变成灰色的了:

     

    •   第4步:点击Edit->Read pattern file

     

    •   第5步:加载文件FontSong16.txt

     

    点击打开后,FontCvt软件的字符显示区中“安富莱电子”五个字的背景已经变成白色,下面是其中一个“莱”字的显示效果:

     

    •   第6步:最后一步,点击File->Save As

     

    弹出如下窗口:

     

    至此就生成了我们所需要的16点阵字体。以同样的方法,我们再以此生成以下几种字体:

    1. 字体类型Standard,16bit Unicode编码,32点阵,宋体,生成的文件名为FontSong32.c。

    2. 字体类型Standard,16bit Unicode编码,72点阵,宋体,生成的文件名为FontSong72.c。

    3. 字体类型Standard,16bit Unicode编码,144点阵,宋体,生成的文件名为FontSong144.c。

    4. 字体类型Antialiased 4bpp(4倍抗锯齿),16bit Unicode编码,144点阵,宋体,生成的文件名为FontSongA144.c。

    5. 字体类型Extended framed(扩展模式,带边框),16bit Unicode编码,144点阵,宋体,生成的文件名为FontSongExF144.c。

    6. 字体类型Extended antialiased 4bpp(扩展模式,4倍抗锯齿),16bit Unicode编码,144点阵,宋体,生成的文件名为FontSongExA144.c。

    通过小软件FontCvt,共生成了7种字体文件:

     

    有了这几个文件就可以进行相应字体的汉字显示了,由于仅生成了“安富莱电子”这五个字,所以仅支持这五个字的显示。接下来讲解这7种字体文件如何使用。

    28.3 使用FontCvt生成C文件格式全字库的方法

    由于FontCvt生成C文件格式的全字库比较大,放在内部Flash非常占空间,所以基本不使用,不过生成方法要简单说明下。

    •   第1步:打开字体生成软件FontCvt,选择字体类型Standard,编码选择16bit Unicode

     

    点击OK后,弹出如下窗口:

     

    再点击确定后弹出FontCvt界面变成如下效果:

     

    •   第2步:点击File->Save As

     

    弹出如下窗口:

     

    此时,桌面上就生成了一个名为FontSong16.c的文件,实际在MDK工程中测试,此文件要占用1147060字节,即1MB多,所以实际项目中不推荐。

    28.4 C文件格式汉字的使用方法

    下面讲解28.2小节生成的7种字体C文件的使用方法,这里将MDK和IAR分别进行说明:

    28.4.1   MDK编译器中使用C文件格式汉字的方法

    •   第1步:将生成的7种字体文件添加到MDK工程目录里面,本章节配套的例子是将其放在User->fonts文件夹下

     

    •   第2步:将生成的7种字体文件添加到MDK工程中

     

    •   第3步:调用函数GUI_UC_SetEncodeUTF8()来使能UTF-8编码,这一步是必须的,切不可以忘了。
    •   第4步:此时就可以使用这7种字体了,打开这7个字体文件,每个文件的开头都有一个extern的字体声明。

    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong16;

    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong32;

    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong72;

    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong144;

    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongA144;

    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongExA144;

    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongExF144;

    如果用户要在哪个源码文件里面使用这些字体,就把这些字体声明放在相应源文件的开头就行。使用方法,跟使用emWin自带的ASCII和ISO 8859-1字体基本是一样的,唯一区别的地方是:调用FontCvt生成的字体时要加上取地址操作&。下面举一个完整的例子,代码在本章节配套例子的MainTask.c文件里面(对于初学者来说,对话框,按钮控件和文本控件还没有讲到,这里只是举个例子,会使用这些新生成的字体即可,后面会讲到这些控件):

    #include "MainTask.h"
    #include "includes.h"
    
    
    
    /*
    *********************************************************************************************************
    *                     调用外部字体声明,这个就是第4步中所说的问题
    *********************************************************************************************************
    */
    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong16;
    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong32;                                                
    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong72;
    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong144;
    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongA144;
    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongExA144;
    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongExF144;
    
    
    /*
    *********************************************************************************************************
    *                                      对话框资源列表
    *********************************************************************************************************
    */
    static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
        { FRAMEWIN_CreateIndirect,  "armfly", 0,         0,  0,  800,480,FRAMEWIN_CF_MOVEABLE,0},
        { BUTTON_CreateIndirect,    "安富莱我们我们",    GUI_ID_BUTTON0,          350,20,420,150,0,0},
        { TEXT_CreateIndirect,      "安富莱电子",        GUI_ID_TEXT0,            5, 10, 300, 33, 0,0},
        { TEXT_CreateIndirect,      "安富莱电子",        GUI_ID_TEXT1,            5, 40,250, 50, 0,0},
        { TEXT_CreateIndirect,      "安富莱",            GUI_ID_TEXT2,            5, 100,360, 90, 0,0},
        { TEXT_CreateIndirect,      "",                GUI_ID_TEXT3,            5, 220,144, 144, 0,0},
        { TEXT_CreateIndirect,      "",                GUI_ID_TEXT4,            205, 230,144, 144, 0,0},
        { TEXT_CreateIndirect,      "",                GUI_ID_TEXT5,            405, 230,144, 144, 0,0},
        { TEXT_CreateIndirect,      "",                GUI_ID_TEXT6,            605, 230,144, 144, 0,0}
    };
    
    /*
    *********************************************************************************************************
    *    函 数 名: PaintDialog
    *    功能说明: 对话框重绘函数
    *    形    参:pMsg   消息指针
    *    返 回 值: 无
    *********************************************************************************************************
    */
    void PaintDialog(WM_MESSAGE   * pMsg)
    {
    //    WM_HWIN hWin = pMsg->hWin;
        
    }
    
    /*
    *********************************************************************************************************
    *    函 数 名: 对话框初始化
    *    功能说明: 对话框初始化
    *    形    参: pMsg   消息指针
    *    返 回 值: 无
    *********************************************************************************************************
    */
    void InitDialog(WM_MESSAGE * pMsg)
    {
        WM_HWIN hWin = pMsg->hWin;
        
        //
        // 配置FrameWin
        //
        FRAMEWIN_SetFont(hWin,&GUI_Font32B_ASCII);
        FRAMEWIN_SetTextAlign(hWin,GUI_TA_VCENTER|GUI_TA_CENTER);
        FRAMEWIN_AddCloseButton(hWin, FRAMEWIN_BUTTON_RIGHT, 0);
        FRAMEWIN_AddMaxButton(hWin, FRAMEWIN_BUTTON_RIGHT, 1);
        FRAMEWIN_AddMinButton(hWin, FRAMEWIN_BUTTON_RIGHT, 2);
        FRAMEWIN_SetTitleHeight(hWin,35);
        
    /* 外部的7种字体在文件控件TEXT和按钮控件BUTTON中都使用了,具体调用方法如下,
    跟使用emWin自带的字体是一样的。*/
        //
        // 按钮的字体是4倍抗锯齿,144点阵
        //                                                               
        BUTTON_SetFont(WM_GetDialogItem(hWin,GUI_ID_BUTTON0),&GUI_FontFontSongA144);                    
        
        //
        // 分别用16点阵,32点阵和72点阵字体显示 安富莱电子 五个字。
        //
        TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT0), GUI_RED);
        TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT0),&GUI_FontFontSong16);
        TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT1), GUI_GREEN);
        TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT1),&GUI_FontFontSong32);
        TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT2), GUI_BLUE);
        TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT2),&GUI_FontFontSong72);
    
        //
        // 分别用144点阵汉字,144点阵的扩展模式且4倍抗锯齿汉字,144点阵的4倍抗锯齿汉字和
        // 144点阵的扩展模式且带边框汉字。
        //
        TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT3),&GUI_FontFontSong144);
        TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT4),&GUI_FontFontSongExA144);
        TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT5),&GUI_FontFontSongA144);
        TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT6),&GUI_FontFontSongExF144);
    }
    
    /*
    *********************************************************************************************************
    *    函 数 名: _cbCallback
    *    功能说明: 对话框回调函数
    *    形    参: pMsg   消息指针
    *    返 回 值: 无
    *********************************************************************************************************
    */
    static void _cbCallback(WM_MESSAGE * pMsg) 
    {
        int NCode, Id;
        WM_HWIN hWin = pMsg->hWin;
        switch (pMsg->MsgId) 
        {
            case WM_PAINT:
                PaintDialog(pMsg);
                break;
            
            case WM_INIT_DIALOG:
                InitDialog(pMsg);
                break;
            
            case WM_KEY:
                switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key) 
                {
                    case GUI_KEY_ESCAPE:
                        GUI_EndDialog(hWin, 1);
                        break;
                    case GUI_KEY_ENTER:
                        GUI_EndDialog(hWin, 0);
                        break;
                }
                break;
                
            case WM_NOTIFY_PARENT:
                Id = WM_GetId(pMsg->hWinSrc); 
                NCode = pMsg->Data.v;        
                switch (Id) 
                {
                    case GUI_ID_OK:
                        if(NCode==WM_NOTIFICATION_RELEASED)
                            GUI_EndDialog(hWin, 0);
                        break;
                        
                    case GUI_ID_CANCEL:
                        if(NCode==WM_NOTIFICATION_RELEASED)
                            GUI_EndDialog(hWin, 0);
                        break;
    
                }
                break;
                
            default:
                WM_DefaultProc(pMsg);
        }
    }
    
    /*
    *********************************************************************************************************
    *    函 数 名: MainTask
    *    功能说明: GUI主函数
    *    形    参: 无
    *    返 回 值: 无
    *********************************************************************************************************
    */
    void MainTask(void) 
    {
        /* 初始化 */
        GUI_Init();
         
        WM_MULTIBUF_Enable(1);
        
        /* 使能UTF-8编码,这个是第3步中所说的问题,不必限制一定要放在这个位置,使用外部字体之前调用了即可 */     
        GUI_UC_SetEncodeUTF8(); 
        
        /* 调用此函数会自动的刷新桌面窗口 */
        WM_SetDesktopColor(GUI_WHITE); 
    
        /* 创建对话框 */
        GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0);
        
        while(1) 
        {
            GUI_Delay(10);
        }
    }

    通过上面的代码就实现了这7种字体的显示,具体效果可以看实验例程说明。

    •   第5步:这个是最重要的一步,很多初学者显示汉字失败就是因为这一步了。

    修改汉字显示所在的源文件,即MainTask.c文件为UTF-8编码,并不是修改FontCvt生成的C文件为UTF-8编码,因为FontCvt软件生成的C文件已经是UTF-8编码了。也就是说哪个文件用到这种汉字显示了,哪个文件就修改编码类型为UTF-8,只有这样,MDK才可以将这些汉字的编码识别出来,要不识别出来的汉字编码与FontCvt生成字体的编码类型不匹配,从而无法正确显示。

    修改编码类型也比较容易,使用电脑自带的记事本即可,将MainTask.C文件用记事本打开:

     

    点击文件->另存为

     

    弹出如下窗口:

     

    点击保存后,会弹出如下窗口:

     

    重新切换回MDK工程,也会弹出一个窗口:

     

    这样MainTask.c文件就变成UTF-8编码了。此时就可以全编译工程并下载例子到开发板进行测试了。

    28.4.2   IAR编译器中使用C文件格式汉字的方法

    •   第1步:将生成的7种字体文件添加到IAR工程目录里面,本章节配套的例子是将其放在User->fonts文件夹下

     

    •   第2步:将生成的7种字体文件添加到IAR工程中

    •   第3步:调用函数GUI_UC_SetEncodeUTF8()来使能UTF-8编码,这一步是必须的,切不可以忘了。
    •   第4步:此时就可以使用这7种字体了,打开这7个字体文件,每个文件的开头都有一个extern的字体声明。

    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong16;

    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong32;

    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong72;

    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong144;

    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongA144;

    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongExA144;

    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongExF144;

    如果用户要在哪个源码文件里面使用这些字体,就把这些字体声明放在相应源文件的开头就行。使用方法,跟使用emWin自带的ASCII和ISO 8859-1字体基本是一样的,唯一区别的地方是:调用FontCvt生成的字体时要加上取地址操作&。下面举一个完整的例子,代码在本章节配套例子的MainTask.c文件里面(对于初学者来说,对话框,按钮控件和文本控件还没有讲到,这里只是举个例子,会使用这些新生成的字体即可,后面会讲到这些控件):

    #include "MainTask.h"
    #include "includes.h"
    
    
    
    /*
    *********************************************************************************************************
    *                     调用外部字体声明,这个就是第4步中所说的问题
    *********************************************************************************************************
    */
    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong16;
    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong32;                                                
    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong72;
    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong144;
    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongA144;
    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongExA144;
    extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongExF144;
    
    
    /*
    *********************************************************************************************************
    *                                      对话框资源列表
    *********************************************************************************************************
    */
    static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
        { FRAMEWIN_CreateIndirect,  "armfly", 0,         0,  0,  800,480,FRAMEWIN_CF_MOVEABLE,0},
        { BUTTON_CreateIndirect,    "安富莱我们我们",    GUI_ID_BUTTON0,          350,20,420,150,0,0},
        { TEXT_CreateIndirect,      "安富莱电子",        GUI_ID_TEXT0,            5, 10, 300, 33, 0,0},
        { TEXT_CreateIndirect,      "安富莱电子",        GUI_ID_TEXT1,            5, 40,250, 50, 0,0},
        { TEXT_CreateIndirect,      "安富莱",            GUI_ID_TEXT2,            5, 100,360, 90, 0,0},
        { TEXT_CreateIndirect,      "",                GUI_ID_TEXT3,            5, 220,144, 144, 0,0},
        { TEXT_CreateIndirect,      "",                GUI_ID_TEXT4,            205, 230,144, 144, 0,0},
        { TEXT_CreateIndirect,      "",                GUI_ID_TEXT5,            405, 230,144, 144, 0,0},
        { TEXT_CreateIndirect,      "",                GUI_ID_TEXT6,            605, 230,144, 144, 0,0}
    };
    
    /*
    *********************************************************************************************************
    *    函 数 名: PaintDialog
    *    功能说明: 对话框重绘函数
    *    形    参:pMsg   消息指针
    *    返 回 值: 无
    *********************************************************************************************************
    */
    void PaintDialog(WM_MESSAGE   * pMsg)
    {
    //    WM_HWIN hWin = pMsg->hWin;
        
    }
    
    /*
    *********************************************************************************************************
    *    函 数 名: 对话框初始化
    *    功能说明: 对话框初始化
    *    形    参: pMsg   消息指针
    *    返 回 值: 无
    *********************************************************************************************************
    */
    void InitDialog(WM_MESSAGE * pMsg)
    {
        WM_HWIN hWin = pMsg->hWin;
        
        //
        // 配置FrameWin
        //
        FRAMEWIN_SetFont(hWin,&GUI_Font32B_ASCII);
        FRAMEWIN_SetTextAlign(hWin,GUI_TA_VCENTER|GUI_TA_CENTER);
        FRAMEWIN_AddCloseButton(hWin, FRAMEWIN_BUTTON_RIGHT, 0);
        FRAMEWIN_AddMaxButton(hWin, FRAMEWIN_BUTTON_RIGHT, 1);
        FRAMEWIN_AddMinButton(hWin, FRAMEWIN_BUTTON_RIGHT, 2);
        FRAMEWIN_SetTitleHeight(hWin,35);
        
    /* 外部的7种字体在文件控件TEXT和按钮控件BUTTON中都使用了,具体调用方法如下,
    跟使用emWin自带的字体是一样的。*/
        //
        // 按钮的字体是4倍抗锯齿,144点阵
        //                                                               
        BUTTON_SetFont(WM_GetDialogItem(hWin,GUI_ID_BUTTON0),&GUI_FontFontSongA144);                    
        
        //
        // 分别用16点阵,32点阵和72点阵字体显示 安富莱电子 五个字。
        //
        TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT0), GUI_RED);
        TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT0),&GUI_FontFontSong16);
        TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT1), GUI_GREEN);
        TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT1),&GUI_FontFontSong32);
        TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT2), GUI_BLUE);
        TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT2),&GUI_FontFontSong72);
    
        //
        // 分别用144点阵汉字,144点阵的扩展模式且4倍抗锯齿汉字,144点阵的4倍抗锯齿汉字和
        // 144点阵的扩展模式且带边框汉字。
        //
        TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT3),&GUI_FontFontSong144);
        TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT4),&GUI_FontFontSongExA144);
        TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT5),&GUI_FontFontSongA144);
        TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT6),&GUI_FontFontSongExF144);
    }
    
    /*
    *********************************************************************************************************
    *    函 数 名: _cbCallback
    *    功能说明: 对话框回调函数
    *    形    参: pMsg   消息指针
    *    返 回 值: 无
    *********************************************************************************************************
    */
    static void _cbCallback(WM_MESSAGE * pMsg) 
    {
        int NCode, Id;
        WM_HWIN hWin = pMsg->hWin;
        switch (pMsg->MsgId) 
        {
            case WM_PAINT:
                PaintDialog(pMsg);
                break;
            
            case WM_INIT_DIALOG:
                InitDialog(pMsg);
                break;
            
            case WM_KEY:
                switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key) 
                {
                    case GUI_KEY_ESCAPE:
                        GUI_EndDialog(hWin, 1);
                        break;
                    case GUI_KEY_ENTER:
                        GUI_EndDialog(hWin, 0);
                        break;
                }
                break;
                
            case WM_NOTIFY_PARENT:
                Id = WM_GetId(pMsg->hWinSrc); 
                NCode = pMsg->Data.v;        
                switch (Id) 
                {
                    case GUI_ID_OK:
                        if(NCode==WM_NOTIFICATION_RELEASED)
                            GUI_EndDialog(hWin, 0);
                        break;
                        
                    case GUI_ID_CANCEL:
                        if(NCode==WM_NOTIFICATION_RELEASED)
                            GUI_EndDialog(hWin, 0);
                        break;
    
                }
                break;
                
            default:
                WM_DefaultProc(pMsg);
        }
    }
    
    /*
    *********************************************************************************************************
    *    函 数 名: MainTask
    *    功能说明: GUI主函数
    *    形    参: 无
    *    返 回 值: 无
    *********************************************************************************************************
    */
    void MainTask(void) 
    {
        /* 初始化 */
        GUI_Init();
         
        WM_MULTIBUF_Enable(1);
        
        /* 使能UTF-8编码,这个是第3步中所说的问题,不必限制一定要放在这个位置,使用外部字体之前调用了即可 */     
        GUI_UC_SetEncodeUTF8(); 
        
        /* 调用此函数会自动的刷新桌面窗口 */
        WM_SetDesktopColor(GUI_WHITE); 
    
        /* 创建对话框 */
        GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0);
        
        while(1) 
        {
            GUI_Delay(10);
        }
    }

    通过上面的代码就实现了这7种字体的显示,具体效果可以看实验例程说明。

    •   第5步:这个是最重要的一步,很多初学者显示汉字失败就是因为这一步了。

    修改汉字显示所在的源文件,即MainTask.c文件为UTF-8编码,并不是修改FontCvt生成的C文件为UTF-8编码,因为FontCvt软件生成的C文件已经是UTF-8编码了。也就是说哪个文件用到这种汉字显示了,哪个文件就修改编码类型为UTF-8,只有这样,IAR将这些汉字的编码识别出来,要不识别出来的汉字编码与FontCvt生成字体的编码类型不匹配,从而无法正确显示。

    修改编码类型也比较容易,使用IAR的话,不要使用记事本来修改了(为什么不可以使用,在28.5小节有讲解),IAR编辑器支持编码类型的修改。

     

    IAR编码方面的小知识:

    默认情况下,IAR创建的工程都是System编码,也就是你的电脑系统是什么编码类型,使用IAR创建的.C和.H文件就是什么编码类型,一般大陆都是用的GBK编码,查看电脑系统编码类型可以通过:单击开始->所有程序->附件->命令提示符,打开命令提示符,输入chcp,然后点击键盘的回车键。

     

    这里的936就是代表GBK编码。而IAR的编码设置在这里,点击菜单Tools->Options,弹出如下窗口

     

    默认的编码类型是System。

     

    在IAR编译器中如何查看.C和.H文件的编码类型,又如何修改呢?查看编码类型可以任意打开一个文件,然后查看右下角。

     

    这里打开的就是一个中文简体,GB2312编码,GBK向下是完全兼容GB2312的。修改单个.C和.H文件的编码类型也比较简单,这里我们需要修改MainTask.c文件的编码类型为UTF-8,直接在MainTask.c文件里面右击鼠标,选择Character Encoding->Convert to UTF-8。

     

    设置后就可以看到右下角已经修改为UTF-8了。

     

    此时就可以全编译工程并下载例子到开发板进行测试了。

    28.5 生成的是Unicode编码字体,而使用时为什么是UTF-8

    初学者容易有这样的疑问,FontCvt软件生成的是Unicode编码的汉字,为什么emWin使用的时候不直接使用,还要多一次转换,即我们操作的时候是用的UTF-8编码字体,emWin的库函数会将这个编码转换成Unicode编码,然后从Unicode编码的字符集中获取相应的点阵数据。

    补充点小知识,方便大家理解:

    • Unicode编码

    各个国家都有一套自己的编码标准,但谁也不懂谁的编码,谁也不支持别人的编码。基于此,国际组织决定着手解决这个问题,即重新弄一套包括了地球上所有文化、所有字母和符号的编码。将其命名为"UniversalMultiple-Octet Coded Character Set“(通用多八位编码字符集),简称 UCS, 俗称Unicode。Unicode有两种编码UCS-2和UCS-4,其中UCS-2用两个字节编码,UCS-4用4个字节编码。

    • UTF-8编码

    事实证明,对可以用ASCⅡ表示的字符使用UNICODE并不高效,因为UNICODE比ASCⅡ占用大一倍的空间,而对ASCⅡ来说高字节的0对他毫无用处。为了解决这个问题,就出现了一些中间格式的字符集,他们被称为通用转换格式,即UTF(Universal Transformation Format)。目前存在的UTF格式有:UTF-7,UTF-7.5,UTF-8,UTF-16以及 UTF-32。

    那么问题来了,emWin中为什么不直接使用Unicode编码,而要使用UTF-8。

    1.  MDK和IAR的编辑器都不支持Unicode编码,仅支持UTF-8,笔者认为,这个是最主要的原因。

    2.  UTF-8编码相对于Unicode编码的优势。

    (1) UTF-8表示与ASCII字符表示是一样的,只占一个字节,解决了Unicode浪费空间的情况。

    (2) 与CPU字节顺序无关, 可以在不同平台之间交流。

    (3) 容错能力高, 任何一个字节损坏后, 最多只会导致一个编码码位损失, 不会连锁错误。

    28.6 MDK4.X,MDK5.X和IAR的UTF-8编码问题

    对于初学者来说,下面的问题是必看的,初次看可能不太理解,实际用这三个编译器操作了本章节配套的例子就有深刻的体会了。

    28.6.1   MDK4.X的UTF-8说明

    MDK4.74是MDK4系列里面的最后一个版本了。

    一直以来都是将汉字显示所在的源文件使用记事本另存为UTF-8编码类型,特别注意,记事本另存的是UTF-8 带 BOM。且用户修改了这个文件的任何地方,MDK都会自动将这个文件存储为UTF-8编码无BOM。实际用Notepad++另存为UTF-8带BOM或者不带BOM,使用MDK4.74都可以正确显示汉字的。

    28.6.2   MDK5.X的UTF-8说明

    对于MDK5.X来说,也可以使用记事本将汉字显示所在的源文件另存为UTF-8编码类型,此时MDK5.21a是可以正确编译的。但是,用户一旦修改了这个文件的任何地方,直接编译或者保存后编译,MDK都会将这个文件存储为UTF-8编码无BOM,而MDK5.X无法像MDK4.X那样带BOM或者不带BOM都能够识别,所以编译会出错。解决方法:options->c/c++->Misc controls 填写“--locale=english”

     

    28.6.3   IAR的UTF-8说明

    对于IAR来说,他仅支持UTF-8无BOM,修改的时候不要使用记事本,直接在汉字显示所在的源文件右击选择即可(在28.4.2小节已经讲解),或者用Notepad++选择UTF-8无BOM。

    28.6.4   编码问题总结

    •   IAR仅支持UTF-8编码无BOM文件的汉字显示,带BOM的话,编译不通过。
    •   MDK4.X对于UTF-8带BOM或者不带BOM都支持,但会将带BOM文件修改为不带BOM,两种编码形式显示汉字都不受影响。
    •   MDK5.X对于UTF-8带BOM或者不带BOM都支持,不过需要大家按照28.6.2小结的说明修改。

    名词解释:BOM

         BOM(Byte Order Mark),字节顺序标记,出现在文本文件头部,Unicode编码标准中用于标识文件是采用哪种格式的编码。UTF-8 不需要 BOM 来表明字节顺序,但可以用 BOM 来表明编码方式。字符 "Zero Width No-Break Space" 的 UTF-8 编码是 EF BB BF。所以如果接收者收到以 EF BB BF 开头的字节流,就知道这是 UTF-8编码了。Windows 就是使用 BOM 来标记文本文件的编码方式的。

         WINDOWS自带的记事本等软件,在保存一个以UTF-8编码的文件时,会在文件开始的地方插入三个不可见的字符(0xEF 0xBB 0xBF,即BOM)。它是一串隐藏的字符,用于让记事本等编辑器识别这个文件是否以UTF-8编码。

    28.7 实验例程说明(RTOS)

    配套例子:

    V7-532_emWin6.x实验_C文件格式的汉字生成和实现,Unicode编码(RTOS)

    实验目的:

    1. 学习emWin的C文件格式汉字的使用方法,Unicode编码。
    2. emWin功能的实现在MainTask.c文件里面。

    实验内容:

    1、K1按键按下,串口或者RTT打印任务执行情况(串口波特率115200,数据位8,奇偶校验位无,停止位1)。

    2、(1) 凡是用到printf函数的全部通过函数App_Printf实现。

    (2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。

    3、默认上电是通过串口打印信息,如果使用RTT打印信息:

    MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可

    #define Enable_RTTViewer  1

    4、各个任务实现的功能如下:

    App Task Start   任务 :启动任务,这里用作BSP驱动包处理。

    App Task MspPro任务 :消息处理,这里用作LED闪烁。

    App Task UserIF  任务 :按键消息处理。

    App Task COM   任务 :暂未使用。

    App Task GUI    任务 :GUI任务。

    μCOS-III任务调试信息(按K1按键,串口打印):

     

    RTT 打印信息方式:

     

    程序设计:

    •   任务栈大小分配:

    μCOS-III任务栈大小在app_cfg.h文件中配置:

    #define  APP_CFG_TASK_START_STK_SIZE                      512u

    #define  APP_CFG_TASK_MsgPro_STK_SIZE                     2048u

    #define  APP_CFG_TASK_COM_STK_SIZE                        512u

    #define  APP_CFG_TASK_USER_IF_STK_SIZE                    512u

    #define  APP_CFG_TASK_GUI_STK_SIZE                        2048u

    任务栈大小的单位是4字节,那么每个任务的栈大小如下:

    App Task Start   任务 :2048字节。

    App Task MspPro任务 :8192字节。

    App Task UserIF  任务 :2048字节。

    App Task COM   任务 :2048字节。

    App Task GUI    任务 :8192字节。

    •   系统栈大小分配:

    μCOS-III的系统栈大小在os_cfg_app.h文件中配置:

    #define  OS_CFG_ISR_STK_SIZE                      512u     

    系统栈大小的单位是4字节,那么这里就是配置系统栈大小为2KB

    emWin动态内存配置:

    GUIConf.c文件中的配置如下:

    #define EX_SRAM   1/*1 used extern sram, 0 used internal sram */
    
    #if EX_SRAM
    #define GUI_NUMBYTES  (1024*1024*24)
    #else
    #define GUI_NUMBYTES  (100*1024)
    #endif

    通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:

    #define  EX_SRAM     1 表示使用外部SDRAM作为emWin动态内存,大小24MB。

    #define  EX_SRAM     0 表示使用内部SRAM作为emWin动态内存,大小100KB。

    默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。

    emWin界面显示效果:

    800*480分辨率界面效果。

     

    28.8 实验例程说明(裸机)

    配套例子:

    V7-531_emWin6.x实验_C文件格式的汉字生成和实现,Unicode编码(裸机)

    实验目的:

    1. 学习emWin的C文件格式汉字的使用方法,Unicode编码。
    2. emWin功能的实现在MainTask.c文件里面。

    emWin界面显示效果:

    800*480分辨率界面效果。

     

    emWin动态内存配置:

    GUIConf.c文件中的配置如下:

    #define EX_SRAM   1/*1 used extern sram, 0 used internal sram */
    
    #if EX_SRAM
    #define GUI_NUMBYTES  (1024*1024*24)
    #else
    #define GUI_NUMBYTES  (100*1024)
    #endif

    通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:

    #define  EX_SRAM     1 表示使用外部SDRAM作为emWin动态内存,大小24MB。

    #define  EX_SRAM     0 表示使用内部SRAM作为emWin动态内存,大小100KB。

    默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。

    28.9 总结

    本章节讲解的内容较多,特别是涉及到UTF-8编码的问题时,望初学者务必将其掌握,有了本章节的基础,后面几个章节的汉字显示操作起来将更加的得心应手。

    微信公众号:armfly_com 安富莱论坛:www.armbbs.cn 安富莱淘宝:https://armfly.taobao.com
  • 相关阅读:
    [C#性能简析]泛型集合的使用
    理解自定义特性(Attribute)
    C语言第1次作业2.0版
    C语言第3次作业
    C语言第1次作业
    C语言第2次作业
    kubernetes 部署metricserver
    安装nginx
    C# Winform应用程序内存回收
    asp.net 数据库访问操作类
  • 原文地址:https://www.cnblogs.com/armfly/p/15044945.html
Copyright © 2020-2023  润新知