第8章 數(shù)據(jù)庫編程_第1頁
第8章 數(shù)據(jù)庫編程_第2頁
第8章 數(shù)據(jù)庫編程_第3頁
第8章 數(shù)據(jù)庫編程_第4頁
第8章 數(shù)據(jù)庫編程_第5頁
已閱讀5頁,還剩82頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第8章

數(shù)據(jù)庫編程

(DatabaseProgramming)主講教師:劉懷廣

lhg81219@163.comVisualC++6.0為用戶提供了ODBC(開放數(shù)據(jù)庫連接)

、DAO(數(shù)據(jù)訪問對象)及OLEDB(OLE數(shù)據(jù)庫)三種數(shù)據(jù)庫方式。這三種方式中最簡單也最常用的是ODBC,因此本章先來重點介紹MFC的ODBC編程方法和技巧,然后介紹基于OLEDB的ADO(ActiveXDataObjects,ActiveX數(shù)據(jù)對象)技術(shù),最后介紹一些用于數(shù)據(jù)庫的ActiveX控件。數(shù)據(jù)庫概述8.1MFCODBC數(shù)據(jù)庫概述ODBC是一種使用SQL的程序設計接口,使用ODBC能使用戶編寫數(shù)據(jù)庫應用程序變得容易簡單,避免了與數(shù)據(jù)源相連接的復雜性。MFC的ODBC數(shù)據(jù)庫類CDatabase(數(shù)據(jù)庫類)、CRecordSet(記錄集類)和CRecordView(記錄視圖類)可為用戶管理數(shù)據(jù)庫提供了切實可行的解決方案。8.1.1數(shù)據(jù)庫基本概念1.數(shù)據(jù)庫和數(shù)據(jù)庫管理系統(tǒng)DBMS

數(shù)據(jù)庫是指以一定的組織形式存放在計算機存儲介質(zhì)上的相互關(guān)聯(lián)的數(shù)據(jù)的集合。DBMS:包括數(shù)據(jù)庫的建立和記錄的輸入、修改、檢索、顯示、刪除和統(tǒng)計等。流行的DBMS都提供了一個SQL接口。8.1.1數(shù)據(jù)庫基本概念2.SQL

DBMS中訪問和操作的語言,SQL(結(jié)構(gòu)化查詢語言)語句分為兩類:

DDL(DataDefinitionLanguage,數(shù)據(jù)定義語言)語句,它是用來創(chuàng)建表、索引等;

DML(DataManipulationLanguage,數(shù)據(jù)操作語言)語句,這些語句是用來讀取數(shù)據(jù)、更新數(shù)據(jù)和執(zhí)行其他類似操作的語句。3.ODBC、DAO和OLEDB

ODBC提供了應用程序接口(API),使得任何一個數(shù)據(jù)庫都可以通過ODBC驅(qū)動器與指定的DBMS相聯(lián)。

DAO使用Jet數(shù)據(jù)庫引擎形成一系列的數(shù)據(jù)訪問對象:數(shù)據(jù)庫對象、表和查詢對象、記錄集對象等。

OLEDB提供一個統(tǒng)一的數(shù)據(jù)訪問接口,使得應用程序可以使用同樣的方法訪問各種數(shù)據(jù),而不用考慮數(shù)據(jù)的具體存儲地點、格式或類型。8.1.1數(shù)據(jù)庫基本概念4.ADO(ActiveXDataObjects)

ADO是目前比較流行的客戶端數(shù)據(jù)庫編程技術(shù)。ADO技術(shù)基于COM(ComponentObjectModel,組件對象模型),是遠程數(shù)據(jù)存取的發(fā)展方向。8.1.1數(shù)據(jù)庫基本概念8.1.2MFCODBC向?qū)н^程用MFCAppWizard使用ODBC數(shù)據(jù)庫的一般過程是:①用Access或其他數(shù)據(jù)庫工具構(gòu)造一個數(shù)據(jù)庫;②在Windows中為剛才構(gòu)造的數(shù)據(jù)庫定義一個ODBC數(shù)據(jù)源;③在創(chuàng)建數(shù)據(jù)庫處理的文檔應用程序向?qū)е羞x擇數(shù)據(jù)源;④設計界面,并使控件與數(shù)據(jù)表字段關(guān)聯(lián)。1.構(gòu)造數(shù)據(jù)庫

數(shù)據(jù)庫表與表之間的關(guān)系構(gòu)成了一個數(shù)據(jù)庫。作為示例,這里用MicrosoftAccess創(chuàng)建一個數(shù)據(jù)庫Student.mdb,其中暫包含一個數(shù)據(jù)表score,用來描述學生課程成績。在表中包括上、下兩部分,上部分是數(shù)據(jù)表的記錄內(nèi)容,下部分是數(shù)據(jù)表的結(jié)構(gòu)內(nèi)容。

表8.1學生課程成績表(score)及其表結(jié)構(gòu)圖8.1Windows2000的管理工具圖8.2ODBC數(shù)據(jù)源管理器2.創(chuàng)建ODBC數(shù)據(jù)源

Windows中的ODBC組件是出現(xiàn)在系統(tǒng)的“控制面板”管理工具中,如圖8.1所示。雙擊ODBC圖標(在圖8.1中已圈定),進入ODBC數(shù)據(jù)源管理器。在這里,用戶可以設置ODBC數(shù)據(jù)源的一些信息。其中,“用戶DSN”頁面是用來定義用戶自己在本地計算機使用的數(shù)據(jù)源名(DSN),如圖8.2所示。圖8.3“創(chuàng)建新數(shù)據(jù)源”對話框

圖8.4ODBCAccess安裝對話框

