The EX31A Program Elements

Let's take a look at the major elements in the EX31A program.

Connecting the Recordset Class to the Application

When ClassWizard generates the CEx31aSet class, it adds the CPP and H files to the project—and that's all it does. It's up to you to link the recordset to your view and to your document. By embedding a CEx31aSet object inside the CEx31aDoc class, you ensure that the recordset object will be constructed when the application starts.

The view could always get the recordset from the document, but it's more efficient if the view has its own recordset pointer. Notice how the view's OnInitialUpdate function sets the m_pSet data member.

If you run AppWizard with either of the Database View options, AppWizard generates a class derived from CRecordset, a class derived from CRecordView (for ODBC), and all the necessary linkage as just described. We're not using AppWizard in this mode because we don't want a form-based application.

The CEx31aView Class's OnInitialUpdate Member Function

The job of the CEx31aView::OnInitialUpdate function is to open the recordset that's associated with the view. The recordset constructor was called with a NULL database pointer parameter, so the CRecordset::Open function knows it must construct a CDatabase object and link that database one to one with the recordset. But how does Open know what data source and table to use? It calls two CRecordset virtual functions, GetDefaultConnect and GetDefaultSQL. ClassWizard generates implementations of these functions in your derived recordset class, as shown here:

CString CEx31aSet::GetDefaultConnect() {     return _T("ODBC;DSN=Student Registration"); } CString CEx31aSet::GetDefaultSQL() {     return _T("[Student]"); }

ClassWizard and AppWizard place brackets around all column and table [names]. These brackets are necessary only if the names contain embedded blanks.

GetDefaultSQL is a pure virtual function, so the derived class must implement it. GetDefaultConnect, on the other hand, has a base class implementation that opens an ODBC dialog box, which in turn prompts the user for the data source name.

Because documents and views are reused in SDI applications, the OnInitialUpdate function must close any open recordset before it opens a new recordset. The CRecordSet::IsOpen member function is used to test this.

The CEx31aView Class's OnDraw Member Function

As in any document_view application, the CEx31aView::OnDraw function is called every time the view is invalidated and once for every printed page. Here OnDraw inefficiently slogs through every row in the recordset and paints its column values with the CDC::TextOut function. The principal CRecordset member functions it calls are MoveFirst and MoveNext. MoveFirst will fail if the recordset is empty, so the initial call to CRecordset::IsBOF is necessary to detect the beginning-of-file condition. The CRecordset::IsEOF call detects the end-of-file condition for the recordset and terminates the row loop.

Remember that ClassWizard generated CEx31aSet class data members for the recordset's columns. This means that the recordset class and now the view class are both hard-coded for the student record. The CRecordset member functions call a pure virtual function, DoFieldExchange, that ClassWizard generates based on the data members m_StudentID, m_Name, and m_GradYear. Here is the code for this example's derived recordset class:

void CEx31aSet::DoFieldExchange(CFieldExchange* pFX) {     //{{AFX_FIELD_MAP(CEx31aSet)     pFX->SetFieldType(CFieldExchange::outputColumn);     RFX_Long(pFX, _T("[StudentID]"), m_StudentID);     RFX_Text(pFX, _T("[Name]"), m_Name);     RFX_Int(pFX, _T("[GradYear]"), m_GradYear);     //}}AFX_FIELD_MAP }

Each SQL data type has a record field exchange (RFX) function. RFX functions are quite complex and are called many times during database processing. You might think at first that the RFX functions are like the CDialog DDX functions and thus actually transfer data between the database and the data members. This is not the case. The primary purpose of the RFX functions is to bind the database columns to the data members so that the underlying ODBC functions, such as SQLExtendedFetch, can transfer the column data. To this end, the DoFieldExchange function is called from CRecordSet::Open. DoFieldExchange is also called by the Move functions for the purpose of reallocating strings and clearing status bits.

Because the DoFieldExchange function is so tightly integrated with MFC database processing, you are advised not to call this function directly in your programs.



Programming Visual C++
Advanced 3ds max 5 Modeling & Animating
ISBN: 1572318570
EAN: 2147483647
Year: 1997
Pages: 331
Authors: Boris Kulagin

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net