简单工程项目管理系统

来源:互联网 发布:centos安装 编辑:程序博客网 时间:2024/04/29 23:12
 我是背后那一束模糊的影子,只为衬托前面那个美丽……图片

        实现这个“简单”的管理系统其实不是那么简单!
        其中总结我所遇到的几个大问题:
                其一:对于一个界面型的管理系统,用我所熟悉的MFC实现,也不断的碰见控件操作和数据交换问题;
                其二:数据库操作,对于MFC的CRecordset类来说,还是需要研究一下才能加入这个系统的使用中来的;
                其三:生成项目报表,这就需要利用MFC来操作word,用MFC提供的库文件来形成word文档的报表;
        下面就来一 一介绍我克服这几个问题的过程吧!

        第一个,控件操作与数据交换!
        首先给大家看一下该系统所涉及的几个界面:
图片
            登陆界面
 
            经营部管理主界面
 
            综合部、生产部、总工办管理主界面类似
 
            用户信息更改界面
 
            项目信息查询界面
 
            用户信息注册界面

        该系统流程大致是:经营部接到项目,填写项目信息和项目安排,交由下一级总工办;总工办登陆显示该项目信息,填写项目安排后交由下一级生产部;生产部登陆显示该项目信息,填写项目安排后交由下一级综合部;综合部登陆显示该项目信息,填写项目安排后提交下一级返回经营部,此项目完成整个流程。经营部再次登陆,可填写新项目信息和安排。每个部门都可以查看之前所有项目的信息。

        之前说的关于控件的操作问题主要就是由于经营部、综合部、生产部、总工办的管理界面相似度很大,我不想做四个Dialog,所以就想着这四个部门共用一个对话框。还有就是不同的用户登陆,所属部门不同,对这个界面的操作权限就不同,如上图所示,还有经营部可以编辑项目信息和安排,而其他3个部门的用户就只能编辑安排那一部分,而已经发送下一级的项目,都变为不可编辑状态。我在资源里加入一个综合部样式的对话框,想到控件有可以隐藏和禁用的操作,所以这个控件的问题应该不算太难……

        但是这个所谓的不太难,难度还不太小。
        我用管理界面的对话框类ManagementMain 生成对话框: ManagementMain dlg;        dlg.DoModal(); 
        这样的结果就是,我设计的对话框是怎样,它出来就是怎样……那要在哪里判断用户后做不同的显示呢? 那我就给ManagementMain 添加一个成员变量,int m_flg;    然后再在构造函数里给它初始化m_flg=0;    如果是经营部登陆,那么ManagementMain dlg;    dlg.m_flg=1;//隐藏部分控件    dlg.DoModal();     然后在构造函数里判断做不同的显示:
 if(m_flg==1)//为经营部登陆,则隐藏归档要求那两个控件,否则禁用项目信息的控件
 {
  m_CtrFileRequire.ShowWindow(false);
  m_CtrFilingRequire.ShowWindow(false);
 }
 else
 {
  GetDlgItem(IDC_ProjectNum)->EnableWindow(FALSE);
  GetDlgItem(IDC_ProjectName)->EnableWindow(FALSE);
  GetDlgItem(IDC_ProjectAddr)->EnableWindow(FALSE);
  GetDlgItem(IDC_ClientAddr)->EnableWindow(FALSE);
  GetDlgItem(IDC_ClientPerson)->EnableWindow(FALSE);
  GetDlgItem(IDC_ClientPhone)->EnableWindow(FALSE);
  GetDlgItem(IDC_ClientRequire)->EnableWindow(FALSE);
 }
