C++课程设计总结

来源:互联网 发布:工作提醒软件 编辑:程序博客网 时间:2024/05/21 07:15

最近为了课设过了一段野人般的生活…我也是初步学习MFC,所以很多东西都不甚了解,很多技巧和用法都是综合各家之言而成…有什么不确切的地方,希望大家指正……

  首先介绍一下我的程序,没有想到新颖的课题,就做了人事档案管理系统,这个系统最主要的就是连接操作数据库,我就以自己工作的顺序介绍一下。

 

一、准备工作

我建立的是单文档工程,虽然没用单文档界面(还是以对话框为主),但是个人觉得单文档连接数据库更直接,另外,我是用ADO连接SQL数据库(之前的建库以及添加数据源就不说了),建好就开始工作啦!!

二、数据库连接

1.StdAfx.h中加入:

 #import "C:\Program Files\Common Files\System\ado\msado15.dll"no_namespace rename("EOF","adoEOF")

2.添加ADO类(封装了操作数据库的多个函数及变量)

ADO.h:

classADO 

{

public:

  CString username;

  ADO();

  virtual ~ADO();

  UINT GetRecordsetCount(_RecordsetPtrpRecordset);                            //返回记录集个数

  void CloseConn();                                                                                                  //关闭连接

  void CloseRecordset();                                                                                        //关闭记录集

  _RecordsetPtr& OpenRecordset(CString sql);                                              //打开记录集

  void OnInitADOConn();                                                                                        //初始化COM环境

  _RecordsetPtr m_pRecordset;                                                                                   //智能指针

  _ConnectionPtr m_pConnection;   

 

};

 

ADO.cpp:

ADO::ADO()

{

 

}

 

ADO::~ADO()

{

 

}

////////////////////////////////////////////////////////////////////////////

//名称:OnInitADOConn

//功能:初始化COM环境(AQL专用,如果用ACCESS的话需要修改)

/////////////////////////////////////////////////////////////////////////////

voidADO::OnInitADOConn()

{

  ::CoInitialize(NULL);

  try

  {

            m_pConnection.CreateInstance("ADODB.Connection");

            _bstr_tstrConnect="Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist SecurityInfo=False;Initial Catalog=MFC Design1;Data Source=.";

            m_pConnection->Open(strConnect,"","",adModeUnknown);

 

  }

  catch(_com_error e)

  {

            AfxMessageBox(e.Description());

  }

}

 

////////////////////////////////////////////////////////////////////////////

//名称:OpenRecordset

//功能:打开记录集

/////////////////////////////////////////////////////////////////////////////

_RecordsetPtr&ADO::OpenRecordset(CString sql)

{

  ASSERT(!sql.IsEmpty());

  try

  {

            m_pRecordset.CreateInstance(__uuidof(Recordset));

  m_pRecordset->Open(_bstr_t(sql),m_pConnection.GetInterfacePtr(),adOpenStatic,adLockOptimistic,adCmdText);

  }

  catch(_com_error e)

  {

            AfxMessageBox(e.Description());

  }

  return m_pRecordset;

}

 

////////////////////////////////////////////////////////////////////////////

//名称:CloseRecordset

//功能:关闭记录集

/////////////////////////////////////////////////////////////////////////////

voidADO::CloseRecordset()

{

  if(m_pRecordset->GetState() == adStateOpen)

  {

            m_pRecordset->Close();

  }

}

 

////////////////////////////////////////////////////////////////////////////

//名称:CloseConn

//功能:断开数据库连接

/////////////////////////////////////////////////////////////////////////////

voidADO::CloseConn()

{

  m_pConnection->Close();

  ::CoUninitialize();

}

 

////////////////////////////////////////////////////////////////////////////

//名称:GetRecordsetCount

//功能:取得记录集数目

/////////////////////////////////////////////////////////////////////////////

UINTADO::GetRecordsetCount(_RecordsetPtr pRecordset)

{

  int nCount = 0;

  try

  {

            pRecordset->MoveFirst();

  }

  catch(...)

  {

            return 0;

  }

  if(pRecordset->adoEOF)

  {

            return 0;

  }

  while(!pRecordset->adoEOF)

  {

            pRecordset->MoveNext();

            nCount = nCount + 1;

  }

  pRecordset->MoveFirst();

  return nCount;

}

3.声明一个ADO的全局对象

这一步是非必要的,之前我是把ADO的对象添加到每个类里,后来发现那样的话用一次就得重新连接一次数据库,这样程序运行的速度就大打折扣了,所以想到添加全局对象,整个程序运行过程中只连接一次数据库,这样程序的运行速度会得到很好的优化。

