已阅读5页,还剩1页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
一个好用的DBGRID-VC数据库开发之二陈松乐一、引言在用vc开发关于数据库的项目时,通常我们只好用微软的DBGRID作为数据库表格控件,其实微软的DBGRID并不好用,想找一份好的帮助文档都找不到,并且界面并不友好,比起C+Builder中的DBGRID来说是逊色不少,但是DBGRID在开发数据库的项目中又是常用的控件,所以就一直想找一个好用的DBGRID,可是网上又没有找到。上次在无意中看到了CGridCtrl(一个很漂亮的表格控件,如果你还没有用过,可以到/miscctrl/gridctrl.asp/下载,上面还有详细的使用说明)支持虚模式,在这种模式下,即使你向这个表格插入一百万条数据,它并不会真的生成一百万行,而是随着你的滚动条的滚动,计算出在屏幕上要显示的行和列,然后会向你提供一个接口,通过这个接口,你可以在这儿设置你要显示的数据。这给了我一些启示,我决定用它来做一个DBGRID。下面的例子是它的一个应用。点击这里下载demo2(/注:请编者在这里联接上例子demo2)二、原理DBGRID和一般的GRID的不同之处在于,一般的GRID并不适合显示大的数据量,如果你的一个查询结果有上万条记录的话,如果你都要插入到GRID中,这将是一个很慢的过程,并且你在GRID中移动滚动条的话,它的记录的滚动也是很慢的,而DBGRID并不会真正把这些记录的数据全部插入到控件中,当DBGRID的滚动条滚动时,它会根据DBGRID的显示面积的大小和查询得到的总的记录数计算出当前应该显示哪那些行,然后会把那几行的记录数据插入到表格中,这样速度当然是很快的,而且没有数据量多少的限制。幸运的是,CGridCtrl类已经为我们提供了这种机制,它是采用虚模式的方式,要使用这种方式,按照以下的步骤就可以了:步骤一初始化void SetVirtualMode(TRUE)设为虚模式BOOL SetRowCount(int nRows) 设置总的行数。BOOL SetFixedRowCount(int nFixedRows = 1)设置固定的行数据BOOL SetColumnCount(int nCols)设置列数BOOL SetFixedColumnCount(int nFixedCols = 1)设置固定的列数步骤二响应消息显示数据我们假设CGridCtrl是放在对话框上,而且它关联的变量是m_Grid,利用ClassWizard添加对话框的OnNotify响应函数。这个响应函数的写法是固定的,类似下面的代码:BOOL CMyOdbcDlg:OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) / TODO: Add your specialized code here and/or call the base classif (wParam = (WPARAM)m_Grid.GetDlgCtrlID() *pResult = 1; GV_DISPINFO *pDispInfo = (GV_DISPINFO*)lParam; if (GVN_GETDISPINFO = pDispInfo-hdr.code)SetGridItem(pDispInfo);/*这是我们自己加的函数,在这个函数里我们设置当前要显示的数据*/return TRUE; return CDialog:OnNotify(wParam, lParam, pResult);在上面的代码中,SetGridItem(pDispInfo)是我们自己加的函数,在这个函数里我们设置当前要显示的数据,pDispInfo是一个GV_DISPINFO的结构体对象,在这个结构中包含了每个单元格的信息,如行号,列号,有没有位图,背景色,前景色等,CGRIDCTRL会在当前要显示那个单元格时,会把这个单元格的行号,列号传递给我们,我们只要在里面设置要显示的数据就可以了。如下面是一个显示数据的例子。int CMyOdbcDlg:SetGridItem(GV_DISPINFO *pDispInfo)pDispInfo-item.strText.Format(“row%d,col%d”,pDispInfo-item.row, pDispInfo-item.col); return 0;通过上面的介绍,我们应该已经会使用CGridCtrl虚模式,下面说明一下用CGridCtrl虚模式做DBGRID的原理,大家都知道,MFC的CRecordset类支持多种游标机制,如双向游标的,如果我们是用ClassWizard来生成一个查询的CRecordset的派生类的话,那么可以调用函数CRecordset:SetAbsolutePosition(),用这种方式方式来做DBGRID真是太简单了,因为在上面的int CMyOdbcDlg:SetGridItem(GV_DISPINFO *pDispInfo)函数中,我们已经知道要显示的是哪一行,哪一列的数据,所以只要通过CRecordset:SetAbsolutePosition(pDispInfo-item.row)函数,把游标定位到那一行,然后获取每个字段的数据就可以了。但是使用上面的方法有一个不好的地方在于,我们必须用ClassWizard为每个查询从CRecordset派生出新类,这样做很不方便,在VC知识库第六期上面有一篇介绍“单独使用CRecordset”文章,可是上面的CRecordset打开方式只能使用CRecordset:forwardOnly,游标只能向前滚动,我们不能使用CRecordset:SetAbsolutePosition()函数,如果要想使用方便的话,我们必须想别的办法,来提供当前要显示的那个单元格的数据。我们知道,oracle数据库并不支持双向游标,那么为什么我们用ClassWizard为查询从CRecordset派生的类能够使游标双向移动呢?我的猜想是这样的,CRecordset类其实把每次获取的数据都保存了下来,并且保存了每行记录所在的位置,这样,当我们调用CRecordset:SetAbsolutePosition()函数时,它就可以得到我们想要的数据了。不管这种猜想对不对,按照上面的思路已经实现一个很好用的DBGRID。我把封装成了类COdbcDBGRIDFILE,它实现的原理是首先得到所查询的行数,列数,然后设置CGridCtrl的属性,如把它设为虚模式,设定CGridCtrl的行数和列数等。然后使用内存映射文件来保存每条记录数据,同时用一个结构体来记录下这条记录所在的位置。这里有一个小技巧,如果查询的结果有几十万条的话,如果我们一开始就把所有的这些记录都保存在内存映射文件中的话,那么时间要很长,所以根本不能满足应用,所以我们在开始时,只会获取记录集的一部分用于显示,当用户在CGRIDCTRL上拖动滚动条向下滚动时,它会随着用户的滚动不断的获取数据,这样显示上面就一点问题也没有。三、使用实例好了,给大家说了这么多,下面就看看如何使用这个封装好的类COdbcDBGRIDFILE这个类对外的接口只有4个函数可以被调用,下面简单的说明一下这4个函数COdbcDBGridFILE(CGridCtrl *pGrid = NULL, CDatabase *pDatabase = NULL, CString strSql = , CString strFilePath = )/构造函数,必须把所要的变量传递进去。int InitGrid();/初始化函数int SetGridText(GV_DISPINFO *pDispInfo);/被外部函数调用接口,用来返回每个单元格应该显示的int Release();/释放资源按照下面的步骤做一遍,你就能够知道它是不是很实用了。步骤一新建一个基于对话框的工程,命名为demo2,打开stdafx.h文件,加入#include,从例子中把OdbcDBGRIDFILE.h, OdbcDBGRIDFILE.cpp复制到这个工程的目录下,并且加入到工程中,方法是菜单project-add to project-files,选择这二个文件就可以了。不要忘了,你要把CGRIDCTRL类的文件都包含进来。步骤二在对话框上,按照上面的样例放上一个CURSTOMER CTROL(就是一个人头的那个控件),在属性的CLASS上输入MFCGridCtrl,ID为IDC_GRIDODBC,然后在放上其它编辑框和按钮控件,为四个编辑框控件通过CLASSWIZARD关联变量CStringm_strPass;/口令CStringm_strSource;/数据源名CStringm_strSql;/查询sqlCStringm_strUser;/用户名在类CDemo2Dlg中加入下面的几个成员变量CGridCtrl m_Grid;COdbcDBGRIDFILE *m_pMapFile;CImageList m_ImageList;CDatabase m_db;当然你要在CDemo2Dlg的声明文件中加入#include gridctrl.h#include OdbcDBGRIDFILE.h在CDemo2Dlg:DoDataExchange(CDataExchange* pDX)函数中加入DDX_Control(pDX, IDC_GRIDODBC, m_Grid);在CDemo2Dlg的构造函数中加入m_pMapFile = NULL;步骤三、用ClassWizard生成CDemo2Dlg的CDemo2Dlg:OnNotify消息响应函数,在这个函数中,输入如下的代码BOOL CDemo2Dlg:OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) / TODO: Add your specialized code here and/or call the base class if (wParam = (WPARAM)m_Grid.GetDlgCtrlID() *pResult = 1; GV_DISPINFO *pDispInfo = (GV_DISPINFO*)lParam; if (GVN_GETDISPINFO = pDispInfo-hdr.code) SetGridItem(pDispInfo);return TRUE; return CDialog:OnNotify(wParam, lParam, pResult);在上面的代码中,SetGridItem(pDispInfo)是我们自己加的函数,在这个函数里我们设置当前要显示的数据步骤四为CDemo2Dlg加入查询按钮的响应函数OnBtnquery()下面是这个函数的代码void CDemo2Dlg:OnBtnquery() this-Release();/*这个函数用于释放资源的*/CString strConn;UpdateData(TRUE);strConn.Format(ODBC;DSN=%s;UID=%s;PWD=%s,m_strSource,m_strUser, m_strPass); BOOL bResult = m_db.Open(strConn);if(bResult = FALSE) return;/*上面的代码用于连接数据库*/m_pMapFile = new COdbcDBGRIDFILE(&m_Grid, &m_db, m_strSql, c:csl.txt);m_pMapFile-InitGrid();/*初始化函数,用于创建内存映射文件等*/在上面的代码中,调用了COdbcDBGRIDFILE的构造函数,它的原型是COdbcDBGRIDFILE:COdbcDBGRIDFILE(CGridCtrl *pGrid , CDatabase *pDatabase, CString strSql, CString strFilePath),其中的参数的含义如下CGridCtrl *pGrid-是一个指向CGridCtrl的指针CDatabase *pDatabase-是一个指向Cdatabase的指针,你必须把一个已经连接好的Cdatabase的对象传递进去。CString strSql-是一个查询语句,如select * from emp;CString strFilePath-是一个用于生成内存映射文件的文件的路径步骤五为CDemo2Dlg加入成员函数SetGridItem(pDispInfo),这个函数是CDemo2Dlg:OnNotify()中调用的,我们用它来设置显示记录数据。void CDemo2Dlg:SetGridItem(GV_DISPINFO *pDispInfo)/*在这儿你可自己进行设置,如第一行为查询的字段中文名,第一行为行的序号等,如果你不进行设置,那么默认会取每个查询得到的字段名,每一行的序号*/m_pMapFile-SetGridText(pDispInfo);/*上面的函数只是用来得到了本来,你还可以用它来进行另外一些属性,如当超过一定的值是显示DBGRID的不同的前景色和前景色等*/步骤六添加成员
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年杭州客车驾驶员从业资格证考试题库答案
- 2024年哈尔滨客运资格证应用能力考试内容是什么
- 2021年广东省公务员录用考试《行测》题(乡镇卷)【原卷版】
- 人教版八年级物理下册分层训练:简单机械(B卷解析版)
- 吉首大学《公共工程项目管理》2021-2022学年第一学期期末试卷
- 吉首大学《三维图像设计与制作》2021-2022学年第一学期期末试卷
- 吉林艺术学院《素描人体》2021-2022学年第一学期期末试卷
- 邯郸房产分割协议书范文
- 2024年公寓足疗转让协议书模板
- 吉林师范大学《遥感软件应用》2021-2022学年第一学期期末试卷
- 【课件】 2024消防月主题培训:全民消防 生命至上
- 在企业高管研修班结业典礼上的讲话
- 最短路径问题(将军饮马问题)
- 水稻常见病虫害ppt
- 学生会考核表(共3页)
- 脓毒症中西医结合诊治专家共识
- 六年级家长会家长代表演讲稿-PPT
- 公寓精装修施工方案
- 农村公路养护规范
- 新冠咽拭子的采集、送检及保存注意事项
- 捷达手动变速器的拆装
评论
0/150
提交评论