




已閱讀5頁,還剩1頁未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
一個(gè)好用的DBGRID-VC數(shù)據(jù)庫開發(fā)之二陳松樂一、引言在用vc開發(fā)關(guān)于數(shù)據(jù)庫的項(xiàng)目時(shí),通常我們只好用微軟的DBGRID作為數(shù)據(jù)庫表格控件,其實(shí)微軟的DBGRID并不好用,想找一份好的幫助文檔都找不到,并且界面并不友好,比起C+Builder中的DBGRID來說是遜色不少,但是DBGRID在開發(fā)數(shù)據(jù)庫的項(xiàng)目中又是常用的控件,所以就一直想找一個(gè)好用的DBGRID,可是網(wǎng)上又沒有找到。上次在無意中看到了CGridCtrl(一個(gè)很漂亮的表格控件,如果你還沒有用過,可以到/miscctrl/gridctrl.asp/下載,上面還有詳細(xì)的使用說明)支持虛模式,在這種模式下,即使你向這個(gè)表格插入一百萬條數(shù)據(jù),它并不會(huì)真的生成一百萬行,而是隨著你的滾動(dòng)條的滾動(dòng),計(jì)算出在屏幕上要顯示的行和列,然后會(huì)向你提供一個(gè)接口,通過這個(gè)接口,你可以在這兒設(shè)置你要顯示的數(shù)據(jù)。這給了我一些啟示,我決定用它來做一個(gè)DBGRID。下面的例子是它的一個(gè)應(yīng)用。點(diǎn)擊這里下載demo2(/注:請編者在這里聯(lián)接上例子demo2)二、原理DBGRID和一般的GRID的不同之處在于,一般的GRID并不適合顯示大的數(shù)據(jù)量,如果你的一個(gè)查詢結(jié)果有上萬條記錄的話,如果你都要插入到GRID中,這將是一個(gè)很慢的過程,并且你在GRID中移動(dòng)滾動(dòng)條的話,它的記錄的滾動(dòng)也是很慢的,而DBGRID并不會(huì)真正把這些記錄的數(shù)據(jù)全部插入到控件中,當(dāng)DBGRID的滾動(dòng)條滾動(dòng)時(shí),它會(huì)根據(jù)DBGRID的顯示面積的大小和查詢得到的總的記錄數(shù)計(jì)算出當(dāng)前應(yīng)該顯示哪那些行,然后會(huì)把那幾行的記錄數(shù)據(jù)插入到表格中,這樣速度當(dāng)然是很快的,而且沒有數(shù)據(jù)量多少的限制。幸運(yùn)的是,CGridCtrl類已經(jīng)為我們提供了這種機(jī)制,它是采用虛模式的方式,要使用這種方式,按照以下的步驟就可以了:步驟一初始化void SetVirtualMode(TRUE)設(shè)為虛模式BOOL SetRowCount(int nRows) 設(shè)置總的行數(shù)。BOOL SetFixedRowCount(int nFixedRows = 1)設(shè)置固定的行數(shù)據(jù)BOOL SetColumnCount(int nCols)設(shè)置列數(shù)BOOL SetFixedColumnCount(int nFixedCols = 1)設(shè)置固定的列數(shù)步驟二響應(yīng)消息顯示數(shù)據(jù)我們假設(shè)CGridCtrl是放在對話框上,而且它關(guān)聯(lián)的變量是m_Grid,利用ClassWizard添加對話框的OnNotify響應(yīng)函數(shù)。這個(gè)響應(yīng)函數(shù)的寫法是固定的,類似下面的代碼: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);/*這是我們自己加的函數(shù),在這個(gè)函數(shù)里我們設(shè)置當(dāng)前要顯示的數(shù)據(jù)*/return TRUE; return CDialog:OnNotify(wParam, lParam, pResult);在上面的代碼中,SetGridItem(pDispInfo)是我們自己加的函數(shù),在這個(gè)函數(shù)里我們設(shè)置當(dāng)前要顯示的數(shù)據(jù),pDispInfo是一個(gè)GV_DISPINFO的結(jié)構(gòu)體對象,在這個(gè)結(jié)構(gòu)中包含了每個(gè)單元格的信息,如行號(hào),列號(hào),有沒有位圖,背景色,前景色等,CGRIDCTRL會(huì)在當(dāng)前要顯示那個(gè)單元格時(shí),會(huì)把這個(gè)單元格的行號(hào),列號(hào)傳遞給我們,我們只要在里面設(shè)置要顯示的數(shù)據(jù)就可以了。如下面是一個(gè)顯示數(shù)據(jù)的例子。int CMyOdbcDlg:SetGridItem(GV_DISPINFO *pDispInfo)pDispInfo-item.strText.Format(“row%d,col%d”,pDispInfo-item.row, pDispInfo-item.col); return 0;通過上面的介紹,我們應(yīng)該已經(jīng)會(huì)使用CGridCtrl虛模式,下面說明一下用CGridCtrl虛模式做DBGRID的原理,大家都知道,MFC的CRecordset類支持多種游標(biāo)機(jī)制,如雙向游標(biāo)的,如果我們是用ClassWizard來生成一個(gè)查詢的CRecordset的派生類的話,那么可以調(diào)用函數(shù)CRecordset:SetAbsolutePosition(),用這種方式方式來做DBGRID真是太簡單了,因?yàn)樵谏厦娴膇nt CMyOdbcDlg:SetGridItem(GV_DISPINFO *pDispInfo)函數(shù)中,我們已經(jīng)知道要顯示的是哪一行,哪一列的數(shù)據(jù),所以只要通過CRecordset:SetAbsolutePosition(pDispInfo-item.row)函數(shù),把游標(biāo)定位到那一行,然后獲取每個(gè)字段的數(shù)據(jù)就可以了。但是使用上面的方法有一個(gè)不好的地方在于,我們必須用ClassWizard為每個(gè)查詢從CRecordset派生出新類,這樣做很不方便,在VC知識(shí)庫第六期上面有一篇介紹“單獨(dú)使用CRecordset”文章,可是上面的CRecordset打開方式只能使用CRecordset:forwardOnly,游標(biāo)只能向前滾動(dòng),我們不能使用CRecordset:SetAbsolutePosition()函數(shù),如果要想使用方便的話,我們必須想別的辦法,來提供當(dāng)前要顯示的那個(gè)單元格的數(shù)據(jù)。我們知道,oracle數(shù)據(jù)庫并不支持雙向游標(biāo),那么為什么我們用ClassWizard為查詢從CRecordset派生的類能夠使游標(biāo)雙向移動(dòng)呢?我的猜想是這樣的,CRecordset類其實(shí)把每次獲取的數(shù)據(jù)都保存了下來,并且保存了每行記錄所在的位置,這樣,當(dāng)我們調(diào)用CRecordset:SetAbsolutePosition()函數(shù)時(shí),它就可以得到我們想要的數(shù)據(jù)了。不管這種猜想對不對,按照上面的思路已經(jīng)實(shí)現(xiàn)一個(gè)很好用的DBGRID。我把封裝成了類COdbcDBGRIDFILE,它實(shí)現(xiàn)的原理是首先得到所查詢的行數(shù),列數(shù),然后設(shè)置CGridCtrl的屬性,如把它設(shè)為虛模式,設(shè)定CGridCtrl的行數(shù)和列數(shù)等。然后使用內(nèi)存映射文件來保存每條記錄數(shù)據(jù),同時(shí)用一個(gè)結(jié)構(gòu)體來記錄下這條記錄所在的位置。這里有一個(gè)小技巧,如果查詢的結(jié)果有幾十萬條的話,如果我們一開始就把所有的這些記錄都保存在內(nèi)存映射文件中的話,那么時(shí)間要很長,所以根本不能滿足應(yīng)用,所以我們在開始時(shí),只會(huì)獲取記錄集的一部分用于顯示,當(dāng)用戶在CGRIDCTRL上拖動(dòng)滾動(dòng)條向下滾動(dòng)時(shí),它會(huì)隨著用戶的滾動(dòng)不斷的獲取數(shù)據(jù),這樣顯示上面就一點(diǎn)問題也沒有。三、使用實(shí)例好了,給大家說了這么多,下面就看看如何使用這個(gè)封裝好的類COdbcDBGRIDFILE這個(gè)類對外的接口只有4個(gè)函數(shù)可以被調(diào)用,下面簡單的說明一下這4個(gè)函數(shù)COdbcDBGridFILE(CGridCtrl *pGrid = NULL, CDatabase *pDatabase = NULL, CString strSql = , CString strFilePath = )/構(gòu)造函數(shù),必須把所要的變量傳遞進(jìn)去。int InitGrid();/初始化函數(shù)int SetGridText(GV_DISPINFO *pDispInfo);/被外部函數(shù)調(diào)用接口,用來返回每個(gè)單元格應(yīng)該顯示的int Release();/釋放資源按照下面的步驟做一遍,你就能夠知道它是不是很實(shí)用了。步驟一新建一個(gè)基于對話框的工程,命名為demo2,打開stdafx.h文件,加入#include,從例子中把OdbcDBGRIDFILE.h, OdbcDBGRIDFILE.cpp復(fù)制到這個(gè)工程的目錄下,并且加入到工程中,方法是菜單project-add to project-files,選擇這二個(gè)文件就可以了。不要忘了,你要把CGRIDCTRL類的文件都包含進(jìn)來。步驟二在對話框上,按照上面的樣例放上一個(gè)CURSTOMER CTROL(就是一個(gè)人頭的那個(gè)控件),在屬性的CLASS上輸入MFCGridCtrl,ID為IDC_GRIDODBC,然后在放上其它編輯框和按鈕控件,為四個(gè)編輯框控件通過CLASSWIZARD關(guān)聯(lián)變量CStringm_strPass;/口令CStringm_strSource;/數(shù)據(jù)源名CStringm_strSql;/查詢sqlCStringm_strUser;/用戶名在類CDemo2Dlg中加入下面的幾個(gè)成員變量CGridCtrl m_Grid;COdbcDBGRIDFILE *m_pMapFile;CImageList m_ImageList;CDatabase m_db;當(dāng)然你要在CDemo2Dlg的聲明文件中加入#include gridctrl.h#include OdbcDBGRIDFILE.h在CDemo2Dlg:DoDataExchange(CDataExchange* pDX)函數(shù)中加入DDX_Control(pDX, IDC_GRIDODBC, m_Grid);在CDemo2Dlg的構(gòu)造函數(shù)中加入m_pMapFile = NULL;步驟三、用ClassWizard生成CDemo2Dlg的CDemo2Dlg:OnNotify消息響應(yīng)函數(shù),在這個(gè)函數(shù)中,輸入如下的代碼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)是我們自己加的函數(shù),在這個(gè)函數(shù)里我們設(shè)置當(dāng)前要顯示的數(shù)據(jù)步驟四為CDemo2Dlg加入查詢按鈕的響應(yīng)函數(shù)OnBtnquery()下面是這個(gè)函數(shù)的代碼void CDemo2Dlg:OnBtnquery() this-Release();/*這個(gè)函數(shù)用于釋放資源的*/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;/*上面的代碼用于連接數(shù)據(jù)庫*/m_pMapFile = new COdbcDBGRIDFILE(&m_Grid, &m_db, m_strSql, c:csl.txt);m_pMapFile-InitGrid();/*初始化函數(shù),用于創(chuàng)建內(nèi)存映射文件等*/在上面的代碼中,調(diào)用了COdbcDBGRIDFILE的構(gòu)造函數(shù),它的原型是COdbcDBGRIDFILE:COdbcDBGRIDFILE(CGridCtrl *pGrid , CDatabase *pDatabase, CString strSql, CString strFilePath),其中的參數(shù)的含義如下CGridCtrl *pGrid-是一個(gè)指向CGridCtrl的指針CDatabase *pDatabase-是一個(gè)指向Cdatabase的指針,你必須把一個(gè)已經(jīng)連接好的Cdatabase的對象傳遞進(jìn)去。CString strSql-是一個(gè)查詢語句,如select * from emp;CString strFilePath-是一個(gè)用于生成內(nèi)存映射文件的文件的路徑步驟五為CDemo2Dlg加入成員函數(shù)SetGridItem(pDispInfo),這個(gè)函數(shù)是CDemo2Dlg:OnNotify()中調(diào)用的,我們用它來設(shè)置顯示記錄數(shù)據(jù)。void CDemo2Dlg:SetGridItem(GV_DISPINFO *pDispInfo)/*在這兒你可自己進(jìn)行設(shè)置,如第一行為查詢的字段中文名,第一行為行的序號(hào)等,如果你不進(jìn)行設(shè)置,那么默認(rèn)會(huì)取每個(gè)查詢得到的字段名,每一行的序號(hào)*/m_pMapFile-SetGridText(pDispInfo);/*上面的函數(shù)只是用來得到了本來,你還可以用它來進(jìn)行另外一些屬性,如當(dāng)超過一定的值是顯示DBGRID的不同的前景色和前景色等*/步驟六添加成員
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 工程造價(jià)全過程跟蹤審計(jì)咨詢合同范本
- 冷庫服務(wù)安裝合同范本
- 企業(yè)購買電腦合同范本
- 廠長和下屬分房合同范本
- 中美服裝合同范本
- 合作舉辦演出合同范本
- 債務(wù)繼承合同范本
- 叉車以租代售合同范本
- 單人房間 出租合同范本
- 名額買賣合同范例
- 2025年安徽職業(yè)技術(shù)學(xué)院單招職業(yè)技能測試題庫一套
- 開啟新征程??點(diǎn)亮新學(xué)期+課件=2024-2025學(xué)年高一下學(xué)期開學(xué)家長會(huì)
- 壓力容器考試審核考試題庫(容標(biāo)委氣體協(xié)會(huì)聯(lián)合)
- 人教版(2025版)七年級(jí)下冊英語UNIT 1 Animal Friends 單元整體教學(xué)設(shè)計(jì)(6個(gè)課時(shí))
- 2025年春季學(xué)期學(xué)校德育工作計(jì)劃及安排表
- 2025年山東商務(wù)職業(yè)學(xué)院高職單招語文2018-2024歷年參考題庫頻考點(diǎn)含答案解析
- 海洋自主無人系統(tǒng)跨域協(xié)同任務(wù)規(guī)劃模型與技術(shù)發(fā)展研究
- 校園體育活動(dòng)的多元化與健康促進(jìn)
- 新中式養(yǎng)生知識(shí)培訓(xùn)課件
- 山東省臨沂市地圖矢量課件模板()
- 學(xué)習(xí)2025年全國教育工作會(huì)議心得體會(huì)
評論
0/150
提交評論