3.1 StdAfx.cpp中生命ADO 对象(我用的m_ado)

3.2 StdAfx.h中加入ADO的头文件ADO.h,这样以后就不用加ADO 的头文件了

3.3 在用到m_adocpp文件中导出这个全局对象extern ADO m_ado;

这样就OK了,在CMainFrame的OnCreate()函数中写入m_ado.OnInitADOConn();进行初始化,完成数据库的连接。

三、操作数据库

其实这些操作在具体功能中体现最为形象,所以我下面以设计的几个功能按钮的实现介绍数据库操作。

1、  用户登录

UpdateData();                                               //从控件上获得数据

if(m_login_name.IsEmpty()||m_login_psd.IsEmpty())   /*m_login_namem_login_psd是我设置的两个编辑框关联的变量,分别指代用户名和密码,这句话的意思就是判断两框中的数据是否为空*/

{/*如果为空,就显示提示,然后清楚编辑框控件上的信息,最后返回主登录界面*/

           AfxMessageBox(TEXT("用户名、密码不能为空!"));

           m_login_name="";

           m_login_psd="";

           UpdateData(FALSE);  //更新控件数据

           return;

}

/*如果不为空,则开始搜索数据库,检查输入内容是否准确*/

CString sql = "select * from admin whereusername = '" +m_login_name+ "' and password ='" +m_login_psd+"' ";/*这是数据库搜索语句,usernamepassword是数据库中分别存放用户名和密码的字段名,意思就是搜索这两个字段中满足输入条件的记录*/

m_ado.m_pRecordset = m_ado.OpenRecordset(sql);   /*打开记录集,即打开符合要求的记录集合*/

int nCount = m_ado.m_pRecordset->RecordCount; //利用成员RecordCount取得记录数,即符合要求的记录数量

if(nCount > 0)            //nCount大于0意味着用户存在,登陆成功

{       

           ::Sleep(300);                                                                                                           //300毫秒后登陆窗口关闭

           OnOK();

 

}

else           //用户不存在

{

           AfxMessageBox(TEXT("用户名、密码错误!"));

           m_login_name="";

           m_login_psd="";

           UpdateData(FALSE);

}

2.用户注册

UpdateData(TRUE);//获取控件上的数据

if(m_log2_name.IsEmpty()||m_log2_psd1.IsEmpty()||m_log2_psd2.IsEmpty())

{

           AfxMessageBox(TEXT("用户名、密码不能为空!!"));

           return ;

}

 

CString sql1 = "select * from admin whereusername = '" +m_log2_name+ "'";

m_ado.m_pRecordset = m_ado.OpenRecordset(sql1); /*检查你输入的用户名是否已经存在了*/

int nCount = m_ado.m_pRecordset->RecordCount;   //利用成员RecordCount取得记录数

    if(nCount > 0)                                                                                                                    //nCount大于0意味着用户已存在

{

           AfxMessageBox(TEXT("抱歉,该用户已存在,请重新填写!!::>_<::"));

}

else                                                                                               //用户不存在

{

           if(m_log2_psd1!=m_log2_psd2)/* m_log2_psd1是密码对应的变量,m_log2_psd2是密码确认对应的变量,即判断两次密码是否输入一致

                    AfxMessageBox(TEXT("抱歉,验证密码输入有误,请重新填写!!::>_<::"));

           else

           {/*密码用户名输入成功则开始录入*/

        UpdateData(true); /*通过操纵智能指针实现多种操作*/

           ::CoInitialize(NULL);

           m_ado.m_pRecordset->AddNew();//添加一条新纪录

           m_ado.m_pRecordset->PutCollect("username",_variant_t(m_log2_name));/*使用这个录入函数,要注意数据的数据类型,具体参见CSDN*/

           m_ado.m_pRecordset->PutCollect("password",_variant_t(m_log2_psd1));

           m_ado.m_pRecordset->Update();/*更新数据库中的数据,即完成数据录入*/

           AfxMessageBox(TEXT("恭喜,新用户已成功注册!!(*^__^*)"));

          

           ::Sleep(300);                                                                                                           //300毫秒后登陆窗口关闭

               OnOK();

           }

 

}

 

3.删除记录

UpdateData();/*获取控件数据,包括你要删除的记录的序号,即行数*/

CString sql = "select * from m_dadj";//打开数据库中所有数据

m_ado.m_pRecordset = m_ado.OpenRecordset(sql);                                         //打开记录集

int nCount = m_ado.m_pRecordset->RecordCount;                      //利用成员RecordCount取得记录数

int nn = atol(m_shan_xuhao);/*m_shan_xuhao是我定义的要删除的记录的序号,我把它定义为CString,在此转为整型*/