創(chuàng)建用戶DSN的過程如下:(1)單擊[添加]→彈出“創(chuàng)建新數(shù)據(jù)源”→選擇“MicrosoftAccessDriver”。(2)單擊[完成]→進入指定驅(qū)動程序的安裝對話框→單擊[選擇]將前面創(chuàng)建的數(shù)據(jù)庫調(diào)入→在數(shù)據(jù)源名輸入“DatabaseExampleForVC++”,結(jié)果如圖8.4所示。(3)單擊[確定]按鈕,剛才創(chuàng)建的用戶數(shù)據(jù)源被添加在“ODBC數(shù)據(jù)源管理器”的“用戶數(shù)據(jù)源”列表中。如圖8.5所示。圖8.5用戶數(shù)據(jù)源列表8.1.2MFCODBC向?qū)н^程8.1.2MFCODBC向?qū)н^程表8.2MFC支持數(shù)據(jù)庫的不同選項3.在MFCAppWizard中選擇數(shù)據(jù)源1)創(chuàng)建一個支持數(shù)據(jù)庫的文檔應用程序Ex_ODBC。2)在向?qū)У牡?步對話框中加入數(shù)據(jù)庫的支持。其中各選項的含義如表8.2所示。3)選中“數(shù)據(jù)庫查看使用文件支持”項,單擊[DataSource]按鈕,彈出“DatabaseOptions”對話框,從中選擇ODBC的數(shù)據(jù)源“DatabaseExampleForVC++”,如圖8.7所示。圖8.7“DatabaseOptions”對話框

8.1.2MFCODBC向?qū)н^程(4)保留其他默認選項,單擊[OK]按鈕,彈出“SelectDatabaseTables”對話框,從中選擇要使用的表score。(5)單擊[OK]按鈕,又回到了向?qū)У牡?步對話框。(6)單擊[完成]按鈕。開發(fā)環(huán)境自動打開表單視圖CEx_ODBCView的對話框資源模板IDD_EX_ODBC_FORM以及相應的對話框編輯器。(7)編譯并運行,結(jié)果如圖8.9所示。記錄瀏覽按鈕圖8.9Ex_ODBC運行結(jié)果8.1.2MFCODBC向?qū)н^程4.設計瀏覽記錄界面在上面的Ex_ODBC中,MFC為用戶自動創(chuàng)建了用于瀏覽數(shù)據(jù)表記錄的工具按鈕和相應的“記錄”菜單項。若在表單視圖CEx_ODBCView中添加控件并與表的字段相關(guān)聯(lián),就可以根據(jù)表的當前記錄位置顯示相應的數(shù)據(jù)。其步驟如下。(1)按照圖所示的布局,為表單對話框資源模板添加控件。8.1.2MFCODBC向?qū)н^程表8.3表單對話框控件及屬性(2)按快捷鍵Ctrl+W→切換到MemberVariables頁面→為上述控件添加相關(guān)聯(lián)的數(shù)據(jù)成員。與以往添加控件變量不同的是,這里添加的控件變量都是由系統(tǒng)自動定義的,并與數(shù)據(jù)庫表字段相關(guān)聯(lián)的。8.1.2MFCODBC向?qū)н^程表8.4控件變量(3)按照上一步驟的方法,為表8.4所示的其他控件依次添加相關(guān)聯(lián)的成員變量。需要說明的是,控件變量的范圍和大小應與數(shù)據(jù)表中的字段一一對應。(4)編譯運行并測試。8.1.2MFCODBC向?qū)н^程8.1.3ODBC數(shù)據(jù)表綁定更新圖8.14“MFCClassWizard”(1)按快捷鍵Ctrl+W,切換到“MemberVariables”頁面。(2)在“Classname”的下拉列表中選擇“CEx_ODBCSet”,[UpdateColumns]和[BindAll]按鈕被激活,如圖8.14所示。圖8.15“DatabaseOptions”

圖8.16“SelectDatabaseTables”(3)[UpdateColumns]按鈕,彈出“DatabaseOptions”對話框,選擇ODBC數(shù)據(jù)源“DatabaseExampleForVC++”,如圖8.15所示。(4)單擊[OK],如圖8.16的“SelectDatabaseTables”,選擇要使用的表。8.1.3ODBC數(shù)據(jù)表綁定更新(5)單擊[OK],又回到MFCClassWizard界面。(6)單擊[BindAll]按鈕,MFCWizard將自動為字段落添加相關(guān)聯(lián)的變量。8.1.3ODBC數(shù)據(jù)表綁定更新8.2MFCODBC應用編程

使用MFC所供的ODBC類:CDatabase(數(shù)據(jù)庫類)、CRecordSet(記錄集類)和CRecordView(可視記錄集類)。

CDatabase類:提供對數(shù)據(jù)源的連接,通過它可以對數(shù)據(jù)源進行操作;

CRecordSet類:為用戶提供了對表記錄進行操作的許多功能,如查詢記錄、添加記錄、刪除記錄、修改記錄等。

