C 语言本身没有内置的 ListBox 控件。

(图片来源网络,侵删)
ListBox 是一个图形用户界面元素,它属于操作系统提供的窗口控件,要创建和使用 ListBox,你需要依赖于一个图形库或GUI 框架。
下面我将为你介绍几种在 C 语言中创建和使用 ListBox 的主流方法,从最基础到更现代的框架。
使用 Windows API (仅限 Windows 平台)
如果你在 Windows 系统上进行开发,可以使用 Windows API 原生创建 ListBox,这是最底层、最直接的方式,但代码也相对繁琐。
核心概念
- 窗口类: 注册一个窗口类,告诉系统我们的窗口是什么类型,有什么样式。
- 创建窗口: 使用
CreateWindowEx函数创建主窗口,并在这个窗口内部创建 ListBox 控件。 - 消息循环: Windows 应用程序是事件驱动的,你需要一个消息循环来不断检查和处理用户操作(如点击、选择等)。
- 消息处理: 编写一个窗口过程函数(
WndProc),来响应各种消息,特别是WM_COMMAND消息,当 ListBox 中的项目被选中时,会发送这个消息。
示例代码
这是一个完整的、可运行的 Windows API 示例,它会创建一个窗口,窗口内有一个 ListBox,并向其中添加一些项目。

