原文: http://zetcode.com/gui/winapi/main/

在 Windows API 教程的这一部分中,我们将讨论main函数。

main函数原型

main()函数是 C 程序的入口点。 但是,它不是第一个运行的程序。 当入口点为main()时,程序实际上从称为mainCRTStartup()的函数开始执行。 该函数位于 C 运行时库中。 它初始化诸如内存管理器,文件 I/O 支持和argv参数之类的东西。 之后,mainCRTStartup()函数将调用main()函数。

  1. int main(void);
  2. int main(int argc, char **argv);
  3. int main(int argc, char *argv[]);

这些是经典控制台程序的main()函数的函数原型。

classic_console.c

  1. #include <stdio.h>
  2. int main(void) {
  3. puts("This is a classic C program.");
  4. return 0;
  5. }

上面的源代码提供了经典控制台 C 程序的示例。

  1. C:\Users\Jano\Documents\Pelles C Projects\ClassicConsole>ClassicConsole.exe
  2. This is a classic C program.

这是ClassicConsole.exe程序的输出。

wmain函数原型

先前的main函数原型只能接收 ASCII 字符。 如果我们想要一个可以从命令行接收宽字符的程序,我们将使用wmain()函数原型。

  1. int wmain(void);
  2. int wmain(int argc, wchar_t **argv);
  3. int wmain(int argc, wchar_t *argv[]);

上面的wmain()函数原型在命令行上接收wchar_t字符。 当我们使用这些原型时,执行从名为wmainCRTStartup()的函数开始,该函数随后将调用wmain()函数。

win_console.c

  1. #include <windows.h>
  2. #include <wchar.h>
  3. int wmain(int argc, wchar_t **argv) {
  4. PDWORD cChars = NULL;
  5. HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);
  6. if (std == INVALID_HANDLE_VALUE) {
  7. wprintf(L"Cannot retrieve standard output handle\n (%d)",
  8. GetLastError());
  9. }
  10. if (argv[1]) {
  11. WriteConsoleW(std, argv[1], wcslen(argv[1]), cChars, NULL);
  12. }
  13. CloseHandle(std);
  14. return 0;
  15. }

我们有一个wmain()函数,可以接收宽字符。 该示例显示控制台程序的第一个参数。 要在 Pelles C 中插入命令行参数,我们转到项目选项,然后选择常规选项卡。 有一个名为“命令行参数”的编辑框。

  1. int wmain(int argc, wchar_t **argv) {

wmain()函数的第二个参数的wchar_t类型告诉我们程序输入为宽字符。

  1. HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);

GetStdHandle()函数将句柄返回到标准输出。

  1. if (std == INVALID_HANDLE_VALUE) {
  2. wprintf(L"Cannot retrieve standard output handle\n (%d)",
  3. GetLastError());
  4. }

如果发生错误,我们会收到INVALID_HANDLE_VALUE返回码。 对于这种情况,我们将显示一条错误消息。 GetLastError()函数检索上一个错误代码值。

  1. WriteConsoleW(std, argv[1], wcslen(argv[1]), cChars, NULL);

我们使用WriteConsoleW()函数以宽字符写入控制台。

  1. CloseHandle(std);

CloseHandle()函数将打开的手柄关闭到标准输出。

  1. C:\Users\Jano\Documents\Pelles C Projects\WindowsConsole>WindowsConsole.exe компилятор
  2. компилятор

我们将俄语单词(编译器)作为参数传递给程序。 该程序只需将参数打印回控制台即可。 请注意,为了查看正确的字符,我们需要将控制台的默认字体更改为 Lucida Console。 我们需要一种真正的字体来正确显示宽字符。

_tmain函数原型

