这不仅仅是指写一个 "Hello, World!",而是指如何利用 Windows 提供的庞大 API(应用程序编程接口)来创建具有图形界面、能够与操作系统交互的桌面应用程序。

核心概念:Windows API
-
什么是 Windows API? 你可以把 Windows 操作系统想象成一个功能极其丰富的“工具箱”,Windows API 就是这个工具箱里所有工具的说明书和接口,它是由微软提供的一套函数、宏、结构体和消息的集合,允许你的 C 程序直接调用操作系统的功能,
- 创建窗口
- 在窗口上绘图
- 处理用户输入(鼠标点击、键盘敲击)
- 访问文件系统
- 管理内存和进程
-
与标准 C 的区别 标准 C 库(如
stdio.h,stdlib.h)是跨平台的,它不关心你运行在 Windows、Linux 还是 macOS 上,而 Windows API 是平台特定的,你编写的代码只能在 Windows 上编译和运行。
开发环境准备
要进行 Windows API 编程,你需要一个 C 语言编译器和一个集成开发环境。
推荐工具链:Visual Studio (VS)
这是最简单、最强大的选择,尤其适合初学者,微软为它提供了顶级的 Windows 开发支持。

-
下载安装 Visual Studio Community
- 访问 Visual Studio 官方网站:https://visualstudio.microsoft.com/zh-hans/
- 下载 "Community" 版本,它是免费的。
- 在安装程序中,确保勾选 “使用 C++ 的桌面开发” 这个工作负载,这个工作负载包含了 C/C++ 编译器、Windows SDK(软件开发工具包)和调试器。
-
创建第一个项目
- 打开 Visual Studio。
- 选择 "创建新项目"。
- 在模板搜索框中输入 "Windows 桌面应用程序"。
- 选择 "C++ 空项目" (即使你写 C 代码,这个项目模板也能完美工作,因为它包含了所有必要的配置)。
- 给项目命名,
MyFirstWinApp,然后点击创建。 - 在右侧的 "解决方案资源管理器" 中,右键点击 "源文件" -> "添加" -> "新建项"。
- 选择 "C++ 文件 (.cpp)",将其命名为
main.c(.c 扩展名告诉编译器这是 C 代码)。
现在你已经准备好写代码了!
经典 Windows 程序剖析:一个窗口的诞生
下面是一个最简单的 Windows 程序,它创建一个空白窗口并显示出来,代码看起来可能有点复杂,但我会逐行解释。
#include <windows.h> // 必须包含的头文件,所有 Windows API 都在这里
// 1. 窗口过程函数 - 这是窗口的“大脑”,负责处理所有消息
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY: // 当用户点击窗口的 'X' 关闭按钮时,会收到这个消息
PostQuitMessage(0); // 发送一个 WM_QUIT 消息,告诉程序该退出了
return 0;
case WM_PAINT: // 当窗口需要重绘时(如首次显示、被另一个窗口遮挡后),会收到这个消息
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// 在这里进行绘图操作,比如画文字
TextOut(hdc, 5, 5, L"Hello, Windows API!", wcslen(L"Hello, Windows API!"));
EndPaint(hwnd, &ps);
}
return 0;
}
// 对于我们没有处理的消息,交给系统默认处理
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
// 2. 程序入口点 - 与标准 C 的 main 不同
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// 3. 注册窗口类 - 告诉系统我们要创建一个什么样的窗口
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc; // 窗口过程函数的地址
wc.hInstance = hInstance; // 当前应用程序的实例句柄
wc.lpszClassName = CLASS_NAME; // 窗口类的名称
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // 窗口内显示的鼠标样式
RegisterClass(&wc); // 向系统注册这个窗口类
// 4. 创建窗口
HWND hwnd = CreateWindowEx(
0, // 可选的窗口样式
CLASS_NAME, // 窗口类的名称
L"Learn to Program Windows", // 窗口标题
WS_OVERLAPPEDWINDOW, // 窗口样式
// 窗口位置和大小
CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
NULL, // 父窗口句柄
NULL, // 菜单句柄
hInstance, // 实例句柄
NULL // 额外的创建参数
);
if (hwnd == NULL)
{
return 0;
}
// 5. 显示窗口
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// 6. 消息循环 - 程序的心跳
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg); // 翻译键盘消息
DispatchMessage(&msg); // 将消息发送给 WindowProc 函数处理
}
// 当 GetMessage 返回 0 时,程序结束
return 0;
}
代码详解:
-
#include <windows.h>一切 Windows 编程的起点,包含了所有必需的定义。 -
WinMain函数- 这是 Windows 程序的入口点,类似于标准 C 的
main函数。 HINSTANCE hInstance: 当前程序的实例句柄,你可以把它想象成一个程序的“身份证号”,操作系统用它来区分不同的程序实例。HWND hwnd: Handle to a Window,窗口句柄,是你在程序中操作一个窗口的唯一标识符,几乎所有与窗口相关的 API 都需要它作为参数。
- 这是 Windows 程序的入口点,类似于标准 C 的
-
WNDCLASS结构体与RegisterClass在创建窗口之前,你必须先“注册”一个窗口类,这个类定义了窗口的“模板”或“蓝图”,包括:- 窗口的外观(图标、鼠标样式)
- 窗口的行为(如何处理消息)
- 窗口类的名称
-
CreateWindowEx使用注册好的窗口类,真正创建出一个窗口实例,这个函数返回窗口的句柄hwnd。 -
ShowWindow和UpdateWindow创建窗口后,它只是存在于内存中,你看不到。ShowWindow负责将其显示在屏幕上。UpdateWindow会立即请求一次窗口重绘(发送WM_PAINT消息)。 -
MSG结构体与GetMessage这是 Windows 程序的核心——消息循环。- Windows 是一个事件驱动的系统,用户的每一个操作(点击、移动、输入)和系统内部的每一个变化(窗口被创建、被销毁)都会被转换成一个“消息”,并放入一个消息队列中。
GetMessage函数会从这个队列中取出消息。- 如果队列为空,
GetMessage会让程序进入“休眠”状态,不占用 CPU 资源。 - 当它取到
WM_QUIT消息时,会返回0,从而结束循环,程序退出。
-
WindowProc函数 这是窗口的“大脑”。DispatchMessage函数会将GetMessage取出的消息传递给WindowProc。WindowProc根据消息的类型(uMsg)执行相应的操作。WM_DESTROY: 窗口被销毁时发送,我们在这里调用PostQuitMessage(0)来结束消息循环。WM_PAINT: 窗口需要重绘时发送,我们必须处理这个消息,否则窗口可能会是空白的或残缺的。BeginPaint和EndPaint是一对函数,用于获取设备上下文并进行绘图。
核心编程模型:事件驱动
理解了上面的例子,你就理解了 Windows 程序的核心模型:
- 注册窗口类 -> 创建窗口 -> 进入消息循环
- 程序的大部分时间都在
while(GetMessage(...))循环中等待。 - 当一个事件发生时,操作系统向你的程序发送一个消息。
- 你的程序响应这个消息,执行相应的操作,然后继续等待。
这与传统的、按顺序执行的程序(读数据 -> 处理数据 -> 输出结果)完全不同。
进阶主题
当你掌握了创建窗口和基本消息处理后,可以探索更高级的主题:
- 控件:在窗口中添加按钮、编辑框、列表框等,这通常通过 Dialog Boxes (对话框) 来实现。
- 绘图:使用 GDI (Graphics Device Interface) 或更现代的 Direct2D/Direct3D 在窗口上绘制复杂的图形、图像和动画。
- 文件 I/O:使用
CreateFile,ReadFile,WriteFile等 API 代替标准 C 的fopen,fread,它们提供了更强大的功能和性能。 - 注册表:通过
RegOpenKeyEx,RegSetValueEx等 API 读写 Windows 注册表,用于存储程序配置。 - 多线程:使用
CreateThreadAPI 创建多个线程,实现程序的并行处理,提高响应速度。 - Windows SDK 版本:Windows API 非常庞大,并且随着新版本的 Windows 不断更新,你需要确保你的项目链接到你目标系统支持的 SDK 版本。
现代替代方案:.NET 与 C++
虽然用 C 语言直接调用 Windows API 是一种非常经典且能让你深入了解操作系统底层的方式,但在现代开发中,也有一些更高效的替代方案:
-
C++ / WinUI (Windows UI Library) / MFC (Microsoft Foundation Classes):
- C++ 是性能之王,使用 C++ 可以直接调用 Windows API,也可以使用更高层次的框架。
- WinUI 3 是微软最新的原生 UI 框架,使用 C++ 和 XAML(一种声明式 UI 语言)来构建现代化的 Windows 应用,外观和体验与 UWP 应用一致。
- MFC 是一个比较老的 C++ 类库,它将复杂的 Windows API 封装成了更易于使用的 C++ 类。
-
C# / .NET / WinUI / WPF / WinForms:
- 对于大多数桌面应用开发,这是目前最推荐的方案。
- C# 是一种现代、类型安全的语言。
- .NET 提供了强大的类库,极大地简化了文件操作、网络通信、数据库访问等任务。
- WinUI / WPF / WinForms 都是用于构建用户界面的框架,让你可以通过拖拽控件和编写 XAML/C# 代码快速开发出功能完善、界面美观的应用。
| 方面 | 描述 |
|---|---|
| 核心 | Windows API,通过 C 语言调用系统功能。 |
| 关键概念 | 句柄、消息、事件驱动模型、窗口过程。 |
| 入门步骤 | 安装 Visual Studio。 创建 C++ 空项目。 编写 WinMain、注册窗口类、创建窗口、实现消息循环。 |
| 优点 | 性能最高,对系统控制最精细,适合开发底层工具、游戏引擎、性能敏感型应用。 |
| 挑战 | 代码量大,概念复杂(如句柄、消息循环),开发效率相对较低。 |
| 现代替代 | C# + .NET 是目前开发商业桌面应用的主流选择,开发效率更高。 |
从 C 语言和 Windows API 入手,虽然门槛稍高,但能让你深刻理解 Windows 程序的运行机制,是成为一名优秀 Windows 开发者的重要基石。