CRecordView類:控制并顯示數(shù)據(jù)庫記錄,該視圖是直接連到一個CRecordSet對象的表單視圖。8.2.1查詢記錄圖8.18要添加的控件CRecordSet類的成員變量m_strFilter、m_strSort和成員函數(shù)Open可以對表進行記錄的查詢和排序。在前面的Ex_ODBC的表單中添加一個編輯框和一個[查詢]按鈕:單擊[查詢]按鈕,將按編輯框中的學號內(nèi)容對數(shù)據(jù)表進行查詢,并將查找到的記錄顯示在前面添加的控件中。具體過程如下:(1)打開Ex_ODBC應用程序的表單資源,按圖8.18所示的布局:添加編輯框ID為IDC_EDIT_QUERY,“查詢”按鈕ID為IDC_BUTTON_QUERY。8.2.1查詢記錄(2)用MFCClassWizard為控件IDC_EDIT_QUERY添加Cstring型的成員變量m_strQuery。(3)在CEx_ODBCView類中添加按鈕控件IDC_BUTTON_QUERY的BN_CLICKED消息映射,并在映射函數(shù)中添加下列代碼:(4)編譯運行并測試,結(jié)果如圖所示。圖8.19查詢記錄voidCEx_ODBCView::OnButtonQuery(){ UpdateData(); m_strQuery.TrimLeft();//刪除字符串左邊的空格及控制字符如(\n\t空格等)

if(m_strQuery.IsEmpty()){MessageBox("要查詢的學號不能為空!");return;} if(m_pSet->IsOpen())m_pSet->Close();//如果記錄集打開,則先關(guān)閉

m_pSet->m_strFilter.Format("studentno='%s'",m_strQuery);

//studentno是score表的字段名,用來指定查詢條件

m_pSet->m_strSort="course";

//course是score表的字段名,用來按course字段從小到大排序

m_pSet->Open();//打開記錄集

if(!m_pSet->IsEOF())//如果打開記錄集有記錄

UpdateData(FALSE);//自動更新表單中控件顯示的內(nèi)容

else MessageBox("沒有查到你要找的學號記錄!");}m_strFilter和m_strSort是CRecordSet的成員變量,用來執(zhí)行條件查詢和結(jié)果排序。其中,m_strFilter稱為“過濾字符串”,相當于SQL語句中WHERE后的條件串;而m_strSort稱為“排序字符串”,相當于SQL語句中ORDERBY后的字符串。若字段的數(shù)據(jù)類型是文本,則需要在m_strFilter字符串中將單引號將查詢的內(nèi)容括起來,對于數(shù)字,則不需要用單引號。8.2.1查詢記錄8.2.2編輯記錄m_pSet->AddNew(); //在表的末尾增加新記錄m_pSet->SetFieldNull(&(m_pSet->m_studentno),FALSE);//設定m_studentno值不為空(NULL)m_pSet->m_studentno="21010503";...... //輸入新的字段值m_pSet->Update(); //將新記錄存入數(shù)據(jù)庫m_pSet->Requery(); //刷新記錄集,這在快照集方式下是必須的CRecordSet類為用戶提供了成員函數(shù)用來添加記錄、刪除記錄和修改記錄等。1.增加記錄使用AddNew函數(shù),但要求數(shù)據(jù)庫必須是以“可增加”的方式打開的。8.2.2編輯記錄2.刪除記錄直接使用CRecordSet::Delete刪除記錄。要使操作有效,還需要移動記錄函數(shù)CRecordsetStatusstatus;m_pSet->GetStatus(status);//獲取當前記錄集狀態(tài)m_pSet->Delete(); //刪除當前記錄if(status.m_lCurrentRecord==0)m_pSet->MoveNext(); //若當前記錄索引號為0(0表示第一條記錄) //則下移一個記錄elsem_pSet->MoveFirst(); //移動到第一個記錄處UpdateData(FALSE);3.修改記錄函數(shù)CRecordSet::Edit可以用來修改記錄,例如:m_pSet->Edit(); //修改當前記錄m_pSet->m_name=“杰克遜"; //修改當前記錄字段值......m_pSet->Update(); //將修改結(jié)果存入數(shù)據(jù)庫m_pSet->Requery();8.2.2編輯記錄4.撤消操作如果用戶在進行增加或者修改記錄后,希望放棄當前操作,則在調(diào)用CRecordSet::Update()函數(shù)之前調(diào)用CRecordSet::Move(AFX_MOVE_REFRESH)來撤消操作,便可恢復在增加或修改操作之前的當前記錄。8.2.2編輯記錄8.2.3字段操作CRecordSet類中的成員變量m_nFields

:用于保存數(shù)據(jù)表的字段個數(shù)。成員函數(shù)GetODBCFieldInfo及GetFieldValue可以簡化多字段的訪問操作。voidGetODBCFieldInfo(shortnIndex,CODBCFieldInfo&fieldinfo);nIndex:指定字段索引號,0表示第一個字段,1表示第二個字段,以此類推。