这里保存后编译链接没问题,运行执行文件登陆过后,就出现下图的运行错误: 
图片
        多次百度查找错误的原因,也没有弄明白个究竟,只知道不能在构造函数里对对话框控件进行操作,要初始化对话框的布局,需要在virtual void DoDataExchange(CDataExchange* pDX);这个函数里进行改变。而且放在构造函数里的判断m_flg始终未0,这是由于构造函数先于 dlg.m_flg=1;//隐藏部分控件 这一句执行,构造里初始化为0,所以构造里判断过后m_flg才会被赋值为1。
        那么将上面改变控件的代码Ctrl+X,Ctrl+V到 DoDataExchange()函数中,编译链接后运行登陆果然可以实现同一个对话框布局的不同显示了!
 
        控件操作的问题解决了,还有一个就是数据交换了。
        比如在经营部登陆后,对话框一出来,就显示该用户信息,项目信息的编号处显示一个新生成的项目编号;综合部、生产部、总工办登陆后,对话框上就显示用户信息,显示上一级发过来的项目信息。 
        这个问题应该可以不用再对话框上再加一个按钮,点击按钮过后才更新各对话框的信息,应该有另外的方法……我百度查了一下对话框的初始化相关的消息,也翻看以前一些写了界面的程序,偶然发现平时忽略的生成对话框的步骤  ManagementMain dlg; dlg.DoModal(); 太简单了,百度有在这两句话之间对类成员变量赋值的例子,效果就是DoModal()对话框可以初始显示控件内容。于是乎,经营部DoModal()之前加上   dlg.m_projectnum=buf;为项目编号的显示内容,用户信息的成员变量依次赋值;另外3个部门DoModal()之前为用户信息、项目信息的成员变量赋值。

        至此,第一个大问题控件操作和数据交换得以解决!

        第二个大问题,MFC的CRecordset类对数据库的操作问题。
        
        之前照着课本写了一个简单的QQ聊天系统,其中有涉及到数据库的操作,记得是重写了一个数据库类,代码还不少,当然是针对那个系统专写的数据库操作。我也没时间再去看那里的代码,找出可用于这个管理系统的数据库操作,再自己重写了,所以我就百度搜索可以直接操作数据库的类的使用。 找到MFC的CDataBase类和CRecordset类结合使用可以直接对数据库进行读写操作。
        在对数据库进行读写操作之前,需要先动态注册数据源,即告诉应用程序所需要的数据库文件和对应的数据库驱动: 
SQLConfigDataSource(NULL,  ODBC_ADD_DSN,
  "Microsoft Access Driver (*.mdb)",//Access数据库的驱动驱动程序,其他数据库可在电脑的数据源(ODBC)里查看哪些可用
  "DSN=projectinfo\0" "DBQ=dbf\\projectinfo.mdb\0" "DEFAULTDIR=dbf\0"); //注册本地数据库数据源,projectinfo为数据库文件名称
 CoInitialize(NULL);
其中 SQLConfigDataSource()为注册数据源,具体参数可百度了解,CoInitialize(NULL)为初始化com库。这两句可以放在需要使用数据库的类的构造函数里。先编译链接运行一下,使其在用户DSN注册一个数据库文件。
        数据源注册完过后,需要自定义一个数据库记录集的类,使该类与需要读写的数据库关联。在类向导里添加一个新类,类名定义为MyProjectSet,选择基类时选择CRecordset,点击OK后弹出对话框选择数据源,完成后就会建成一个与数据库文件相关联的类MyProjectSet:
 long m_ID;
 CString m_projectnum;
 CString m_projectname;
 CString m_projectaddr;
 CString m_clientaddr;
 CString m_clientperson;
 CString m_clientphone;
 CString m_clientrequire;
……………

 RFX_Long(pFX, _T("[ID]"), m_ID);
 RFX_Text(pFX, _T("[projectnum]"), m_projectnum);
 RFX_Text(pFX, _T("[projectname]"), m_projectname);
 RFX_Text(pFX, _T("[projectaddr]"), m_projectaddr);
 RFX_Text(pFX, _T("[clientaddr]"), m_clientaddr);
 RFX_Text(pFX, _T("[clientperson]"), m_clientperson);
 RFX_Text(pFX, _T("[clientphone]"), m_clientphone);
 RFX_Text(pFX, _T("[clientrequire]"), m_clientrequire);
………… 

        接下来,我们就可以通过MyProjectSet类来对数据库进行读写操作了。我在这个管理系统中,就只用到数据库的查询、修改、添加3个操作。 
        数据库的查询操作如下: 
 CDatabase m_db;
 MyProjectSet myset(&m_db);
 CString strSQL1="select * from projectinfo where projectnum=  '00001'  ";
 if(!myset.Open(CRecordset::dynaset,strSQL1))
  return;
如果没有打开失败返回,则myset里存放的就是数据文件中projectnum为00001的所有记录。可以做如下判断:
if(myset.GetRecordCount()!=0)
{//有projectnum为00001的记录,定义操作
…………}
        数据库的修改操作如下: 
  //更新项目信息
  myset.Edit();
  myset.m_projectname=m_projectname;//需要修改的数据项
