ZetCode

Windows API 主要函数

最后修改于 2023 年 10 月 18 日

在本 Windows API 教程中,我们讨论主要函数。

主要函数原型

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

int main(void);
int main(int argc, char **argv);
int main(int argc, char *argv[]);

以下是经典控制台程序的 main 函数的原型。

classic_console.c
#include <stdio.h>

int main(void) {

    puts("This is a classic C program.");

    return 0;
}

上述源代码展示了经典控制台 C 程序的示例。

C:\Users\Jano\Documents\WinApi\ClassicConsole>ClassicConsole.exe
This is a classic C program.

这是 ClassicConsole.exe 程序的输出。

wmain 函数原型

以前的 main 函数原型只能接收 ASCII 字符。 如果我们希望程序能够从命令行接收宽字符,我们使用 wmain 函数原型。

int wmain(void);
int wmain(int argc, wchar_t **argv);
int wmain(int argc, wchar_t *argv[]);

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

win_console.c
#include <windows.h>
#include <wchar.h>

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

    PDWORD cChars = NULL;
    HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);

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

    if (argv[1]) {

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

    CloseHandle(std);

    return 0;
}

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

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

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

HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);

GetStdHandle 函数返回标准输出的句柄。

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

如果发生错误,我们将收到 INVALID_HANDLE_VALUE 返回代码。 对于这种情况,我们打印一条错误消息。 GetLastError 函数检索最后一个错误代码值。

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

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

CloseHandle(std);

CloseHandle 函数关闭已打开的标准输出句柄。

C:\Users\Jano\Documents\WinApi\WindowsConsole>WindowsConsole.exe компилятор
компилятор

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

_tmain 函数原型

_tmain 函数是 Microsoft 的扩展。 它使程序员可以轻松地创建程序的 ANSI 和 UNICODE 版本。 它是一个 C 宏,根据是否定义了 _UNICODE 常量,它会转换为 wmainmain 函数。

过去,创建 ANSI 和 UNICODE 版本是很常见的。 如今,建议创建 Unicode 程序,除非我们有特定的理由创建 ANSI 版本。

int _tmain(void);
int _tmain(int argc, TCHAR **argv);
int _tmain(int argc, TCHAR *argv[]);

以下是 _tmain 函数原型。 TCHAR 宏转换为 charwchar_t。 它由 UNICODE 常量控制。

tmain_ex.c
#define _UNICODE
#define UNICODE

#ifndef UNICODE
    #include <stdio.h>
#endif

#include <windows.h>
#include <tchar.h>

int _tmain(int argc, TCHAR **argv)
{
    PDWORD cChars = NULL;
    HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);

    if (std == INVALID_HANDLE_VALUE) {
        _tprintf(_T("Cannon retrieve standard output handle\n (%d)"), GetLastError());
    }

    if (argv[1]) {
        WriteConsole(std, argv[1], _tcslen(argv[1]), cChars, NULL);
    }

    CloseHandle(std);

    return 0;
}

如果可用,该示例打印其第一个参数。

#define _UNICODE
#define UNICODE

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

#ifndef UNICODE
    #include <stdio.h>
#endif

如果版本是 ANSI,我们包含 <stdio.h> 标头。

#include <windows.h>

我们包含 TCHAR 宏的定义。 该宏受 UNICODE 常量的影响。

#include <tchar.h>

我们必须包含此标头文件才能使用 _tmain_tcslen 宏。 它们根据 _UNICODE 常量进行转换。

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

_tmain 函数在我们这里转换为 wmain,而 TCHAR 宏转换为 wchar_t

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

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

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

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

WinMain 函数原型

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

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PWSTR pCmdLine, int nCmdShow);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow);
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPTSTR lpCmdLine, int nCmdShow);

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

当入口点是 WinMain 时,程序的执行开始于 WinMainCRTStartup。 如果是 wWinMain,则执行开始于 wWinMainCRTStartup

winmain_ex.c
#include <windows.h>

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
               PWSTR szCmdLine, int CmdShow) {

    MessageBoxW(NULL, szCmdLine, L"Title", MB_OK);

    return 0;
}

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

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

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

A message box
图:消息框

在本 Windows API 教程中,我们提到了主要函数。