fieldinfo是CODBCFieldInfo結(jié)構(gòu)參數(shù),用來表示字段信息。8.2.3字段操作structCODBCFieldInfo{CStringm_strName; //字段名

SWORDm_nSQLType;//字段的SQL數(shù)據(jù)類型

UDWORDm_nPrecision;//字段的文本大小或數(shù)據(jù)大小

SWORDm_nScale; //字段的小數(shù)點位數(shù)

SWORDm_nNullability;//字段接受空值(NULL)能力};8.2.3字段操作structCRecordsetStatus{longm_lCurrentRecord; //當前記錄的索引,0表示第一個記錄,1表示第二個記錄,依次類推。但-1表示在第一個記錄之前,-2表示不確定。

BOOLm_bRecordCountFinal; //記錄總數(shù)是否是最終結(jié)果};voidGetFieldValue(shortnIndex,CString&strValue);nIndex:指定字段索引號,strValue:返回字段的內(nèi)容。longGetRecordCount()const;//獲得表中的記錄總數(shù)voidGetStatus(CRecordsetStatus&rStatus)const;//當前記錄的索引表8.5課程信息表(course)及其表結(jié)構(gòu)[例Ex_Field]字段的編程操作1.為Student.mdb添加一個數(shù)據(jù)表course:用MicrosoftAccess為數(shù)據(jù)庫Student.mdb添加一個數(shù)據(jù)表course,如表8.5所示。表中上部分是數(shù)據(jù)表的記錄內(nèi)容,下部分是數(shù)據(jù)表的結(jié)構(gòu)內(nèi)容。#ifndef_AFX_NO_AFXCMN_SUPPORT#include<afxcmn.h>//MFCsupportforWindowsCommonControls#endif//_AFX_NO_AFXCMN_SUPPORT#include<afxdb.h>2.文檔程序添加ODBC的支持(1)創(chuàng)建一個默認的單文檔應用程序Ex_Field,但在向?qū)У牡?步將CEx_FieldView的基類由默認的CView選擇為CListView類。(2)將項目工作區(qū)窗口切換到FileView頁面,展開HeaderFiles所有項,雙擊stdafx.h,打開該文件。(3)在stdafx.h中添加ODBC數(shù)據(jù)庫支持的頭文件包含#include<afxdb.h>:3.創(chuàng)建數(shù)據(jù)表score的CRecordSet派生類(1)按快捷鍵Ctrl+W→單擊[AddClass],從彈出的下拉菜單中選擇“New”。(2)在彈出的“AddClass”對話框中指定CRecordSet的派生類CCourseSet。圖8.23定義新的CRecordSet派生類(3)單擊[OK],彈出“DatabaseOptions”。從中選擇ODBC的數(shù)據(jù)源“DatabaseExampleForVC++”,單擊[OK],彈出“SelectDatabaseTables”對話框,從中選擇要使用的表course。(4)單擊[OK]回到MFCClassWizard界面,單擊[確定],系統(tǒng)自動為用戶生成CCourseSet類所需要的代碼。(5)在CEx_FieldView::PreCreateWindow函數(shù)中添加修改列表視圖風格的代碼:BOOLCEx_FieldView::PreCreateWindow(CREATESTRUCT&cs){cs.style&=~LVS_TYPEMASK;cs.style|=LVS_REPORT;//報表方式

returnCListView::PreCreateWindow(cs);}(6)在CEx_FieldView::OnInitialUpdate函數(shù)中添加下列代碼:voidCEx_FieldView::OnInitialUpdate(){ CListView::OnInitialUpdate(); CListCtrl&m_ListCtrl=GetListCtrl();//獲取內(nèi)嵌在列表視圖中的列表控件

CCourseSetcSet;

cSet.Open(); //打開記錄集

CODBCFieldInfofield;

//創(chuàng)建列表頭

for(UINTi=0;i<cSet.m_nFields;i++) { cSet.GetODBCFieldInfo(i,field); m_ListCtrl.InsertColumn(i,field.m_strName,LVCFMT_LEFT,100); }//添加列表項

intnItem=0; CStringstr; while(!cSet.IsEOF()) {for(UINTi=0;i<cSet.m_nFields;i++){cSet.GetFieldValue(i,str); if(i==0)m_ListCtrl.InsertItem(nItem,str); else m_ListCtrl.SetItemText(nItem,i,str); } nItem++; cSet.MoveNext(); } cSet.Close(); //關(guān)閉記錄集}(7)在Ex_FieldView.cpp文件的前面添加CCourseSet類的頭文件包含:

#include"Ex_FieldDoc.h"#include"Ex_FieldView.h"#include"CourseSet.h"(8)編譯運行,結(jié)果如圖8.24所示。圖8.24Ex_Field第一次運行結(jié)果4.在狀態(tài)欄中顯示當前記錄號和記錄總數(shù)(1)在MainFrm.cpp文件中,向原來的indicators數(shù)組添加一個元素,用來在狀態(tài)欄上增加一個窗格:staticUINTindicators[]={ID_SEPARATOR,//第一個信息行窗格

ID_SEPARATOR,//第二個信息行窗格

ID_INDICATOR_CAPS,ID_INDICATOR_NUM,ID_INDICATOR_SCRL,};voidDispRecNum(CCourseSet*pSet){ CStringstr; CMainFrame*pFrame=(CMainFrame*)AfxGetApp()->m_pMainWnd;//獲得主框架窗口的指針

CStatusBar*pStatus=&pFrame->m_wndStatusBar;//獲得主框架窗口中的狀態(tài)欄指針

if(pStatus){ CRecordsetStatusrStatus; pSet->GetStatus(rStatus);//獲得當前記錄信息

str.Format("當前記錄:%d總記錄:%d",1+rStatus.m_lCurrentRecord,pSet->GetRecordCount()); pStatus->SetPaneText(1,str); //更新第二個窗格的文本

}}//該函數(shù)先獲得狀態(tài)欄對象的指針,然后調(diào)用SetPaneText函數(shù)更新第二個窗格文本(2)在Ex_FieldView.cpp文件的前面添加一個全局函數(shù)DispRecNum成員函數(shù)(3)在CEx_ODBCView的OnInitialUpdate函數(shù)處添加下列代碼:voidCEx_FieldView::OnInitialUpdate(){…CStringstr;while(!cSet.IsEOF()) {… }::DispRecNum(&cSet);cSet.Close(); //關(guān)閉記錄集}(4)在Ex_ODBCView.cpp文件的開始處增加下列語句:

#include"Ex_FieldDoc.h" #include"Ex_FieldView.h" #include"CourseSet.h" #include"MainFrm.h"(5)將MainFrm.h文件中的保護型變量m_wndStatusBar變成公共變量。(6)編譯運行并測試,結(jié)果如圖8.25所示。顯示的記錄信息圖8.25Ex_Field最后運行結(jié)果8.2.4多表處理圖8.26Ex_Student運行結(jié)果

下面的示例在一個對話框中用兩個控件來進行學生課程成績信息的相關(guān)操作,如圖8.26所示,左邊是樹視圖,用來顯示學生成績、專業(yè)和班級號三個層次信息,單擊班級號,所有該班級的學生課程成績信息將在右邊的列表視圖中顯示出來。[例Ex_Student]多表處理1.為數(shù)據(jù)庫Student.mdb添加一個數(shù)據(jù)表student用MicrosoftAccess為數(shù)據(jù)庫Student.mdb添加一個數(shù)據(jù)表student,如表8.6所示。表中上部分是數(shù)據(jù)表的記錄內(nèi)容,下部分是數(shù)據(jù)表的結(jié)構(gòu)內(nèi)容。表8.6學生基本信息表(student)及其表結(jié)構(gòu)2.創(chuàng)建并設計對話框應用程序(1)創(chuàng)建一個默認的基于對話框應用程序Ex_Student。(2)刪除[取消]按鈕和默認的靜態(tài)文本控件。(3)對話框的標題改為“處理多表”,將[確定]按鈕的標題文本改為“退出”。(4)參看圖8.26,添加一個樹控件,在其屬性對話框中,選中“有按鈕”、“有行(Lines,線)”、“Linesatroot”和“總是顯示選擇”屬性。(5)添加一個列表控件,在其屬性對話框中,將“查看”屬性選為“Report”。(6)用MFCClassWizard在CEx_StudentDlg類中,添加樹控件的控件變量為m_treeCtrl,添加列表控件的控件變量為m_listCtrl。3.添加對MFCODBC的支持及記錄集在stdafx.h文件中添加ODBC數(shù)據(jù)庫支持的頭文件包含

#include<afxdb.h>