_tmain()函数是 Microsoft 扩展。 它使程序员可以轻松地创建程序的 ANSI 和 UNICODE 版本。 它是一个 C 宏,它转换为wmain()main()函数,具体取决于是否定义了_UNICODE常量。 在过去,创建 ANSI 和 UNICODE 构建都是很常见的。 如今,许多程序员建议仅创建 Unicode 程序。 这也是我们在本教程中将要做的。 我们将主要创建 Unicode 程序。

  1. int _tmain(void);
  2. int _tmain(int argc, TCHAR **argv);
  3. int _tmain(int argc, TCHAR *argv[]);

这些是_tmain函数原型。 TCHAR宏转换为charwchar_t。 它由UNICODE常数控制。

tmain_ex.c

  1. #define _UNICODE
  2. #define UNICODE
  3. #include <windows.h>
  4. #include <tchar.h>
  5. int _tmain(int argc, TCHAR *argv[]) {
  6. PDWORD cChars = NULL;
  7. HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);
  8. if (std == INVALID_HANDLE_VALUE) {
  9. _tprintf(L"Cannot retrieve standard output handle\n (%d)",
  10. GetLastError());
  11. }
  12. if (argv[1]) {
  13. WriteConsole(std, argv[1], _tcslen(argv[1]), cChars, NULL);
  14. }
  15. CloseHandle(std);
  16. return 0;
  17. }

该示例输出其第一个参数(如果有)。

  1. #define _UNICODE
  2. #define UNICODE

在这里,我们定义两个常数。 这些定义意味着我们将构建一个 Unicode 程序。 它们转换 C 运行时和 Windows 头文件中的 C 宏。 _UNICODE常量在 C 运行时中转换宏。 (这些宏以下划线开头。)UNICODE常量转换 Windows 头文件中的宏。

  1. #include <windows.h>

我们包括TCHAR宏的定义。 宏受UNICODE常数的影响。

  1. #include <tchar.h>

我们必须为_tmain_tcslen宏包含此头文件。 根据_UNICODE常数翻译它们。

  1. int _tmain(int argc, TCHAR *argv[]) {

在我们的情况下,_tmain()函数将转换为wmain()TCHAR宏将转换为wchar_t

  1. WriteConsole(std, argv[1], _tcslen(argv[1]), cChars, NULL);

WriteConsole()宏被转换为WriteConsoleW()函数。 WriteConsoleW()将输出写入控制台。 _tcslen宏被转换为wcslen()函数; 它返回宽字符串的长度。

  1. C:\Users\Jano\Documents\Pelles C Projects\TMainEx>TMainEx.exe "операционная система"
  2. операционная система

该程序将另一个俄语单词(操作系统)作为参数并将其打印到控制台。

WinMain函数原型

到目前为止,我们已经有了控制台的main函数。 对于图形用户界面开发,我们使用WinMain函数原型之一。

  1. int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  2. PWSTR pCmdLine, int nCmdShow);
  3. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  4. LPSTR lpCmdLine, int nCmdShow);
  5. int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  6. LPTSTR lpCmdLine, int nCmdShow);

这三个函数原型用于 Windows GUI 应用的入口点。 wWinMain()函数的pCmdLine参数包含作为 Unicode 字符串的命令行参数。 WinMain()函数的pCmdLine参数包含作为 ANSI 字符串的命令行参数。 _tWinMain是一个 C 宏,它取决于是否定义了_UNICODE常量,它转换为其他两个函数原型。

当入口点为WinMain()时,程序的执行从WinMainCRTStartup()开始。 在wWinMain()的情况下,执行从wWinMainCRTStartup()开始。

winmain_ex.c

  1. #include <windows.h>
  2. int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  3. PWSTR szCmdLine, int CmdShow) {
  4. MessageBoxW(NULL, szCmdLine, L"Title", MB_OK);
  5. return 0;
  6. }

此代码在屏幕上显示一个小消息框。 它显示第一个命令行参数。

  1. int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  2. PWSTR szCmdLine, int CmdShow)

wWinMain()函数的第三个参数是PWSTR(指向宽字符串的指针)。 它接受宽字符。

Windows API `main`函数 - 图1

图:消息框

在 Windows API 教程的这一部分中,我们提到了main函数。