开发学院软件开发VC 一个好用的DBGRID 阅读

一个好用的DBGRID

 2010-06-04 20:37:47 来源:WEB开发网 闂傚倸鍊搁崐椋庢濮橆兗缂氱憸宥堢亱闂佸湱铏庨崰鏍不椤栫偞鐓ラ柣鏇炲€圭€氾拷闂傚倸鍊搁崐椋庣矆娓氣偓楠炲鏁撻悩鎻掔€梺姹囧灩閻忔艾鐣烽弻銉︾厵闁规鍠栭。濂告煕鎼达紕校闁靛洤瀚伴獮鎺楀箣濠靛啫浜鹃柣銏⑶圭壕濠氭煙閻愵剚鐏辨俊鎻掔墛缁绘盯宕卞Δ鍐冣剝绻涘畝濠佺敖缂佽鲸鎹囧畷鎺戭潩閹典焦鐎搁梻浣烘嚀閸ゆ牠骞忛敓锟�婵犵數濮烽弫鍛婃叏椤撱垹绠柛鎰靛枛瀹告繃銇勯幘瀵哥畼闁硅娲熷缁樼瑹閳ь剙岣胯鐓ら柕鍫濇偪濞差亜惟闁宠桨鑳堕崝锕€顪冮妶鍡楃瑐闁煎啿鐖奸崺濠囧即閵忥紕鍘梺鎼炲劗閺呮稒绂掕缁辨帗娼忛埡浣锋闂佽桨鐒﹂幑鍥极閹剧粯鏅搁柨鐕傛嫹闂傚倸鍊搁崐椋庢濮橆兗缂氱憸宥堢亱闂佸湱铏庨崰鏍不椤栫偞鐓ラ柣鏇炲€圭€氾拷  闂傚倸鍊搁崐鐑芥嚄閼哥數浠氱紓鍌欒兌缁垶銆冮崨鏉戠厺鐎广儱顦崡鎶芥煏韫囨洖校闁诲寒鍓熷铏圭磼濡搫顫岄梺鍦拡閸嬪棝鎯€椤忓浂妯勯梺鍝勬湰濞叉ḿ鎹㈠┑濠勭杸闁哄洨濮烽悰銉╂⒒娴e搫甯跺鐟帮攻缁傚秴饪伴崼姘e亾閺冨牆绀冩い蹇庣娴滈箖鏌ㄥ┑鍡涱€楀褜鍠栭湁闁绘ɑ鐟ョ€氼喚绮绘ィ鍐╃厱妞ゆ劑鍊曢弸搴ㄦ煟韫囧鍔滈柕鍥у瀵潙螣閸濆嫬袝婵$偑鍊戦崹娲偡閳哄懎绠栭柍鈺佸暞閸庣喖鏌曢崶褍绨婚柟鍑ゆ嫹
核心提示:步骤二响应消息显示数据我们假设CGridCtrl是放在对话框上,而且它关联的变量是m_Grid,利用ClassWizard添加对话框的OnNotify响应函数,一个好用的DBGRID(2),这个响应函数的写法是固定的,类似下面的代码:BOOL CMyOdbcDlg::OnNotify(WPARAM wParam, LP

步骤二 响应消息 显示数据

我们假设CGridCtrl是放在对话框上,而且它关联的变量是m_Grid,利用ClassWizard添加对话框的OnNotify响应函数。这个响应函数的写法是固定的,类似下面的代码:

BOOL CMyOdbcDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
  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)是我们自己加的函数,在这个函数里我们设置当前要显示的数据,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();//释放资源

上一页  1 2 3 4  下一页

Tags:一个 好用 DBGRID

编辑录入:爽爽 [复制链接] [打 印]
[]
  • 好
  • 好的评价 如果觉得好,就请您
      0%(0)
  • 差
  • 差的评价 如果觉得差,就请您
      0%(0)
赞助商链接