关于Vspy中CCode编程对文本控件信息的编码格式转换(Vspy系列应用1)
1、目的
通讯矩阵中有用于发送歌曲信息的报文信号;现需在Vspy的“Graphical Pannels”下制作面板,在文本框中输入歌曲名,通过报文将输入的歌曲名以utf8编码格式进行发送
2、GB2312编码格式及格式转换
2.1、 GB2312编码格式介绍
在Vspy中,关于中文使用的是GB2312编码格式(英文数字则是使用ASCII码);接下来,我们对涉及到的GB2312编码进行简单的介绍。
在GB2312编码格式中,每个字符是以两个字节来表示 。其中,第一个字节称为“高位字节”,也称为区码,使用了0xA1-0xF7(把01-87区的区号加上0xA0)。第二个字节称为“低位字节”,也称为位码,使用了0xA1-0xFE(把01-94加上0xA0)。例如 “啊”字“是GB2312之中的第一个汉字,它的区位码就是1601(第16区第一位),则其GB2312编码是0xB0A1(0xB0=0xA0+区码16,0xA1=0xA0+位码01)。
GB2312编码中,将所收录的字符分为 94 个区,编号为 01 区至 94 区;每个区收录 94 个字符,编号为 01 位至 94 位。各区的分配类型如下,其中,汉字的分配范围是在16区–87区。
2.2、 GB2312编码格式转Unicode
可以通过MultiByteToWideChar()函数进行多字节字符到宽字符转换函数;该函数原型如下,参数设置可参考对应的注释部分:
int
WINAPI
MultiByteToWideChar(
_In_ UINT CodePage,/*指定要转换成的字符集代码页,常用的参数是CP_ACP(表示当前系统ANSI代码页)、CP_UTF8 */
_In_ DWORD dwFlags,/*一般设置为0即可 */
_In_NLS_string_(cbMultiByte) LPCCH lpMultiByteStr,/*要进行转换的字符串*/
_In_ int cbMultiByte,/*要转换字符串的长度,若为-1则表示转换到字符串结尾,并返回原字符串长度*/
_Out_writes_to_opt_(cchWideChar, return) LPWSTR lpWideCharStr,/*用于接收转换后输出的宽字符串,如果为NULL, 则表示计算生成的字符串的长度*/
_In_ int cchWideChar/*输出缓冲区大小,即转化生成的unicode字符串的缓存容量;为0时, 函数 将返回所需缓冲区大小*/
);
利用上述函数将GB2312转换为Unicode的代码如下(注意用完之后通过free()函数对malloc分配的内存进行释放):
int wLen = MultiByteToWideChar(CP_ACP, 0, Name, -1, NULL, 0); /*获取转换为Unicode所需的缓冲区大小(注意此时的单位是宽字符)*/
LPWSTR Name_Unicode = NULL;
Name_Unicode = (LPWSTR)malloc((sizeof(WCHAR))* wLen); /*分配空间*/
MultiByteToWideChar(CP_ACP, 0, Name, -1, Name_Unicode, wLen); /*进行编码转换*/
2.3、 Unicode编码格式转Utf8
可以通过WideCharToMultiByte()函数将宽字符串转换成指定的字符串,如ANSI,UTF8等,新字符串不必是多字节字符集;该函数原型如下,参数设置与上一小节的MultiByteToWideChar()函数基本一致:
int
WINAPI
WideCharToMultiByte(
_In_ UINT CodePage,/*指定要转换成的字符集代码页,常用的参数是CP_ACP(表示当前系统ANSI代码页)、CP_UTF8 */
_In_ DWORD dwFlags,/*一般设置为0即可 */
_In_NLS_string_(cchWideChar) LPCWCH lpWideCharStr,/*要进行转换的字符串*/
_In_ int cchWideChar,/*要转换字符串的长度,若为-1则表示转换到字符串结尾,并返回原字符串长度*/
_Out_writes_bytes_to_opt_(cbMultiByte, return) LPSTR lpMultiByteStr,/*用于接收转换后输出的字符串,如果为NULL, 则表示计算生成的字符串的长度*/
_In_ int cbMultiByte,/*输出缓冲区大小,即转化生成的字符串的缓存容量;为0时, 函数 将返回所需缓冲区大小*/
_In_opt_ LPCCH lpDefaultChar,/*一般设置为NULL即可 */
_Out_opt_ LPBOOL lpUsedDefaultChar/*一般设置为NULL即可 */
);
利用上述函数将Unicode转换为Utf8编码的代码如下(注意用完之后通过free()函数对malloc分配的内存进行释放):
int Len = WideCharToMultiByte(CP_UTF8, 0, Name_Unicode, -1, NULL, 0, NULL, NULL); /*获取转换为Utf8所需的缓冲区大小*/
char * Name_Utf8 = NULL;
Name_Utf8 = (char *)malloc((sizeof(char))* Len);/*分配空间*/
WideCharToMultiByte(CP_UTF8, 0, Name_Unicode, -1, Name_Utf8, Len, NULL, NULL);/*进行编码转换*/
2.4、 Utf8编码格式转GB2312
在前两小节我们介绍了通过MultiByteToWideChar()函数和WideCharToMultiByte()函数将GB2312编码转换为Utf8的步骤。当我们想反过来将Utf8转换为GB2312编码时,其操作如下:先通过MultiByteToWideChar()函数将Utf8转换为Unicode编码(第一个参数设置为CP_UTF8);再通过WideCharToMultiByte()函数将Unicode转换为GB2312编码(第一个参数设置为CP_ACP)即可。对应代码如下:
int wLen1 = MultiByteToWideChar(CP_UTF8, 0, Name_Utf8, -1, NULL, 0);/*假设要转换的Utf8码存储在Name_Utf8中*/
char * Name_Unicode1 = NULL;
Name_Unicode1 = (char *)malloc((sizeof(char))* wLen1);
MultiByteToWideChar(CP_UTF8, 0, Name_Utf8, -1, Name_Unicode1, wLen1);
int Len1 = WideCharToMultiByte(CP_ACP, 0, Name_Unicode1, -1, NULL, 0, NULL, NULL);
char * Name_GB2312 = NULL;
Name_GB2312 = (char *)malloc((sizeof(char))* Len1);
WideCharToMultiByte(CP_ACP, 0, Name_Unicode1, -1, Name_GB2312, Len1, NULL, NULL);
3、操作步骤
(1)、定义用于发送的报文
在"Message Editor"界面下,根据通讯矩阵中关于该报文的描述定义该发送报文;或者已经有dbc的情况下从dbc中导入到"Transmit"中;
(2)、定义存储文本信息的App Signal
定义一个文本类型的App Signal,用于存储我们输入的文本信息;如下:
(3)、创建Text Entry控件
在“Graphical Pannels”下放置一个文本输入框(Text Entry)控件;关联上前面一步定义的App Signal。如下:
Ps:关于前面三点的操作,可以查看“Vspy常用操作”的相关介绍(第5、第7小节内容);这里不对步骤进行详细操作介绍。
(4)、新建C Code工程
在C Code Interface中新增C工程;此时,前面定义的App Signal、报文等信息都会在工程中的SpyCCode.c中自动生成对应的接口操作函数。
(5)、在C Code工程代码中进行编码格式转换
在上一步新建的C工程中;通过自动生成的App Signal接口获取其文本值(如下的AS_NameOfSong_GetText()函数);因为在Vspy中,关于中文使用的是GB2312编码格式(英文数字是使用ASCII码);所以我们需要通过编程对其进行编码格式的转换。代码如下:
int GetNameOfSong(void)
{
unsigned char Name[512];
AS_NameOfSong_GetText(Name); /*获取文本控件的输入信息*/
unsigned short LengthOfSongName = 0u;
for (int i = 0; i < strlen(Name); i++) /*计算歌曲名字字符长度*/
{
if (Name[i] < 0xA1) /*是数字英文字符*/
{
LengthOfSongName++;
}
else
{
if ((Name[i + 1] > 0xA0) && (Name[i + 1] < 0xFF)) /*是GB2312编码*/
{
LengthOfSongName++;
i++;
}
}
}
/*GB2312转Unicode*/
int wLen = MultiByteToWideChar(CP_ACP, 0, Name, -1, NULL, 0);
LPWSTR Name_Unicode = NULL;
Name_Unicode = (LPWSTR)malloc((sizeof(WCHAR))* wLen);
MultiByteToWideChar(CP_ACP, 0, Name, -1, Name_Unicode, wLen);
/*Unicode转Utf8*/
int Len = WideCharToMultiByte(CP_UTF8, 0, Name_Unicode, -1, NULL, 0, NULL, NULL);
char * Name_Utf8 = NULL;
Name_Utf8 = (char *)malloc((sizeof(char))* Len);
WideCharToMultiByte(CP_UTF8, 0, Name_Unicode, -1, Name_Utf8, Len, NULL, NULL);
return 0;
}
(6)、通过生成的_Tranmit(参数)函数接口进行报文发送,操作可对应查看“Vspy工程之C Code Interface的使用”一文中4.2小节中对其的使用介绍。