注:最后有面试挑战,看看自己掌握了吗
根本原因是程序使用了标准函数,而在你的机器上,没有这个标准函数对应的动态库实现,如果想要顺利运行则需要到官方网站下载对应版本的动态库安装即可
如果你没有依赖其它第三方库,默认 IDE 中指定的运行时库的方式是动态链接,这情况下,会依赖于特定版本的运行时库,具体的编译选项是
/MT、/MTd 以及 /MD 和 /MDd 。后面的小d表示 Debug 和 Release 之分,而 MT 和 MD
则是选择使用静态编译还是动态编译,如果发布程序选择 /MT 选项进行链接,则可以避免在其它机器上运行时缺失动态库的麻烦。
数据类型 大小 有符号?
BYTE 8 bits Unsigned
DWORD 32 bits Unsigned
INT32 32 bits Signed
INT64 64 bits Signed
LONG 32 bits Signed
LONGLONG 64 bits Signed
UINT32 32 bits Unsigned
UINT64 64 bits Unsigned
ULONG 32 bits Unsigned
ULONGLONG 64 bits Unsigned
WORD 16 bits Unsigned
RECT* rect; // Pointer to a RECT structure.
LPRECT rect; // The same PRECT rect; // Also the same.
DWORD_PTR
INT_PTR
LONG_PTR
ULONG_PTR
UINT_PTR
p 指针
h 句柄
sz 字符串
b BYTE
ul ULONG
l LONG
i INT
ui UINT
ch CHAR
dw DWORD
hr HRESULT
typedef wchar_t WCHAR
声明一个宽字符或者一个宽字符串需要将 L 放到文件前面:wchar_t a = L'a';
wchar_t *str = L"hello";
类型 定义
CHAR char
PSTR or LPSTR char*
PCSTR or LPCSTR const char*
PWSTR or LPWSTR wchar_t*
PCWSTR or LPCWSTR const wchar_t*
因为微软提供对 Unicde 的支持,所以它将每个和字符串相关的 API 都提供了两个版本,一种是 ANSI 字符串版本,另一种是Unicode 字符串版本。
为使计算机支持更多语言,通常使用 0x80~0xFFFF 范围的 2 个字节来表示 1 个字符。比如:汉字 ‘中’ 在中文操作系统中,使用 [0xD6,0xD0] 这两个字节存储。
不同的国家和地区制定了不同的标准,由此产生了 GB2312、GBK、GB18030、Big5、Shift_JIS 等各自的编码标准。这些使用多个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文Windows操作系统中,ANSI 编码代表 GB2312编码;在繁体中文Windows操作系统中,ANSI编码代表Big5;在日文Windows操作系统中,ANSI 编码代表 JIS 编码。 [1] [2]
不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。ANSI编码表示英文字符时用一个字节,表示中文用两个或四个字节。
ANSI编码作为中国以及部分亚太地区的多字符编码格式,Windows系统和OS X都是提供原生支持的。但是即便如此,许多国外开发者仍然在开发笔记或者文字录入类应用的时候将ANSI编码完全忽略,只加入全球通用的UTF-8编码。
SetWindowTextA
需要传入 ANSI 字符串。SetWindowTextW
需要传入 Unicode 字符串。#ifdef UNICODE
#define SetWindowText SetWindowTextW
#else
#define SetWindowText SetWindowTextA
#endif
SetWindowText
函数设置标题即可。宏 Unicode ANSI
TCHAR wchar_t char
TEXT(“x”) L”x” “x”
SetWindowText(TEXT("My Application"));
该语句等价于:
SetWindowTextW(L"My Application"); // Unicode function with wide-character string.
SetWindowTextA("My Application"); // ANSI function.
如今,TEXT 和 TCHAR 宏的用处已经很小了,因为所有的程序都应该使用 Unicode 字符,然而你在一些老的程序中仍然看见它们的身影。
除了上边的问题,在头文件中,微软 C 运行时库中,仍然存在类似的宏定义,例如涉及到字符操作的函数:
#ifdef _UNICODE
#define _tcslen wcslen
#else
#define _tcslen strlen
#endif
每个 Windows 程序都有一个类似 main 函数的入口函数,名字叫做 WinMain 或者 wWinMain , 其声明如下:int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);
该函数有四个参数:
hInstance 参数的含义是一个实例句柄,或者是一个模块句柄。该参数代表被加载到内存的可执行程序(exe文件)。某些 Windows API 可能需要该参数。如:加载图标或者加载位图等等。
hPrevInstance 该参数无意义,它在过去的16位操作系统中被使用,现在永远为0。
pCmdLine 该参数是程序传入的命令行参数,和 main 函数中的 argv 参数含义类似,只不过现在的字符集是 Unicode。
nCmdShow 该参数是一个整数,代表应用程序主窗口的显示状态,是最小化、最大化还是正常显示。
WINAPI 是一种调用约定。这个约定确保函数从调用者那里接收参数的相关规则,例如,参数在栈中保存的顺序等等。在写代码的时候一定不要忘记该约定的标识。
WinMain 和 wWinMain 默认是等价的,除非命令行参数是一个 ANSI 字符串,Unicode 版本永远是首选
。如果是 Unicode 版本,你可以传递一个 ANSI 字符串,反之不可
可以通过 GetCommandLine
函数获取命令行参数,这个函数返回一个单一的字符串。
获取参数的数组样式,可以通过 CommandLineToArgvW
函数完成。
编译器是怎样知道调用 wWinMain
还是调用标准的 main 函数?
实际情况下,在微软的 C 运行时库(CRT)中提供了一个 main 函数实现,其内部会调用 WinMain 或者 wWinMain。
CRT 中 main 函数的内部在调用 wWinMain 之前做了一些额外的工作,
例如初始化一些静态成员或者其它 C 函数的初始化操作等等。虽然你可以手动指定不同的链接不同的入口函数,但是仍然推荐你使用 CRT 默认提供的入口点函数,否则 CRT 内部的一些代码将被会跳过,有可能会导致一些异常的结果。
空的 WinMain 函数:
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR lpCmdLine, INT nCmdShow)
{
return 0;
}
🍃博主昵称:
一拳必胜客
🌸博主寄语:欢迎点赞收藏关注哦,一起成为朋友一起成长;
特别鸣谢:木芯工作室 、Ivan from Russia
部分来源:https://meishizaolunzi.com/winmain-ying-yong-cheng-xu-ru-kou-dian/