…………
  myset.Update();
  myset.Requery();
  myset.Close();
        数据库添加操作如下: 
  //项目信息加入数据库信息表
  myset.AddNew();
  myset.SetFieldNull(NULL);
  myset.m_projectnum=m_projectnum;//需要添加的数据项
…………
  myset.Update();
  myset.Requery();
  myset.Close();

        至此,第二个大问题数据库的操作也可以得到解决。

        最后一个大问题就是MFC操作word生成报表。
        在这之前,我所接触的MFC操作文档就只限于读写txt文件,而要读写word并生成表格样式的doc文档,就不是那么简单了。百度MFC读写word,发现网上也没有说得非常明白的应用文档,最终让我找到一篇比较好的应用说明文档http://wenku.baidu.com/view/e62b610c52d380eb62946d5a.html,其中说到在word中创建一个表格,然后为单元格赋值,还有合并单元格等操作的使用。当然,这篇文档里没有说得那么完整,需要先使用MFC提供的wor库文件添加几个操作类。具体方法为:

按下快捷键Ctrl+W,弹出MFC ClassWizard对话框,单击Add Class,选择From a type library,弹出Import from Type Library对话框,找到你OFFICE软件的安装文件夹(默认是在C盘的Program Files中),在其中找到MSWORD.OLB,单击打开。在Confirm Classes中按下Ctrl键选中_Application,Documents,_Document,Cell,Cells,Paragraph,Paragraphs,Shading,Table,Tables,InlineShapesSelection,单击OK。之后会发现类视图下多了之前添加的那几个文档操作类,在需要生成word表格的Cpp文件头部添加几个头文件:
#include "MyProjectSet.h"
#include "msword.h"
#include <atlbase.h>
然后就可以创建生成word的表格了: 
 COleVariant bTRUE((short)TRUE);
 COleVariant bFALSE((short)FALSE);
 COleVariant OPTION((long)DISP_E_PARAMNOTFOUND,VT_ERROR);
 _Application WordApp;
 if(!WordApp.CreateDispatch("Word.Application",NULL))
 {
  AfxMessageBox("CreateDispatch falied.",MB_OK|MB_SETFOREGROUND);
  return;
 }
 Documents Docs;
 _Document Doc;
 Docs=WordApp.GetDocuments();
 Doc=Docs.Add(OPTION,OPTION,OPTION,OPTION);
 Selection Select;
 Select=WordApp.GetSelection();
 _Document ActiveDoc;
 ActiveDoc=WordApp.GetActiveDocument();
 Tables tables=ActiveDoc.GetTables();
 CComVariant defaultBehavior(1);
 CComVariant AutoFitBehavior(1);
 tables.Add(Select.GetRange(),16,6,&defaultBehavior,&AutoFitBehavior);//添加一个7行11列的空表格
 Table table=tables.Item(1);
 Cell c,c1;
 Cells cs;
//以上就是创建一个表格,并定义单元格对象
c=table.Cell(1,1);
 c1=table.Cell(1,6);
 c.Merge(c1);//合并(1,1)到(1,6)的单元格
 c.Select();
 cs=Select.GetCells();
 cs.SetVerticalAlignment(1);
 Select.TypeText("项目信息");
//这是将第一行前6个单元格合并,并设置该合并后的单元格显示字符"项目信息"
   c=table.Cell(i,j);
   c.Select();
   cs=Select.GetCells();
   cs.SetVerticalAlignment(1);
   Select.TypeText("字符"); 
//这里是选定第i行第j列的单元格,并设置字符"字符"

 Select.ReleaseDispatch();
 c.ReleaseDispatch();//释放文档操作类的对象
 ActiveDoc.SaveAs(COleVariant(filename),COleVariant((short)0),
bFALSE,COleVariant(""),bTRUE,COleVariant(""),
  bFALSE,bFALSE,bFALSE,bFALSE,bFALSE,bFALSE,bFALSE,bFALSE,bFALSE,bFALSE);
//保存该word文档
 WordApp.Quit(OPTION,OPTION,OPTION);
 

         以上就是对于最后一个大问题的解决方法。

        至此,我的一个“简单”的工程项目管理系统的实践的过程说明就完成了,至于心得体会以及收获,那就只有重复研究该系统,精益求精,才能将这个“简单”的系统变为一份不简单的编程财富!

原创粉丝点击