用MFCClassWizard為數(shù)據(jù)表student、course和score分別創(chuàng)建CRecordSet派生類CStudentSet、CCourseSet和CScoreSet。4.完善左邊樹控件的代碼(1)為CEx_StudentDlg類添加一個成員函數(shù)FindTreeItem,用來查找指定節(jié)點下是否有指定節(jié)點文本的子節(jié)點,該函數(shù)的代碼如下:HTREEITEMCEx_StudentDlg::FindTreeItem(HTREEITEMhParent,CStringstr){HTREEITEMhNext;CStringstrItem;hNext=m_treeCtrl.GetChildItem(hParent);while(hNext!=NULL){strItem=m_treeCtrl.GetItemText(hNext);if(strItem==str)returnhNext;elsehNext=m_treeCtrl.GetNextItem(hNext,TVGN_NEXT);}returnNULL;}(2)為CEx_StudentDlg類添加CImageList成員變量m_ImageList。(3)在CEx_StudentDlg::OnInitDialog中添加下列代碼:BOOLCEx_StudentDlg::OnInitDialog(){…SetIcon(m_hIcon,FALSE); //Setsmalliconm_ImageList.Create(16,16,ILC_COLOR8|ILC_MASK,2,1);m_treeCtrl.SetImageList(&m_ImageList,TVSIL_NORMAL);SHFILEINFOfi; //定義一個文件信息結(jié)構(gòu)變量

SHGetFileInfo("C:\\Windows",0,&fi,sizeof(SHFILEINFO), SHGFI_ICON|SHGFI_SMALLICON);//獲取文件夾圖標

m_ImageList.Add(fi.hIcon);//獲取打開文件夾圖標

SHGetFileInfo("C:\\Windows",0,&fi,sizeof(SHFILEINFO),HGFI_ICON|SHGFI_SMALLICON|SHGFI_OPENICON);m_ImageList.Add(fi.hIcon);HTREEITEMhRoot,hSpec,hClass; hRoot=m_treeCtrl.InsertItem("學生成績",0,1); CStudentSetsSet; sSet.m_strSort=“special”; //按專業(yè)排序

sSet.Open(); while(!sSet.IsEOF()){ hSpec=FindTreeItem(hRoot,sSet.m_special);//查找是否有重復的專業(yè)節(jié)點

if(hSpec==NULL)//若沒有重復的專業(yè)節(jié)點

hSpec=m_treeCtrl.InsertItem(sSet.m_special,0,1,hRoot); hClass=FindTreeItem(hSpec,sSet.m_studentno.Left(6)); //查找是否有重復的班級節(jié)點

if(hClass==NULL)//若沒有重復的班級節(jié)點

hClass=m_treeCtrl.InsertItem(sSet.m_studentno.Left(6),0,1,hSpec); sSet.MoveNext(); } sSet.Close(); returnTRUE;//returnTRUEunlessyousetthefocustoacontrol}(4)在Ex_StudentDlg.cpp文件的前面添加記錄集類的包含文件:

#include"Ex_StudentDlg.h"#include"StudentSet.h"#include"ScoreSet.h"#include"CourseSet.h"(5)編譯運行,結(jié)果如圖8.27所示。圖8.27Ex_Student第一次運行結(jié)果5.完善右邊列表控件的代碼(1)在CEx_StudentDlg::OnInitDialog函數(shù)中添加代碼,創(chuàng)建列表標題頭BOOLCEx_StudentDlg::OnInitDialog(){…sSet.Close();//設置列表頭

CStringstrHeader[]={"學號","姓名","課程號","課程所屬專業(yè)", "課程名稱","課程類別","開課學期","課時數(shù)","學分","成績"};intnLong[]={80,80,80,180,180,80,80,80,80,80};for(intnCol=0;nCol<sizeof(strHeader)/sizeof(CString);nCol++)m_listCtrl.InsertColumn(nCol,strHeader[nCol],LVCFMT_LEFT,nLong[nCol]);returnTRUE;//returnTRUEunlessyousetthefocustoacontrol}(2)為CEx_StudentDlg類添加一個成員函數(shù)DispScoreAndCourseInfo,用來根據(jù)指定的條件在列表控件中用報表形式顯示學生成績的所有信息。voidCEx_StudentDlg::DispScoreAndCourseInfo(CStringstrFilter){ m_listCtrl.DeleteAllItems();//刪除所有的列表項

CScoreSetsSet; sSet.m_strFilter=strFilter;//設置過濾條件

sSet.Open(); //打開score表

intnItem=0; CStringstr; while(!sSet.IsEOF()) {m_listCtrl.InsertItem(nItem,sSet.m_studentno);//插入學號

//根據(jù)score表中的studentno(學號)獲取student表中的"姓名" CStudentSetuSet; uSet.m_strFilter.Format("studentno='%s'",sSet.m_studentno); uSet.Open(); if(!uSet.IsEOF())m_listCtrl.SetItemText(nItem,1,uSet.m_studentname); uSet.Close(); m_listCtrl.SetItemText(nItem,2,sSet.m_course);

//根據(jù)score表中的course(課程號)獲取course表中的課程信息

CCourseSetcSet; cSet.m_strFilter.Format("courseno='%s'",sSet.m_course); cSet.Open(); UINTi=7; if(!cSet.IsEOF()){for(i=1;i<cSet.m_nFields;i++){cSet.GetFieldValue(i,str);//獲取指定字段值

m_listCtrl.SetItemText(nItem,i+2,str); } } cSet.Close(); str.Format("%0.1f",sSet.m_score); m_listCtrl.SetItemText(nItem,i+2,str); sSet.MoveNext(); nItem++; } if(sSet.IsOpen())sSet.Close();}(3)編譯并運行,結(jié)果如圖8.28所示。圖8.28Ex_Student第二次運行結(jié)果voidCEx_StudentDlg::OnSelchangedTree1(NMHDR*pNMHDR,LRESULT*pResult){ NM_TREEVIEW*pNMTreeView=(NM_TREEVIEW*)pNMHDR; HTREEITEMhSelItem=pNMTreeView->itemNew.hItem;//獲取當前選擇節(jié)點

//如果當前的節(jié)點沒有子節(jié)點,那說明該節(jié)點是班級號節(jié)點

if(m_treeCtrl.GetChildItem(hSelItem)==NULL){ CStringstrSelItem,str; strSelItem=m_treeCtrl.GetItemText(hSelItem); str.Format("studentnoLIKE'%s%%'",strSelItem.Left(6));

DispScoreAndCourseInfo(str); } *pResult=0;}6.完善兩控件的關(guān)聯(lián)代碼從上圖中可以看出,學生成績還沒有顯示出來,下面將實現(xiàn)單擊左邊的班級號,在右邊視圖中顯示該班級的所有學生成績信息。(1)CEx_StudentDlg類添加TVN_SELCHANGED消息處理:

代碼中,調(diào)用DispScoreAndCourseInfo

函數(shù)的參數(shù)是用來設置數(shù)據(jù)表(記錄集)打開的過濾條件。str是類似內(nèi)容:“studentnoLIKE210101%”,它使得所有學號前面是210101的記錄被打開。%是SQL使用的通配符,由于%也是VisaulC++格式前導符,因為在代碼中需要兩個%。(2)編譯運行并測試。8.3ADO數(shù)據(jù)庫編程ADO最主要的優(yōu)點:易于使用、速度快、內(nèi)存開銷小,它使用最少的網(wǎng)絡流量,并且在前端和數(shù)據(jù)源之間使用最少的層數(shù),它是一個輕量、高性能的接口。ADO實際上就是由一組Automation對象構(gòu)成的組件,因此可以像使用其它任何Automation對象一樣使用ADO。ADO中最重要的對象有三個:Connection、Command和Recordset,它們分別表示“連接”對象、“命令”對象和“記錄集”對象。8.3.1ADO編程的一般過程在MFC應用程序中使用ADO數(shù)據(jù)庫的一般過程是:①添加對ADO的支持;②創(chuàng)建一個數(shù)據(jù)源連接;③對數(shù)據(jù)源中的數(shù)據(jù)庫進行操作;④關(guān)閉數(shù)據(jù)源。1.添加對ADO的支持

ADO編程有三種方式:使用預處理指令#import、使用MFC中的CIDispatchDriver和直接使用COM提供的API。這三種方式中,第一種最為簡便,故這里采有用這種方法。下面以一個示例過程來說明在MFC應用程序中添加對ADO的支持。[例Ex_ADO]添加對ADO的支持(1)

創(chuàng)建單文檔應用程序Ex_ADO,在第6步將CEx_ADOView的基類由默認的CView選擇為CListView類。(2)

在CEx_ADOView::PreCreateWindow函數(shù)添加下列代碼,用來設置列表視圖內(nèi)嵌列表控件的風格:BOOLCEx_ADOView::PreCreateWindow(CREATESTRUCT&cs){cs.style|=LVS_REPORT;//報表風格

returnCListView::PreCreateWindow(cs);}(3)在stdafx.h文件中添加對ADO支持的代碼:#endif//_AFX_NO_AFXCMN_SUPPORT#include<afxcmn.h>//MFCsupportforWindowsCommonControls#import"C:\ProgramFiles\CommonFiles\System\ADO\msado15.dll"\no_namespacerename("EOF","adoEOF")#include<icrsint.h>//{{AFX_INSERT_LOCATION}}

預編譯命令#import是編譯器將此命令中所指定的動態(tài)鏈接庫文件引入到程序中,并從動態(tài)鏈接庫文件中抽取出其中的對象和類的信息。

icrsint.h文件包含了VisualC++擴展的一些預處理指令、宏等的定義,用于與數(shù)據(jù)庫數(shù)據(jù)綁定。(4)CEx_ADOApp::InitInstance添加代碼,用來對ADO的

COM環(huán)境進行初始化BOOLCEx_ADOApp::InitInstance(){::CoInitialize(NULL);AfxEnableControlContainer(); …}(5)在Ex_ADOView.h文件中為CEx_ADOView定義三個ADO對象指針變量:public:_ConnectionPtrm_pConnection;_RecordsetPtrm_pRecordset;_CommandPtrm_pCommand;_ConnectionPtr、_RecordsetPtr和_CommandPtr分別是ADO對象Connection、Recordset和Command的智能指針類型。2.連接數(shù)據(jù)源