if (!(nn>0&&nn<=nCount))/*判断输入的序号是否在正常范围内*/

{

           AfxMessageBox(TEXT("请输入正确的序号!!"));

           return ;

}

::CoInitialize(NULL);

m_ado.m_pRecordset->Move(nn-1);/*移动指针到你所输入序号指定的记录上*/

m_ado.m_pRecordset->Delete(adAffectCurrent);/*删除该记录*/

AfxMessageBox(TEXT("记录已成功删除!!"));

::Sleep(300);

OnOK();

 

 

 

4. 提取数据库中的数据到控件上显示

 我用的是MicrosofFlexGrid Control,version 6.0

/*首先打开数据库,如果你要筛选信息的话,可添加搜索条件,这个同上登陆的用法,此处不再赘述*/

CString sql = "select * from m_dadj";

m_ado.m_pRecordset = m_ado.OpenRecordset(sql);   //打开记录集

nCount = m_ado.m_pRecordset->RecordCount;                                //利用成员RecordCount取得记录数

m_xiugai_list.SetRows(nCount+1);/*设置控件中表格行数为ncount+1  */

  /*初始化表格信息

m_xiugai_list.SetRow(0);

  m_xiugai_list.SetCol(1);

  m_xiugai_list.SetText("序号");/*即设置表格第0行第1列数据为序号,其实就是写入表头信息*/

 

  m_xiugai_list.SetRow(0);

  m_xiugai_list.SetCol(2);

  m_xiugai_list.SetText("职工编码");

 

    m_xiugai_list.SetRow(0);

  m_xiugai_list.SetCol(3);

  m_xiugai_list.SetText("姓名");

 

intiRow=1;/*用来标识现在处理的记录序号,即行数*/

  while (iRow<=nCount)

  {/*m_xiugai_list为显示控件所关联的数据变量*/

            CString ll;

            ll.Format("%d",iRow);

 

      m_xiugai_list.SetRow(iRow);

            m_xiugai_list.SetCol(1);

            m_xiugai_list.SetText(ll);/*将ll的数据写入第irow行第1

 

 

            m_xiugai_list.SetRow(iRow);

            m_xiugai_list.SetCol(2);

  m_xiugai_list.SetText((_bstr_t)m_ado.m_pRecordset->GetCollect("zgbm"));/*m_ado.m_pRecordset->GetCollect("zgbm")为读取数据库中该记录中zgbm字段所对应的数据,zgbm为我个人加的字段,通用,这里也涉及到数据类型的转换,原因参见CSDNGetCollect()这个函数的描述*/

 

            m_xiugai_list.SetRow(iRow);

            m_xiugai_list.SetCol(3);

            m_xiugai_list.SetText((_bstr_t)m_ado.m_pRecordset->GetCollect("xm"));

5.列表控件的操作

读取数据库的数据到列表控件中(m_xiugai_list 为列表控件的关联变量)

         m_xiugai_list.DeleteAllItems();

CString sql = "select * from m_dadj";

m_ado.m_pRecordset = m_ado.OpenRecordset(sql);//打开记录集

nCount = m_ado.m_pRecordset->RecordCount;//利用成员RecordCount取得记录数

    

//列表初始化

m_xiugai_list.SetItemCount(nCount+1);

LONG lStyle = m_xiugai_list.SendMessage(LVM_GETEXTENDEDLISTVIEWSTYLE);

lStyle |=  LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES;

m_xiugai_list.SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, 0,(LPARAM)lStyle);

m_xiugai_list.InsertColumn(0,"职工编码",NULL,150,-1);//初始化表格控件表头

m_xiugai_list.InsertColumn(1,"姓名",NULL,110,-1);

int iRow=1,n1;

   CString s1,s2;

while (iRow<=nCount)

{n1=m_xiugai_list.GetItemCount();

    m_xiugai_list.InsertItem(n1,(_bstr_t)m_ado.m_pRecordset->GetCollect("zgbm"));

m_xiugai_list.SetItemText(n1,1,(_bstr_t)m_ado.m_pRecordset->GetCollect("xm"));

m_xiugai_list.SetItemText(n1,2,(_bstr_t)m_ado.m_pRecordset->GetCollect("xb"));

iRow++;

m_ado.m_pRecordset->MoveNext();

}

m_ado.m_pRecordset->Close();

其实课程设计就是这些操作的扩展与融合,大家想要做好还得多多学习,个人觉得不要忽视网络这个绝对强大的工具,多看一看别人写的程序,也会使我们受益匪浅的…暂时想了这么多,以后有机会再补充吧…………希望能对大家有所帮助……