使用C编程实现Listview控件与数据库的无缝连接操作 (c listview 添加数据库)
Listview控件是Windows中常用的一种视窗控件,它可以在Windows的用户界面中显示类似于列表的数据。而数据库是现在最常用的一种数据存储方式,它可以帮助我们储存、管理和检索数据。在许多Windows应用程序中,需要把这两种技术结合起来,将数据库中的数据通过Listview控件展示出来,从而实现更好的用户体验。在本文中,将介绍如何。
一、环境搭建
首先要搭建C编程的环境,这里我们使用Visual Studio 2023。打开Visual Studio后,选择“新建项目”,选择Visual C++ → Windows桌面,选择“Windows桌面向导”。
在窗口右边选择“Windows应用程序”,填写应用程序名称和位置。选择合适的位置,这里选择“桌面(Desktop)”,然后单击“下一步”。在下一个窗口中,我们可以选择我们希望生成的代码类型,这里选择“空项目”。
单击“完成”来生成项目。
二、关联ListView控件
接下来,我们将开始创建Listview控件。选择“解决方案资源管理器”中的项目名称,右键单击,选择“添加新项”。
在弹出的向导窗口中,选择“对话框”并输入名称,这里命名为“ListviewDialog”。
在左侧的“工具箱”面板中找到“ListView”控件,将其拖动到对话框上,然后更改ListView的ID名称,命名为“IDC_LISTVIEW1”。
在对话框上单击两次“OK”保存更改。
三、实现与数据库的连接操作
接下来,我们需要创建一个SQLite数据库,这里我们使用SQLite3 C API。SQLite是一种轻型的关系型数据库管理系统,非常适合开发小型的应用程序。
1. 引入SQLite头文件
我们需要在代码中加入头文件sqlite3.h,在stdc++头文件之前定义_MSC_VER要求Visual Studio使用C99标准。
#ifdef _MSC_VER
# define _CRT_SECURE_NO_WARNINGS
#endif
#include
#include
#include
#ifndef _MSC_VER
# define _T
#endif
#include “sqlite3.h”
2. 创建数据库并连接
我们需要在代码中创建一个数据库,并连接到该数据库。在这个过程中,我们还需要定义一个回调函数,用于告诉我们关于数据库操作的信息。
//定义数据库操作回调函数
static int callback(void *NotUsed, int argc, char **argv, char **azColName) {
for (int i = 0; i
printf(“%s = %s\n”, azColName[i], argv[i] ? argv[i] : “NULL”);
}
printf(“\n”);
return 0;
}
//创建数据库并连接
int createDatabase() {
sqlite3 *db;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open(“test.db”, &db);
if (rc) {
fprintf(stderr, “Can’t open database: %s\n”, sqlite3_errmsg(db));
return(0);
}
else {
fprintf(stderr, “Opened database successfully\n”);
}
sqlite3_close(db);
return(0);
}
3. 创建表
现在,我们应该已经创建了一个空的数据库。 接下来,我们将在该数据库中创建一张表,并将其与Listview控件进行关联。在我们的例子中,我们将创建一张名为“students”的表。
int createTable() {
sqlite3* db;
char* zErrMsg = 0;
int rc;
rc = sqlite3_open(“test.db”, &db);
if (rc) {
fprintf(stderr, “Can’t open database: %s\n”, sqlite3_errmsg(db));
return(0);
}
else {
fprintf(stderr, “Opened database successfully\n”);
}
char* sql = “CREATE TABLE students (” \
“ID INT PRIMARY KEY NOT NULL,” \
“NAME TEXT NOT NULL,” \
“AGE INT NOT NULL,” \
“ADDRESS CHAR(50),” \
“SALARY REAL );”;
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
if (rc != SQLITE_OK) {
fprintf(stderr, “SQL error: %s\n”, zErrMsg);
sqlite3_free(zErrMsg);
}
else {
fprintf(stdout, “Table created successfully\n”);
}
sqlite3_close(db);
return 0;
}
四、查询数据库
创建完表之后,我们需要从数据库中查询数据,并将其填充到Listview控件中。我们需要使用sqlite3_prepare_v2()函数准备查询语句,并使用sqlite3_step()函数执行查询。我们需要将Listview控件用到的数据加载到内存中,再使用ListView控件的消息机制将其显示,这些都需要使用Win32 API来完成。
1.加载查询结果到内存
我们将创建一个名为“loadDataToListView”的函数。这个函数将会从数据库中查询数据,然后将其存储到一个数组中。在完成数据加载之后,我们还必须将数组中的数据加载到ListView控件中。
static int loadDataToListView(HWND hWndListView) {
sqlite3 *db;
sqlite3_stmt *stmt;
int rc;
TCHAR szTemp[256];
LVCOLUMN lvColumn;
LRESULT nIndex;
TCHAR szText[256];
rc = sqlite3_open(“test.db”, &db);
if (rc) {
fprintf(stderr, “Can’t open database: %s\n”, sqlite3_errmsg(db));
sqlite3_close(db);
return FALSE;
}
else {
fprintf(stderr, “Opened database successfully\n”);
}
TCHAR* szSelectSql = _T(“SELECT * FROM students”);
BOOL bContinue = TRUE;
while (bContinue) {
nIndex = SendMessage(hWndListView, LVM_GETITEMCOUNT, 0, 0);
lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 150;
lvColumn.pszText = _T(“ID”);
SendMessage(hWndListView, LVM_INSERTCOLUMN, 0, (LPARAM)&lvColumn);
lvColumn.pszText = _T(“NAME”);
SendMessage(hWndListView, LVM_INSERTCOLUMN, 1, (LPARAM)&lvColumn);
lvColumn.pszText = _T(“AGE”);
SendMessage(hWndListView, LVM_INSERTCOLUMN, 2, (LPARAM)&lvColumn);
lvColumn.pszText = _T(“ADDRESS”);
SendMessage(hWndListView, LVM_INSERTCOLUMN, 3, (LPARAM)&lvColumn);
lvColumn.pszText = _T(“SALARY”);
SendMessage(hWndListView, LVM_INSERTCOLUMN, 4, (LPARAM)&lvColumn);
rc = sqlite3_prepare_v2(db, szSelectSql, -1, &stmt, 0);
if (rc == SQLITE_OK) {
int nColCount = sqlite3_column_count(stmt);
while (sqlite3_step(stmt) == SQLITE_ROW) {
TCHAR szText[256];
TCHAR szText2[256];
TCHAR szText3[256];
TCHAR szText4[256];
TCHAR szText5[256];
LV_ITEM lvItem = { 0 };
lvItem.mask = LVIF_TEXT;
nIndex = SendMessage(hWndListView, LVM_GETITEMCOUNT, 0, 0);
lvItem.iItem = nIndex;
sprintf(szText, “%d”, sqlite3_column_int(stmt, 0));
sprintf(szText2, “%s”, sqlite3_column_text(stmt, 1));
sprintf(szText3, “%d”, sqlite3_column_int(stmt, 2));
sprintf(szText4, “%s”, sqlite3_column_text(stmt, 3));
sprintf(szText5, “%.2f”, sqlite3_column_double(stmt, 4));
lvItem.pszText = szText;
SendMessage(hWndListView, LVM_INSERTITEM, 0, (LPARAM)&lvItem);
lvItem.pszText = szText2;
SendMessage(hWndListView, LVM_SETITEMTEXT, nIndex, (LPARAM)&lvItem);
lvItem.pszText = szText3;
SendMessage(hWndListView, LVM_SETITEMTEXT, nIndex, (LPARAM)&lvItem);
lvItem.pszText = szText4;
SendMessage(hWndListView, LVM_SETITEMTEXT, nIndex, (LPARAM)&lvItem);
lvItem.pszText = szText5;
SendMessage(hWndListView, LVM_SETITEMTEXT, nIndex, (LPARAM)&lvItem);
}
sqlite3_finalize(stmt);
}
else {
bContinue = FALSE;
}
sqlite3_close(db);
return TRUE;
}
}
我们可以通过调用loadDataToListView()函数,将查询结果加载到ListView控件中。
2. 定义窗口过程
接下来,我们需要定义一个窗口过程,该过程将负责处理Listview控件的事件。我们可以在窗口过程中处理如下事件:
– 初始化Listview控件
– 加载数据到Listview控件
– 响应Listview控件的事件,如选中事件、删除事件等
//定义窗口过程
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hWndListView;
switch (message)
{
case WM_CREATE:
{
RECT rcList;
GetClientRect(hWnd, &rcList);
hWndListView = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, _T(“List View”),
WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_EDITLABELS,
rcList.left, rcList.top, rcList.right – rcList.left, rcList.bottom – rcList.top,
hWnd, (HMENU)IDC_LISTVIEW1, GetModuleHandle(NULL), NULL);
SendMessage(hWndListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT);
loadDataToListView(hWndListView);
break;
}
case WM_NOTIFY:
{
switch (((LPNMHDR)lParam)->code)
{
case LVN_ITEMCHANGED: {
LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;
if ((lpnmitem->uNewState & LVIS_SELECTED) == LVIS_SELECTED) {
int nIndex = ListView_GetSelectionMark(hWndListView);
TCHAR szText[256];
ListView_GetItemText(hWndListView, nIndex, 1, szText, 256);
MessageBox(hWnd, szText, _T(“Title”), MB_OK);
}
}
}
break;
}
case WM_COMMAND:
int wmId, wmEvent;
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case ID_FILE_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PNT:
{
PNTSTRUCT ps;
HDC hdc = BeginPnt(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here…
EndPnt(hWnd, &ps);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
五、测试
现在,我们已经完成了数据库和Listview控件的关联,我们需要运行程序,来检查是否正确显示了数据库中的数据。
启动程序后,我们可以看到程序主窗口中显示了一个Listview控件,其中显示了我们之前创建的student表格中的数据。如果我们单击某行数据,程序会显示出该行数据的第二列,也就是学生的名字。
六、