(图片来源网络,侵删)
#include <windows.h>
// 窗口过程函数的声明
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
// 1. 注册窗口类
const char* CLASS_NAME = "Simple Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WndProc; // 窗口过程函数
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
if (!RegisterClass(&wc)) {
MessageBox(NULL, "Window Registration Failed!", "Error", MB_ICONERROR);
return 0;
}
// 2. 创建主窗口
HWND hwnd = CreateWindowEx(
0, // 扩展样式
CLASS_NAME, // 窗口类名
"C Language ListBox Example", // 窗口标题
WS_OVERLAPPEDWINDOW, // 窗口样式
// 窗口位置和大小
CW_USEDEFAULT, CW_USEDEFAULT, 400, 300,
NULL, // 父窗口句柄
NULL, // 菜单句柄
hInstance, // 实例句柄
NULL // 额外参数
);
if (hwnd == NULL) {
MessageBox(NULL, "Window Creation Failed!", "Error", MB_ICONERROR);
return 0;
}
ShowWindow(hwnd, nCmdShow); // 显示窗口
UpdateWindow(hwnd); // 更新窗口
// 3. 消息循环
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg); // 翻译键盘消息
DispatchMessage(&msg); // 发送消息到窗口过程
}
return 0;
}
// 4. 窗口过程函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CREATE: {
// 在窗口创建时,创建 ListBox 控件
// 参数: 父窗口, ID, 位置, 大小, 样式
HWND hListBox = CreateWindow(
"LISTBOX", "",
WS_CHILD | WS_VISIBLE | LBS_STANDARD,
10, 10, 360, 200,
hwnd, (HMENU)1, NULL, NULL
);
// 向 ListBox 添加项目
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)"Apple");
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)"Banana");
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)"Cherry");
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)"Date");
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)"Elderberry");
return 0;
}
case WM_COMMAND: {
// 检查消息是否来自我们的 ListBox (ID为1)
if (LOWORD(wParam) == 1) {
if (HIWORD(wParam) == LBN_SELCHANGE) {
// 用户选择了新项目
int selectedIndex = SendMessage((HWND)lParam, LB_GETCURSEL, 0, 0);
char buffer[256];
SendMessage((HWND)lParam, LB_GETTEXT, selectedIndex, (LPARAM)buffer);
char title[256];
sprintf(title, "You selected: %s", buffer);
MessageBox(hwnd, title, "Selection", MB_OK | MB_ICONINFORMATION);
}
}
return 0;
}
case WM_DESTROY: {
PostQuitMessage(0); // 发送退出消息
return 0;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
如何编译:
你需要一个 C 编译器,MinGW (GCC),将代码保存为 listbox_win.c,然后使用以下命令编译:
gcc listbox_win.c -o listbox_win.exe -mwindows
-mwindows 链接器选项会链接必要的 Windows 库,并创建一个控制台窗口不可见的 GUI 程序。
使用第三方 GUI 库 (跨平台)
为了编写跨平台的 GUI 程序,开发者通常会选择第三方库,这些库封装了底层的 API(如 Windows API、GTK、Qt 等),提供了更简洁、一致的接口。
推荐库
-
GTK+ (GIMP Toolkit)
(图片来源网络,侵删)- 特点: 非常流行,是 Linux 桌面环境(如 GNOME)的原生库,也支持 Windows 和 macOS,使用 C 语言编写,但也有 C++、Python 等语言的绑定。
- 优点: 文档丰富,社区活跃,外观现代。
-
Qt (通过其 C 绑定)
- 特点: 一个功能极其强大的跨平台框架,虽然它主要是用 C++ 实现的,但提供了
Qt for C的 API (QC),让你可以用 C 语言来使用 Qt。 - 优点: 功能最全面,性能优异,支持高级特性。
- 特点: 一个功能极其强大的跨平台框架,虽然它主要是用 C++ 实现的,但提供了
-
Win32Lib (仅限 Windows,但更简单)
- 特点: 一个轻量级的 C 语言库,它封装了 Windows API,使其使用起来比原生 API 简单得多。
示例:使用 GTK+
下面是使用 GTK+ 创建 ListBox 的示例。
环境准备: 你需要安装 GTK+ 开发库。
- 在 Ubuntu/Debian 上:
sudo apt-get install libgtk-3-dev - 在 Windows 上: 从 GTK 官网 下载安装包。
示例代码:
#include <gtk/gtk.h>
// 当窗口关闭时调用的函数
static void activate(GtkApplication* app, gpointer user_data) {
GtkWidget *window;
GtkWidget *listbox;
GtkWidget *box;
// 创建主窗口
window = gtk_application_window_new(app);
gtk_window_set_title(GTK_WINDOW(window), "GTK+ ListBox Example");
gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
// 创建一个垂直盒子,用于放置控件
box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add(GTK_CONTAINER(window), box);
// 创建 ListBox
listbox = gtk_list_box_new();
gtk_container_add(GTK_CONTAINER(box), listbox);
// 向 ListBox 添加行
GtkWidget *row1 = gtk_list_box_row_new();
gtk_container_add(GTK_CONTAINER(row1), gtk_label_new("First Item"));
gtk_container_add(GTK_CONTAINER(listbox), row1);
GtkWidget *row2 = gtk_list_box_row_new();
gtk_container_add(GTK_CONTAINER(row2), gtk_label_new("Second Item"));
gtk_container_add(GTK_CONTAINER(listbox), row2);
GtkWidget *row3 = gtk_list_box_row_new();
gtk_container_add(GTK_CONTAINER(row3), gtk_label_new("Third Item"));
gtk_container_add(GTK_CONTAINER(listbox), row3);
// 显示所有控件
gtk_widget_show_all(window);
}
int main(int argc, char **argv) {
GtkApplication *app;
int status;
app = gtk_application_new("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
}
如何编译:
gcc listbox_gtk.c -o listbox_gtk `pkg-config --cflags --libs gtk+-3.0`
pkg-config 工具会自动帮你找到正确的头文件和库文件路径。
在控制台模拟 (纯 C,无 GUI)
如果你不关心图形界面,只是想在命令行中实现一个类似列表框的功能(比如让用户从多个选项中选择),你可以自己用 C 语言实现一个简单的版本。
实现思路
- 使用
printf显示所有选项。 - 使用
printf和scanf或getchar来获取用户输入。 - 根据用户输入的数字或字母,返回对应的选项。
示例代码
#include <stdio.h>
#include <string.h>
// 定义选项
#define NUM_OPTIONS 5
const char* options[NUM_OPTIONS] = {
"Option 1: Open File",
"Option 2: Save File",
"Option 3: Edit Settings",
"Option 4: Exit Program",
"Option 5: Help"
};
// 显示菜单并获取用户选择
int show_menu() {
int choice;
printf("Please choose an option:\n");
for (int i = 0; i < NUM_OPTIONS; i++) {
printf("%d. %s\n", i + 1, options[i]);
}
printf("Enter your choice (1-%d): ", NUM_OPTIONS);
scanf("%d", &choice);
// 验证输入
if (choice < 1 || choice > NUM_OPTIONS) {
printf("Invalid choice. Please try again.\n");
return -1; // 表示无效选择
}
return choice - 1; // 返回数组索引
}
int main() {
int selected_index;
char selected_option[50];
do {
selected_index = show_menu();
if (selected_index != -1) {
printf("\nYou selected: %s\n", options[selected_index]);
// 这里可以添加根据选择执行的操作
if (selected_index == 3) { // Exit Program
printf("Exiting...\n");
break;
} else {
printf("Press Enter to continue...");
getchar(); // 清除输入缓冲区中的换行符
getchar(); // 等待用户按 Enter
}
}
} while (1); // 循环直到用户选择退出
return 0;
}
总结与对比
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Windows API | - 直接、底层、性能高 - 无需额外库(Windows自带) |
- 仅限Windows平台 - 代码繁琐、复杂 - 学习曲线陡峭 |
Windows平台下的原生开发、学习Windows GUI原理。 |
| GTK+/Qt | - 跨平台(Windows, Linux, macOS) - 代码更简洁、面向对象 - 功能强大、社区支持好 |
- 需要额外安装库 - 库本身可能较大 |
开发需要运行在多个操作系统上的专业桌面应用程序。 |
| 控制台模拟 | - 纯C,无需任何GUI库 - 简单、轻量、可移植性强 |
- 无图形界面,体验差 - 功能极其有限 |
命令行工具、简单的交互式脚本、嵌入式系统。 |
给初学者的建议:
- 如果你想学习Windows 系统编程,可以尝试 Windows API,虽然难,但能让你深入理解 GUI 的工作原理。
- 如果你想快速开发一个跨平台的桌面应用,强烈推荐 GTK+ 或 Qt,它们能让你更专注于业务逻辑,而不是底层的窗口管理。
- 如果你只是想在控制台程序里做个简单的选择,用控制台模拟的方法就足够了。