ADO使用Connection對象來建立與數(shù)據(jù)庫服務器的連接,它相當于MFC的CDatabase類。和CDatabase類一樣,調(diào)用Connection對象的Open即可建立與服務器的連接。ConnectionString:連接字串,UserID:用戶名,Password:登錄密碼,Options是選項,通常用于設置同步和異步等方式。_bstr_t是一個COM類,用于字符串BSTR(用于Automation的寬字符)操作。需要說明的是,正確設置ConnectionString是連接數(shù)據(jù)源的關(guān)鍵。不同的數(shù)據(jù),其連接字串有所不同,見表8.7所示。HRESULTConnection::Open(_bstr_t

ConnectionString,_bstr_tUserID,_bstr_tPassword,longOptions)表8.7Connection對象的連接字串格式voidCEx_ADOView::OnDestroy(){ CListView::OnDestroy(); if(m_pConnection)m_pConnection->Close();//關(guān)閉連接 }3.關(guān)閉連接

CEx_ADOView映射WM_DESTROY消息,并添加下列代碼:4.獲取數(shù)據(jù)源信息Connection對象除了建立與數(shù)據(jù)庫服務器的連接外,還可以通過OpenSchema來獲取數(shù)據(jù)源的自有信息。下面的代碼用來獲取student.mdb的數(shù)據(jù)表名和字段名,并將內(nèi)容顯示在列表視圖中:voidCEx_ADOView::OnInitialUpdate(){CListView::OnInitialUpdate();//初始化Connection指針

m_pConnection.CreateInstance(__uuidof(Connection));//初始化Recordset指針

m_pRecordset.CreateInstance(__uuidof(Recordset));//初始化Recordset指針

m_pCommand.CreateInstance(__uuidof(Command));

//連接數(shù)據(jù)源為"DatabaseExampleForVC++"m_pConnection->ConnectionString="DSN=DatabaseExampleForVC++";

//允許連接超時時間,單位為秒

m_pConnection->ConnectionTimeout=30;HRESULThr=m_pConnection->Open("","","",0);//獲取數(shù)據(jù)表名和字段名

if(hr!=S_OK)MessageBox(“無法連接指定的數(shù)據(jù)庫!”);_RecordsetPtrpRstSchema=NULL; //定義一個記錄集指針

//獲取表信息

pRstSchema=m_pConnection->OpenSchema(adSchemaColumns);//將表信息顯示在列表視圖控件中

CListCtrl&m_ListCtrl=GetListCtrl();CStringstrHeader[3]={"序號","TABLE_NAME","COLUMN_NAME"};for(inti=0;i<3;i++)m_ListCtrl.InsertColumn(i,strHeader[i],LVCFMT_LEFT,120);intnItem=0;CStringstr;_bstr_tvalue; while(!(pRstSchema->adoEOF)){str.Format("%d",nItem+1); m_ListCtrl.InsertItem(nItem,str); for(inti=1;i<3;i++){value=pRstSchema->Fields->GetItem((_bstr_t)(LPCSTR)strHeader[i])->Value; m_ListCtrl.SetItemText(nItem,i,value); } pRstSchema->MoveNext(); nItem++; } pRstSchema->Close();}__uuidof:獲取對象的的全局唯一標識(GUID)。ConnectionTimeout:連接超時屬性,單位為秒。OpenSchema方法中的adSchemaColumns是一個預定義的枚舉常量,用來獲取與“列”(字段)相關(guān)的信息記錄集。該信息記錄集的主要字段名有“TABLE_NAME”、“COLUMN_NAME”;類似的,若在OpenSchema方法中指定adSchemaTables枚舉常量,則返回的記錄集的字段名主要有“TABLE_NAME”、“TABLE_TYPE”。8.3.2Recordset對象使用Recordset:從數(shù)據(jù)表或某一個SQL執(zhí)行后獲得記錄集,通過Recordset對象的AddNew、Update和Delete方法可實現(xiàn)記錄的添加、修改和刪除操作。1.讀取數(shù)據(jù)表全部記錄內(nèi)容(1)打開IDR_MAINFRAME,在頂層菜單“查看”下添加一個“顯示Course表記錄”子菜單,將其ID號設為D_VIEW_COURSE。(2)按快捷鍵Ctrl+W,向CEx_ADOView類添加ID_VIEW_COURSE的COMMAND消息映射,保留默認的映射函數(shù)OnViewCourse:voidCEx_ADOView::OnViewCourse(){ CListCtrl&m_ListCtrl=GetListCtrl();

//刪除列表中所有行和列表頭

m_ListCtrl.DeleteAllItems(); intnColumnCount=m_ListCtrl.GetHeaderCtrl()->GetItemCount(); for(inti=0;i<nColumnCount;i++) m_ListCtrl.DeleteColumn(0); m_pRecordset->Open("Course",//指定要打開的表

m_pConnection.GetInterfacePtr(),//獲取當前數(shù)據(jù)庫連接的接口指針

adOpenDynamic, //動態(tài)游標類型,可以使用Move等操作

adLockOptimistic,adCmdTable);//建立列表控件的列表頭

FieldsPtrflds=m_pRecordset->GetFields();//獲取當前表的字段指針

_variant_tIndex;Index.vt=VT_I2; m_ListCtrl.InsertColumn(0,"序號",LVCFMT_LEFT,60); for(i=0;i<(int)flds->GetCount();i++){ Index.iVal=i; m_ListCtrl.InsertColumn(i+1,(LPSTR)flds->GetItem(Index)->GetName(),LVCFMT_LEFT,140); }

//顯示記錄

_bstr_tstr,value; intnItem=0; CStringstrItem; while(!m_pRecordset->adoEOF){strItem.Format("%d",nItem+1); m_ListCtrl.InsertItem(nItem,strItem); for(i=0;i<(int)flds->GetCount();i++){ Index.iVal=i; str=flds->GetItem(Index)->GetName(); value=m_pRecordset->GetCollect(str); m_ListCtrl.SetItemText(nItem,i+1,(LPCSTR)value); } m_pRecordset->MoveNext(); nItem++; } m_pRecordset->Close(); }_variant_t:一個用于COM的VARIANT類,VARIANT類型是一個C結(jié)構(gòu),由于它既包含了數(shù)據(jù)本身,也包含了數(shù)據(jù)的類型,它可以實現(xiàn)各種不同的自動化數(shù)據(jù)的傳輸。(3)編譯運行并測試,結(jié)果如圖8.30所示。圖8.30顯示Course表所有記錄8.3.2Recordset對象使用2.添加、修改和刪除記錄向course表中新添加一個記錄可有下列代碼://打開記錄集m_pRecordset->AddNew();//添加新記錄m_pRecordset->PutCollect("courseno",_variant_t("2112111"));m_pRecordset->PutCollect("coursehourse",_variant_t(60));…m_pRecordset->Update();//使添加有效//關(guān)閉記錄集若從course表中刪除一個記錄可有下列代碼://打開記錄集……m_pRecordset->Delete(adAffectCurrent);//刪除當前行m_pRecordset->MoveFirst();//調(diào)用Move方法,使刪除有效

//關(guān)閉記錄集若從course表中修改一個記錄可有下列代碼://打開記錄集m_pRecordset->PutCollect("courseno",_variant_t("2112111"));m_pRecordset->PutCollect("coursehourse",_variant_t(60));…m_pRecordset->Update();//使修改有效

//關(guān)閉記錄集

特別強調(diào)的是,數(shù)據(jù)庫的表名不能與ADO的某些關(guān)鍵字串同名,例如:user等。另外,通常用Command對象執(zhí)行SQL命令來實現(xiàn)數(shù)據(jù)表記錄的查詢、添加、更新和刪除等操作,而用Recordset對象獲取記錄集,用來顯示記錄內(nèi)容。8.3.3Command對象使用Command對象用來執(zhí)行SQL命令。下面簡單介紹SQL幾個常用語句:1.SELECT語句一個典型的SQL查詢可以從指定的數(shù)據(jù)庫表中“選擇”信息,這時就需要使用SELECT語句來執(zhí)行。SELECT語句格式如下:

SELECT字段名

FROM表名[WHERE子句][ORDERBY子句]…

它的最簡單形式是:

SELECT*FROMtableName

其中,星號(*)用來指定從數(shù)據(jù)庫的tableName表中選擇所有的字段(列)。若要從表中選擇指定字段的記錄,則將星號(*)用字段列表來代替,多個字段之間用逗號分隔。(1)WHERE子句SELECTcolumn1,

column2,…FROMtableNameWHEREconditionWHERE子句中的條件可以<(小于)、>(大于)、<=(小于等于)、>=(大于等于)、=(等于)、<>(不等于)和LIKE等運算符。其中,LIKE用于匹配條件的查詢,它可以使用“%”和“_(下劃線)”等通配符,“%”表示可以出現(xiàn)0個或多個字符,“_”表示該位置處只能出現(xiàn)1個字符。(1)SELECT*FROMScoreWHEREstudentnoLIKE‘21%’則將Score表中所有學號以21打頭的記錄查詢出來。注意,LIKE后面的字符串是以單引號來標識。(2)SELECT*FROMScoreWHEREstudentnoLIKE‘210105__’則將Score表中所有學號以210105打頭,且學號為8位的記錄查詢出來.(3)還可用AND(與)、OR(或)以及NOT(非)運算符來構(gòu)造復合條件查詢:SELECT*FROMScoreWHEREscore<=80ANDscore>=70ASC:升序(從低到高),DESC:降序(從高到低),col1、col2…分別用來指定是按什么字段來排序。當指定多個字段時,則先按col1排序,當有相同col1的記錄時,則相同的記錄按col2排序,依此類推。(2)ORDERBY子句SELECTcolumn1,

column2,…FROMtableName[WHEREcondition]ORDERBYcol1,

co2,…ASC|DESC2.INSERT語句INSERTINTO

tableName(col1,col2,col3,…,colN)

VALUES

(val1,val2,val3,…valN)tableName:指定插入新記錄的數(shù)據(jù)表,tableName后跟一對圓括號,包含一個以逗號分隔的列(字段)名的列表,VALUES后面的圓括號內(nèi)是一個以逗號分隔的值列表,它與tableName后面的列名列表是一一對應的。需要說明的是,若某個記錄的某個字段值是字符串,則需要用單引號來括起來。例如:INSERTINTOStudent(studentno,studentname)VALUES('21010503','張小峰')將在Student中插入一個新行,其中studentno(學號)為“21010503”,studentname(學生姓名)為“張小峰”,對于該記錄的其它字段值,由于沒有指定相應的值,其結(jié)果由系統(tǒng)決定。3.UPDATE語句UPDATE

tableNameSET

column1=value1,

column2=value2,…,columnN=valueN

WHEREcondition該語句可以更新tableName表中一行記錄或多行記錄的數(shù)據(jù),這取決于WHERE后面的條件。關(guān)鍵字SET后面是以逗號分隔的“列名/值”列表。例如:UPDATEStudentSETstudentname='王鵬'WHEREstudentno='21010503'將學號為“21010503”的記錄中的studentname字段內(nèi)容更新為“王鵬”。4.DELETE語句DELETE語句用來從表中刪除記錄,其常用形式如下:

DELETEFROMtableNameWHEREcondition

該語句可以刪除tableNam表中一行記錄或多行記錄,這取決于WHERE后面的條件。8.4數(shù)據(jù)庫相關(guān)的ActiveX控件

在前面的數(shù)據(jù)庫處理中,一次只能顯示出一行記錄,且修改或添加等操作不能“可視化”地進行。為了彌補MFC的這種不足,在VisualC++6.0中允許用戶使用一些ActiveX控件用來更好地操作數(shù)據(jù)庫,這些控件包括MSFlexGrid、RemoteData、DBGrid等。8.4.1使用MSFlexGrid控件可以顯示網(wǎng)格數(shù)據(jù),也可以對其進行操作。網(wǎng)格中可以包含字符串和圖片。利用MSFlexGrid可以將某個表的所有記錄顯示。[例Ex_Grid]使用RemoteData和DBGrid控件1.將控件的類添加到項目中(1)創(chuàng)建一個單文檔應用程序Ex_Grid。(2)第2步對話框中,選中“數(shù)據(jù)庫查看使用文件支持”,單擊[DataSource],彈出“DatabaseOptions”,從中選擇ODBC的數(shù)據(jù)源“DatabaseExampleForVC++”。保留其他默認選項,單擊[OK],在彈出的“SelectDatabaseTables”對話框中,選擇要使用的表score。(3)單擊[OK],又回到了第2步對話框。單擊[完成]。開發(fā)環(huán)境自動打開表單視圖CEx_GridView的對話框資源模板IDD_EX_GRID_FORM。(4)在打開的表單資源模板中右擊鼠標,從彈出的快捷菜單中選擇“InsertActiveControl”命令,出現(xiàn)如圖8.31所示“插入Active控件”對話框。(5)在列表中選擇MicorsoftFlexGridControl控件,單擊[確定]按鈕,該控件就添加到表單資源中,參看圖8.33,調(diào)整其大小和位置。圖8.31“插入ActiveX控件”對話框圖8.32MSFlexGrid控件的屬性對話框2.修改MSFlexGrid控件屬性右擊MicorsoftFlexGridControl控件,彈出的菜單中選擇“屬性”或“屬性MSFlexGridObject”命令均可打開控件的屬性對話框,如圖8.32所示。

MSFlexGrid控件的屬性要比VisualC++的控件屬性要多,如“General”、“通用”、“樣式”、“字體”、“顏色”、“圖片”等。這些屬性不僅能設置控件的字體、顏色,而且能設置網(wǎng)格的行數(shù)和列數(shù)以及其他的功能。3.編程控制(1)保留默認的屬性及其控件標識符IDC_MSFLEXGRID1。(2)用MFCClassWizard在CEx_GridView類中為剛才添加的MSFlexGrid控件設置一個相關(guān)聯(lián)的控件變量m_MSFGrid。在此步驟中會出現(xiàn)一些對話框,用于詢問是否要添加相關(guān)控件的類代碼等,選擇[是]。(3)在CEx_ODBCView類的OnInitialUpdate函數(shù)中添加下列代碼:voidCEx_GridView::OnInitialUpdate(){ … while(!m

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論