滴水-day38-WIN32-宽字符
宽字符
在编程中通常会遇到多语言的问题,也就是每个国家都有不同的语言,如果没有一个统一的表就无法直接表示各个国家的语言。
在WIN32中有两个码表,分别是ASCII和UNICODE。
ASCII码表通常是只表示一个字符或者一个字节,这个在使用英文语言下是使用最多的一个码表,还有一个是UNICODE码表,这个码表很大,几乎包括了这个世界上各个国家常用的文字。
例如中文:
在WIN32中,一个中文无法使用ASCII码表进行表示,所以中国大佬就创建了一个规则,一个中文字符使用两个字节进行表示,再查表组合成一个中文。
在不同的码表中所表示的字节也不不一样的。
在ASCII中:
中国表示为:
//d6 d0 b9 fa 00
在UNICODE中:
//2d 4e fd 56 00 00
可以发现UNICODE中是以两个00为结束标志的。
也就是说不管是任何字符,只要使用了UNICODE都是以两个字节进行表示。
Unicode中的每个字符都是16位宽而不是8位宽
在C语言中使用wchar_t表示宽字符,但是无法直接给这个宽字符进行赋值,因为编译器默认使用了ASCII码表,我们需要手动告述编译器使他使用UNICODE码表。在字符串前加一个L
wchar_t temp[] = L"中国";
这样就不会报错了。
wchar_t temp[] = L"中国";
wchar_t data[30];
wprintf(L"%s\\n", temp);
cout << wcslen(temp) << endl; // 2;
wcscpy_s(data, temp);
wprintf(L"%s", data);
wchar_t aa[] = L"AAAA";
wcscat_s(data, aa);
wprintf(L"%s\\n", data);
cout << wcscmp(temp, data) << endl;
WCHAR *sss = wcsstr(temp, data);
wprintf(L"%s\\n", sss);
在以上使用中,不知道什么时候使用ASCII和UNICODE码表,这个时候我们可是使用TEXT来指定字符串的格式,当当前项目使用ASII的时候,就相当于“AAA”,当项目使用了UNICODE的时候就相当于使用了L”AAA”
WIN32入口程序
在WIN32中,有很多的宏,这些宏无非就是给C语言中的一些关键字什么的起了一个新的名字。
在win32中多字节与宽字符的区别
MessageBoxA(0,"内容多字节","标题",MB_OK);
MessageBoxW(0,L"内容宽字节",L"标题",MB_OK);
MessageBox(0,TEXT("根据项目字符集决定"),TEXT("标题"),MB_OK);
Windows提供的API 凡是需要传递字符串参数的函数,都会提供两个版本和一个宏.
这就是是为什么有的API会有A版和W版。其实就是ASCII和UNICODE的区别。
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
这是一个WIN32应用程序的入口点也就是main函数,他与控制台程序的main函数不同,首先是参数的个数不一样。
APIENTRY:__stdcall
这个宏就是调用约定中的_stdcall,与控制台函数一样。
wWinMain参数解释
hInstance:应用程序的当前实例的句柄,也是当前程序的ImageBase hPrevInstance:此参数始终 NULL lpCmdLine:应用程序的命令行,不包括程序名称 nShowCmd:控制窗口的显示方式,参考 ShowWindow 函数
返回值:
如果函数成功,在收到 WM_QUIT 消息时终止,它应返回该消息 wParam 参数中包含的退出值。 如果函数在输入消息循环之前终止,则应返回零。
格式化输出
因为原有的OutputDebugString并不支持%d%s什么的,所以需要重写一个函数用来支持这样的功能
void __cdecl OutputDebugStringF(const char* format, ...)
{
char strBuffer[4096]; // 使用栈上缓冲区
va_list vlArgs;
va_start(vlArgs, format);
vsnprintf(strBuffer, sizeof(strBuffer), format, vlArgs); // 更安全的格式化函数
va_end(vlArgs);
// 添加换行符
strcat_s(strBuffer, sizeof(strBuffer), "\\n");
// 输出到调试窗口
OutputDebugStringA(strBuffer);
}
在WIN32中,如果有一些运行中的错误,他是不会报出来的,需要我们手动获取到错误去查错误表
使用**GetLastError函数,**该函数返回一个DWORD的值,根据这个值去微软提供的错误表查找相应的错误。
WNDCLASSEXW类参数
cbSize:此结构的大小(以字节为单位)。 将此成员设置为
sizeof(WNDCLASSEX)
style:类样式 () 。 此成员可以是 类样式的任意组合 lpfnWndProc:此窗口的消息处理函数 cbClsExtra:0 cbWndExtra:0 ****hInstance:实例的句柄,该实例包含类的窗口过程 hIcon:窗口图标 hCursor:窗口光标 hbrBackground:窗口背景色 lpszMenuName:菜单资源名称 lpszClassName:类名 hIconSm:小图标资源
WNDCLASSEXW参数填写完毕后使用RegisterClassExW完成注册。
InitInstance自定义函数,显示窗口
CreateWindowW函数创建窗口
ShowWindow函数显示窗口