本文主要是介绍上一篇的续集,另一个人写的,请原谅到底是谁写的我不知道,感谢原创人,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
二、编程步骤
1、启动Visual C++6.0,生成一个单文档视图结构的应用程序,将该程序命名为"Enroll"。在MFC AppWizard的第一步选择Single document,在MFC AppWizard的第二步选择Database view without file support,然后点击Data Source...按钮,在Database Options对话框中的ODBC组合框中选择Student Registration数据源,则会打开一个Select Database Table对话框,在该对话框中选择数据库中的Section表按OK按钮退出,在MFC AppWizard的第六步中,将类CEnrollSet改名为CSectionSet,将类CEnrollView改名为CSectionForm;
2、接下来的任务设计应用程序的界面(具体设置请参见原代码部分),并用ClassWizard把表单中的控件与记录集的域数据成员连接起来,以实现控件与当前记录的DDX数据交换。请读者按如下步骤操作:进入ClassWizard,选择Member Variables页并且选择CSectionForm类。在变量列表中双击IDC_CAPACITY项,则会显示Add Member Variable对话框。注意该对话框的Member variable name栏显示的是一个组合框,而不是平常看到的编辑框。在组合框的列表中选择m_pSet->m_Capacity并按OK按钮确认。其它控件依此类推。
3、对于组合框控件IDC_COURSELIST项,除在Add Member Variable对话框的组合框中选择m_pSet->m_CourseID外,还要再次双击IDC_COURSELIST,并为CSectionForm类加入一个名为m_ctlCourseList的CComboBox类成员。
4、使用Class Wizard为IDC_COURSELIST组合框加入CBN_SELENDOK通知消息处理函数,函数名为OnSelendokCourselist。该函数负责响应用户在组合框中选择的变化。
5、接着使用ClassWizard为数据库中的Course表创建一个名为CCourseSet的记录集类;
6、在CEnrollDoc类的定义中,紧接着m_sectionSet成员,加入下面一行:CCourseSet m_courseSet。这样CEnrollDoc就包含了两个记录集。由于CEnrollDoc类用到了CCourseSet类,所以要在所有含有#include "EnrolDoc.h"语句的CPP文件中,在#include "EnrolDoc.h"语句的前面加上#include "CourseSet.h"语句。
7、在CSectionSet类的定义中,紧接着域数据成员,在"//}}AFX_FIELD"注释外加入下面一行CString m_strCourseIDParam;
8、添加代码,编译运行程序。
三、程序代码
/ SectSet.h : interface of the CSectionSet class class CSectionSet : public CRecordset { public: CSectionSet(CDatabase* pDatabase = NULL); DECLARE_DYNAMIC(CSectionSet) // Field/Param Data //{{AFX_FIELD(CSectionSet, CRecordset) CString m_CourseID; CString m_SectionNo; CString m_InstructorID; CString m_RoomNo; CString m_Schedule; int m_Capacity; //}}AFX_FIELD CString m_strCourseIDParam; // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CSectionSet) public: virtual CString GetDefaultConnect(); // Default connection string virtual CString GetDefaultSQL(); // default SQL for Recordset virtual void DoFieldExchange(CFieldExchange* pFX); // RFX support //}}AFX_VIRTUAL // Implementation #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif }; /// SectSet.cpp : implementation of the CSectionSet class #include "stdafx.h" #include "Enroll.h" #include "SectSet.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif IMPLEMENT_DYNAMIC(CSectionSet, CRecordset) CSectionSet::CSectionSet(CDatabase* pdb) : CRecordset(pdb) { //{{AFX_FIELD_INIT(CSectionSet) m_CourseID = _T(""); m_SectionNo = _T(""); m_InstructorID = _T(""); m_RoomNo = _T(""); m_Schedule = _T(""); m_Capacity = 0; m_nFields = 6; //}}AFX_FIELD_INIT m_nDefaultType = snapshot; m_nParams = 1; m_strCourseIDParam = ""; } CString CSectionSet::GetDefaultConnect() { return _T("ODBC;DSN=Student Registration"); } CString CSectionSet::GetDefaultSQL() { return _T("[Section]"); } void CSectionSet::DoFieldExchange(CFieldExchange* pFX) { //{{AFX_FIELD_MAP(CSectionSet) pFX->SetFieldType(CFieldExchange::outputColumn); RFX_Text(pFX, _T("[CourseID]"), m_CourseID); RFX_Text(pFX, _T("[SectionNo]"), m_SectionNo); RFX_Text(pFX, _T("[InstructorID]"), m_InstructorID); RFX_Text(pFX, _T("[RoomNo]"), m_RoomNo); RFX_Text(pFX, _T("[Schedule]"), m_Schedule); RFX_Int(pFX, _T("[Capacity]"), m_Capacity); //}}AFX_FIELD_MAP pFX->SetFieldType(CFieldExchange::param); RFX_Text(pFX, "CourseIDParam", m_strCourseIDParam); } #ifdef _DEBUG void CSectionSet::AssertValid() const { CRecordset::AssertValid(); } void CSectionSet::Dump(CDumpContext& dc) const { CRecordset::Dump(dc); } #endif //_DEBUG coursset.h : header file class CCourseSet : public CRecordset { public: CCourseSet(CDatabase* pDatabase = NULL); DECLARE_DYNAMIC(CCourseSet) // Field/Param Data //{{AFX_FIELD(CCourseSet, CRecordset) CString m_CourseID; CString m_CourseTitle; int m_Hours; //}}AFX_FIELD // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CCourseSet) public: virtual CString GetDefaultConnect(); // Default connection string virtual CString GetDefaultSQL(); // Default SQL for Recordset virtual void DoFieldExchange(CFieldExchange* pFX); // RFX support //}}AFX_VIRTUAL // Implementation #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif }; /// coursset.cpp : implementation file #include "stdafx.h" #include "enroll.h" #include "coursset.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif IMPLEMENT_DYNAMIC(CCourseSet, CRecordset) CCourseSet::CCourseSet(CDatabase* pdb) : CRecordset(pdb) { //{{AFX_FIELD_INIT(CCourseSet) m_CourseID = _T(""); m_CourseTitle = _T(""); m_Hours = 0; m_nFields = 3; //}}AFX_FIELD_INIT } CString CCourseSet::GetDefaultConnect() { return _T("ODBC;DSN=Student Registration;"); } CString CCourseSet::GetDefaultSQL() { return _T("COURSE"); } void CCourseSet::DoFieldExchange(CFieldExchange* pFX) { //{{AFX_FIELD_MAP(CCourseSet) pFX->SetFieldType(CFieldExchange::outputColumn); RFX_Text(pFX, "CourseID", m_CourseID); RFX_Text(pFX, "CourseTitle", m_CourseTitle); RFX_Int(pFX, "Hours", m_Hours); //}}AFX_FIELD_MAP } #ifdef _DEBUG void CCourseSet::AssertValid() const { CRecordset::AssertValid(); } void CCourseSet::Dump(CDumpContext& dc) const { CRecordset::Dump(dc); } #endif //_DEBUG // EnrolDoc.h : interface of the CEnrollDoc class class CEnrollDoc : public CDocument { protected: // create from serialization only CEnrollDoc(); DECLARE_DYNCREATE(CEnrollDoc) // Attributes public: CSectionSet m_sectionSet; CCourseSet m_courseSet; // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CEnrollDoc) public: virtual BOOL OnNewDocument(); //}}AFX_VIRTUAL // Implementation public: virtual ~CEnrollDoc(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif protected: // Generated message map functions protected: //{{AFX_MSG(CEnrollDoc) // NOTE - the ClassWizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_MSG DECLARE_MESSAGE_MAP() }; EnrolDoc.cpp : implementation of the CEnrollDoc class #include "Stdafx.h" #include "Enroll.h" #include "SectSet.h" #include "CoursSet.h" #include "EnrolDoc.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif IMPLEMENT_DYNCREATE(CEnrollDoc, CDocument) BEGIN_MESSAGE_MAP(CEnrollDoc, CDocument) //{{AFX_MSG_MAP(CEnrollDoc) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG_MAP END_MESSAGE_MAP() CEnrollDoc::CEnrollDoc() { // TODO: add one-time construction code here } CEnrollDoc::~CEnrollDoc() {} BOOL CEnrollDoc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE; return TRUE; } #ifdef _DEBUG void CEnrollDoc::AssertValid() const { CDocument::AssertValid(); } void CEnrollDoc::Dump(CDumpContext& dc) const { CDocument::Dump(dc); } #endif //_DEBUG SectForm.h : interface of the CSectionForm class class CSectionSet; class CSectionForm : public CRecordView { protected: // create from serialization only CSectionForm(); DECLARE_DYNCREATE(CSectionForm) public: //{{AFX_DATA(CSectionForm) enum{ IDD = IDD_ENROLL_FORM }; CEdit m_ctlSection; CComboBox m_ctlCourseList; CSectionSet* m_pSet; //}}AFX_DATA // Attributes public: CEnrollDoc* GetDocument(); protected: BOOL m_bAddMode; // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CSectionForm) public: virtual CRecordset* OnGetRecordset(); virtual BOOL PreCreateWindow(CREATESTRUCT& cs); virtual BOOL OnMove(UINT nIDMoveCommand); protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support virtual void OnInitialUpdate(); // called first time after construct virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); //}}AFX_VIRTUAL // Implementation public: virtual ~CSectionForm(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif protected: // Generated message map functions protected: //{{AFX_MSG(CSectionForm) afx_msg void OnSelendokCourselist(); afx_msg void OnRecordAdd(); afx_msg void OnRecordDelete(); afx_msg void OnRecordRefresh(); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; #ifndef _DEBUG // debug version in SectForm.cpp inline CEnrollDoc* CSectionForm::GetDocument() { return (CEnrollDoc*)m_pDocument; } #endif SectForm.cpp : implementation of the CSectionForm class #include "stdafx.h" #include "Enroll.h" #include "SectSet.h" #include "CoursSet.h" #include "EnrolDoc.h" #include "SectForm.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif IMPLEMENT_DYNCREATE(CSectionForm, CRecordView) BEGIN_MESSAGE_MAP(CSectionForm, CRecordView) //{{AFX_MSG_MAP(CSectionForm) ON_CBN_SELENDOK(IDC_COURSELIST, OnSelendokCourselist) ON_COMMAND(ID_RECORD_ADD, OnRecordAdd) ON_COMMAND(ID_RECORD_DELETE, OnRecordDelete) ON_COMMAND(ID_RECORD_REFRESH, OnRecordRefresh) //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CRecordView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CRecordView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CRecordView::OnFilePrintPreview) END_MESSAGE_MAP() CSectionForm::CSectionForm() : CRecordView(CSectionForm::IDD) { //{{AFX_DATA_INIT(CSectionForm) m_pSet = NULL; //}}AFX_DATA_INIT m_bAddMode = FALSE; } CSectionForm::~CSectionForm() {} void CSectionForm::DoDataExchange(CDataExchange* pDX) { CRecordView::DoDataExchange(pDX); //{{AFX_DATA_MAP(CSectionForm) DDX_Control(pDX, IDC_COURSELIST, m_ctlCourseList); DDX_FieldText(pDX, IDC_SECTION, m_pSet->m_SectionNo, m_pSet); DDX_Control(pDX, IDC_SECTION, m_ctlSection); DDX_FieldText(pDX, IDC_INSTRUCTOR, m_pSet->m_InstructorID, m_pSet); DDX_FieldText(pDX, IDC_ROOM, m_pSet->m_RoomNo, m_pSet); DDX_FieldText(pDX, IDC_SCHEDULE, m_pSet->m_Schedule, m_pSet); DDX_FieldText(pDX, IDC_CAPACITY, m_pSet->m_Capacity, m_pSet); DDX_FieldCBString(pDX, IDC_COURSELIST, m_pSet->m_CourseID, m_pSet); //}}AFX_DATA_MAP } BOOL CSectionForm::PreCreateWindow(CREATESTRUCT& cs) { return CRecordView::PreCreateWindow(cs); } void CSectionForm::OnInitialUpdate() { m_pSet = &GetDocument()->m_sectionSet; // Fill the combo box with all of the courses CEnrollDoc* pDoc = GetDocument(); pDoc->m_courseSet.m_strSort = "CourseID"; if (!pDoc->m_courseSet.Open()) return; // Filter, parameterize and sort the course recordset m_pSet->m_strFilter = "CourseID = ?"; m_pSet->m_strCourseIDParam = pDoc->m_courseSet.m_CourseID; m_pSet->m_strSort = "SectionNo"; m_pSet->m_pDatabase = pDoc->m_courseSet.m_pDatabase; CRecordView::OnInitialUpdate(); m_ctlCourseList.ResetContent(); if (pDoc->m_courseSet.IsOpen()) { while (!pDoc->m_courseSet.IsEOF()) { m_ctlCourseList.AddString(pDoc->m_courseSet.m_CourseID); pDoc->m_courseSet.MoveNext(); } } m_ctlCourseList.SetCurSel(0); } BOOL CSectionForm::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } void CSectionForm::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add extra initialization before printing } void CSectionForm::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add cleanup after printing } #ifdef _DEBUG void CSectionForm::AssertValid() const { CRecordView::AssertValid(); } void CSectionForm::Dump(CDumpContext& dc) const { CRecordView::Dump(dc); } CEnrollDoc* CSectionForm::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CEnrollDoc))); return (CEnrollDoc*)m_pDocument; } #endif //_DEBUG CRecordset* CSectionForm::OnGetRecordset() { return m_pSet; } void CSectionForm::OnSelendokCourselist() { if (!m_pSet->IsOpen()) return; m_ctlCourseList.GetLBText(m_ctlCourseList.GetCurSel(), m_pSet->m_strCourseIDParam); if (!m_bAddMode) { m_pSet->Requery(); if (m_pSet->IsEOF()) { m_pSet->SetFieldNull(&(m_pSet->m_CourseID), FALSE); m_pSet->m_CourseID = m_pSet->m_strCourseIDParam; } UpdateData(FALSE); } } void CSectionForm::OnRecordAdd() { // If already in add mode, then complete previous new record if (m_bAddMode) OnMove(ID_RECORD_FIRST); CString strCurrentCourse = m_pSet->m_CourseID; m_pSet->AddNew(); m_pSet->SetFieldNull(&(m_pSet->m_CourseID), FALSE); m_pSet->m_CourseID = strCurrentCourse; m_bAddMode = TRUE; m_ctlSection.SetReadOnly(FALSE); UpdateData(FALSE); } void CSectionForm::OnRecordDelete() { TRY { m_pSet->Delete(); } CATCH(CDBException, e) { AfxMessageBox(e->m_strError); return; } END_CATCH // Move to the next record after the one just deleted m_pSet->MoveNext(); // If we moved off the end of file, then move back to last record if (m_pSet->IsEOF()) m_pSet->MoveLast(); // If the recordset is now empty, then clear the fields // left over from the deleted record if (m_pSet->IsBOF()) m_pSet->SetFieldNull(NULL); UpdateData(FALSE); } void CSectionForm::OnRecordRefresh() { if (m_bAddMode == TRUE) { m_pSet->Move(AFX_MOVE_REFRESH); m_ctlSection.SetReadOnly(TRUE); m_bAddMode = FALSE; } // Copy fields from recordset to form, thus // overwriting any changes user may have made // on the form UpdateData(FALSE); } BOOL CSectionForm::OnMove(UINT nIDMoveCommand) { if (m_bAddMode) { if (!UpdateData()) return FALSE; TRY { m_pSet->Update(); } CATCH(CDBException, e) { AfxMessageBox(e->m_strError); return FALSE; } END_CATCH m_pSet->Requery(); UpdateData(FALSE); m_ctlSection.SetReadOnly(TRUE); m_bAddMode = FALSE; return TRUE; } else { return CRecordView::OnMove(nIDMoveCommand); } } |
四、小结
由于ODBC数据库编程是学习DAO、ADO等数据库编程的基础,所以上文用了大量的篇幅,详细介绍了ODBC数据库编程所涉及到的一些基础知识,并通过一个具体的实例,实现了对数据库中的两个表的关联操作,读者朋友可以将文章和代码结合起来学习,慢慢的体会,相信可以从中学习到很多数据编程的应用技巧。
这篇关于上一篇的续集,另一个人写的,请原谅到底是谁写的我不知道,感谢原创人的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!