先来看下最终程序的运行效果吧
运行程序,点击查询所有,将是数据库中的信息显示到ListContrl控件上,鼠标点击ListContrl控件的某一行,将对应的球员信息显示到右边的编辑框中,方便修改。
来看看与数据库中的信息是否一致
接下来看看具体如何实现呢?
既然是用ODBC操作数据库,首先,我们得先创建一个ODBC的数据源,如果已经创建了ODBC数据源的小伙伴,这部分就可以跳过啦。
打开电脑的控制面板->系统和安全->管理工具,会看到如下界面
因为我这里使用的ODBC驱动是32位的驱动,所以我们选择配置32位的数据源
此处的IP地址填本机地址,也可以写localhost,User和Password写你Mysql的用户名和密码,Database选择你想要操作的数据库,之后点击Test,若果弹出如图所示的连接成功提示,表示测试成功,点击Ok,我们就会看到界面多出了我刚才创建的数据源。
数据源到此创建完毕,接下我们进入第二步。
新建一个基于对话框的MFC应用程序,我这里命名为ODBC-Test,来看看创建完项目后的解决方案
对界面进行如下布局,布局可能不是很好看,当个例子,大家凑合看吧,之后打开类向导可以看到对相应的控件添加了如下变量,这里记得吧ListContrl控件的属性中的View改为Report。
界面搭建完成,下一步开始上代码实现。
在ODBC-TestDlg.h中加入以下头文件,以提供ODBC对象来对数据库进行访问。
#include "afxcmn.h"
#include
#include "afxdb.h"
#include "afxwin.h"
稍加思考,我们只等读取数据库的数据到ListContrl控件上,但是控件的第一行ID、Name、Height、Weight这4个是要我们自己初始化的,因此在初始化对话框函数 OnInitDialog() 中接入下列代码来给ListContrl控件设置风格和标题。
//设定风格样式
m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
//在Listctrl控件上添加列,与数据库table对应。
/*
第一个参数表示需要设置的列
第二个参数表示要给该列填充的值
第三个参数表示填充的值以什么风格显示,这里我们使用居中显示
第四个参数表示给该列分配的宽度
*/
m_list.InsertColumn(0, _T("ID"), LVCFMT_CENTER, 50);
m_list.InsertColumn(1, _T("Name"), LVCFMT_CENTER, 100);
m_list.InsertColumn(2, _T("Height"), LVCFMT_CENTER, 80);
m_list.InsertColumn(3, _T("Weight"), LVCFMT_CENTER, 80);
初始化工作完成后,因为考虑到后面在每次对数据库进行操作的时候,我们想让数据库中的数据同步显示到ListContrl控件中,因此我们可以把查询数据库的代码封装成一个函数,到时候在每次对数据库进行操作完毕后,直接调用查询函数就可以。
//查询函数
void CODBCTestDlg::show(CString cmdStr)
{
//清空ListContrl控件
m_list.DeleteAllItems();
/*声明一个数据库对象,因为要调用相关的方法来操作数据库,
那怎么调用呢,肯定要先有对象嘛,没有对象,还怎么玩,
是这个道理吧*/
CDatabase db;
//这里的DSN就是我们刚刚创建的数据源,UID,PWD对应的就是账户和密码
db.Open(NULL, FALSE, FALSE, L"ODBC;DSN=NBA;UID=root;PWD=root");
//声明一个记录集对象,用来对数据库进行操作
CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly, (L"%s", cmdStr));
int count = 0;
while (!rs.IsEOF())
{
/*要往ListContrl中填充数据库的数据,那就要先给控件开辟一行,
在向这一行里面的每列填充数据,注意,先开辟行*/
m_list.InsertItem(count, _T(""));
CString varID;
rs.GetFieldValue(L"id", varID);
m_list.SetItemText(count, 0, varID);
CString varName;
rs.GetFieldValue(L"name", varName);
m_list.SetItemText(count, 1, varName);
CString varHeight;
rs.GetFieldValue(L"height", varHeight);
m_list.SetItemText(count, 2, varHeight);
CString varWeight;
rs.GetFieldValue(L"weight", varWeight);
m_list.SetItemText(count, 3, varWeight);
count++;
rs.MoveNext();
}
rs.Close();
db.Close();
}
接下来,我们来查询数据库中所有球员的信息,因为我们刚刚已经把查询函数封装完毕,因此这一步会异常简单,有多简单呢,2行代码搞定
//查询素有球员信息
void CODBCTestDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
CString cmdStr = _T("select * from players");
show(cmdStr);
}
到此,就可以运行程序看一下是否可以查询出来所有信息了,我这里就不上图了,接着往下走,来写添加球员的函数。
添加球员,我们先分析一下思路,要添加球员的信息肯定是要从编辑框中获得的,之后再用一个sql语句来向数据库中插入信息
//添加
void CODBCTestDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
CDatabase db;
db.Open(NULL, FALSE, FALSE, _T("ODBC;DSN=NBA;UID=root;PWD=root"));
//获取四个编辑框的值
CString str, Id, Name, Height, Weight;
m_uiId.GetWindowTextW(Id);
m_uiName.GetWindowTextW(Name);
m_uiHeight.GetWindowTextW(Height);
m_uiWeight.GetWindowTextW(Weight);
str.Format(L"insert into players values('%s', '%s', '%s', '%s')",Id, Name, Height, Weight);
//执行Sql语句向数据库中插入数据
db.ExecuteSQL(str);
db.Close();
MessageBox(TEXT("添加成功"));
//调用查询函数,让数据库的信息同步更新到控件上
CString cmdStr = TEXT("select * from players");
show(cmdStr);
}
接下来是删除吧,说到删除这里,其实有很多思路,可以直接根据ID来删除,也可以更严谨一点,加上姓名、身高、体重等作为判断依据,我们这里做的更严谨一点,先判断鼠标是否点击到ListContrl控件中的某行,如果点击到了,直接获取这一行的信息来作为删除的依据,如果没有点击到控件内,就获取编辑框的内容来作为删除的依据。不过,其实稍加思考就知道,要是两者都没有,还可以弹个提示框提醒用户选择要删除的信息,这个,就留着有兴趣的再添加吧,毕竟难度不大,对吧。
//删除
void CODBCTestDlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
CDatabase db;
db.Open(NULL, FALSE, FALSE, _T("ODBC;DSN=NBA;UID=root;PWD=root"));
int nIndex;
CString Id, Name, Height, Weight;
//获取当前鼠标在ListContrl中的位置
nIndex = m_list.GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);
if (nIndex != -1)
{
Id = m_list.GetItemText(nIndex, 0);
Name = m_list.GetItemText(nIndex, 1);
Height = m_list.GetItemText(nIndex, 2);
Weight = m_list.GetItemText(nIndex, 3);
}
else
{
//获取编辑框的内容
m_uiId.GetWindowTextW(Id);
m_uiName.GetWindowTextW(Name);
m_uiHeight.GetWindowTextW(Height);
m_uiWeight.GetWindowTextW(Weight);
}
CString str;
str.Format(TEXT("delete from players where id='%s' and name='%s' and height='%s' and weight='%s'"),
Id, Name, Height, Weight);
db.ExecuteSQL(str);
db.Close();
MessageBox(TEXT("删除成功"));
CString strCmd = TEXT("select * from players");
show(strCmd);
}
终于来到最后一个更新功能,思路依然要清晰,更新,肯定也是当鼠标点击某个球员信息的时候,将信息同步更新到编辑框中,然后获取编辑框的值来作为更新的依据。
//修改
void CODBCTestDlg::OnBnClickedButton4()
{
// TODO: 在此添加控件通知处理程序代码
CDatabase db;
db.Open(NULL, FALSE, FALSE, _T("ODBC;DSN=NBA;UID=root;PWD=root"));
CString Id, Name, Height, Weight;
m_uiId.GetWindowTextW(Id);
m_uiName.GetWindowTextW(Name);
m_uiHeight.GetWindowTextW(Height);
m_uiWeight.GetWindowTextW(Weight);
CString updateStr;
updateStr.Format(TEXT("update players set name='%s', height='%s',weight='%s' where id='%s'"),
Name, Height, Weight, Id);
db.ExecuteSQL(updateStr);
db.Close();
MessageBox(TEXT("更新成功"));
CString strCmd = TEXT("select * from players");
show(strCmd);
}
差点忘了,还差个鼠标点击某行,把相应的信息显示到编辑框中。这里我们调用一个ListContrl控件的鼠标点击响应函数,具体方法,在对话框界面鼠标右键点击ListContrl,选择添加事件处理程序,找到对应的函数
//鼠标点击某行,将对应的信息显示到控件上
void CODBCTestDlg::OnNMClickList1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
int nIndex = 0;
if (nIndex == -1)
nIndex = 0;
//获取鼠标当前选中的行
nIndex = m_list.GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);
//将该行的信息显示到编辑框中
m_uiId.SetWindowTextW(m_list.GetItemText(nIndex, 0));
m_uiName.SetWindowTextW(m_list.GetItemText(nIndex, 1));
m_uiHeight.SetWindowTextW(m_list.GetItemText(nIndex, 2));
m_uiWeight.SetWindowTextW(m_list.GetItemText(nIndex, 3));
*pResult = 0;
}
到此,大功告成,可以运行一下程序,享受一下运行成功的那种快乐了,当然,如果你不幸出了bug,也不要惊慌,毕竟改bug才能更好的体会编程的乐趣,所以说,直接运行成功的乐趣已经少了一半了。