在 Windows 平台上使用 C 语言进行图形界面开发,通常需要依赖于某种 GUI 库或框架。常见的选择有 Win32 API、GTK、Qt 等。在本次讲解中,我们将使用 Win32 API 进行一个简单的 C 语言图形界面开发示例。Win32 API 是微软提供的一套用于 Windows 应用程序开发的原生 API,它提供了创建和管理窗口、处理事件、绘图等功能。
在开始之前,需要确保您的开发环境已经准备好,包括:
我们将使用 MinGW GCC 进行编译。
Win32 API 是用于开发 Windows 应用程序的底层 API,使用它可以直接访问 Windows 操作系统的核心功能。
以下是使用 Win32 API 创建一个简单窗口的完整代码示例及详细解释。
#include <windows.h>
// 定义窗口过程函数的原型
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
// WinMain 是 Windows 应用程序的入口点
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
// 定义并初始化窗口类结构体
const char CLASS_NAME[] = "Sample Window Class";
WNDCLASS wc = {0}; // 初始化 WNDCLASS 结构体
wc.lpfnWndProc = WindowProc; // 窗口过程函数指针
wc.hInstance = hInstance; // 当前应用程序实例句柄
wc.lpszClassName = CLASS_NAME; // 窗口类名称
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // 光标样式
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // 背景颜色
// 注册窗口类
RegisterClass(&wc);
// 创建窗口
HWND hwnd = CreateWindowEx(
0, // 可选的窗口扩展样式
CLASS_NAME, // 窗口类名
"C Language Windows GUI", // 窗口标题
WS_OVERLAPPEDWINDOW, // 窗口风格
// 窗口位置和大小
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // 父窗口句柄
NULL, // 菜单句柄
hInstance, // 应用程序实例句柄
NULL // 传递给窗口的附加应用程序数据
);
// 检查窗口是否创建成功
if (hwnd == NULL) {
return 0;
}
// 显示窗口
ShowWindow(hwnd, nShowCmd);
// 进入消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg); // 翻译消息
DispatchMessage(&msg); // 分发消息到窗口过程
}
return 0;
}
// 窗口过程函数
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_DESTROY: // 处理窗口销毁消息
PostQuitMessage(0);
return 0;
case WM_PAINT: // 处理窗口重绘消息
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// 绘制文本
TextOut(hdc, 10, 10, "Hello, Windows!", 15);
EndPaint(hwnd, &ps);
}
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
包含头文件
#include <windows.h>
windows.h
是包含所有 Windows API 函数和宏定义的头文件。窗口过程函数
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
WindowProc
是一个回调函数,用于处理窗口的各种消息。它的参数包括:
HWND hwnd
:窗口的句柄。UINT uMsg
:消息标识符。WPARAM wParam
和 LPARAM lParam
:附加的消息信息。应用程序入口点
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
...
}
WinMain
是 Windows 应用程序的入口函数。HINSTANCE hInstance
:当前应用程序实例的句柄。HINSTANCE hPrevInstance
:前一个实例的句柄(已废弃,通常为 NULL)。LPSTR lpCmdLine
:命令行参数。int nShowCmd
:显示窗口的方式。定义窗口类
const char CLASS_NAME[] = "Sample Window Class";
WNDCLASS wc = {0};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
RegisterClass(&wc);
WNDCLASS
结构体用于定义窗口类。
lpfnWndProc
:指向窗口过程函数的指针。hInstance
:应用程序实例的句柄。lpszClassName
:窗口类名称。hCursor
:光标样式。hbrBackground
:窗口背景画刷。RegisterClass
注册窗口类。
创建窗口
HWND hwnd = CreateWindowEx(
0,
CLASS_NAME,
"C Language Windows GUI",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
CreateWindowEx
函数用于创建窗口。
0
:扩展窗口样式。CLASS_NAME
:窗口类名。"C Language Windows GUI"
:窗口标题。WS_OVERLAPPEDWINDOW
:窗口风格。CW_USEDEFAULT
:窗口位置和大小。NULL
:父窗口句柄。NULL
:菜单句柄。hInstance
:应用程序实例句柄。NULL
:附加应用程序数据。显示窗口
ShowWindow(hwnd, nShowCmd);
ShowWindow
函数用于显示窗口。消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GetMessage
函数用于从消息队列中检索消息。TranslateMessage
函数用于翻译键盘消息。DispatchMessage
函数用于将消息分派到窗口过程。窗口过程函数
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
TextOut(hdc, 10, 10, "Hello, Windows!", 15);
EndPaint(hwnd, &ps);
}
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
WM_DESTROY
:处理窗口销毁消息,调用 PostQuitMessage(0)
终止应用程序。WM_PAINT
:处理窗口重绘消息。
BeginPaint
:开始绘制。TextOut
:输出文本。EndPaint
:结束绘制。如果您使用 MinGW,您可以通过以下命令编译代码:
gcc -o myapp myapp.c -lgdi32
-lgdi32
是链接器选项,用于链接 Windows 图形设备接口 (GDI