Learn an Enroll routine

xiaoxiao2021-03-06  63

Learn an Enroll routine

Visual C provides an example called Enroll as a tutorial for learning MFC database programming. Enroll is divided into four steps. This section is to guide the reader to complete the first three steps of Enroll routines and make more thorough analysis. By studying these three-step routines, the reader will master the method of creating an MFC database application with AppWizard and ClassWizard.

When you start learning the Enroll routine, readers may feel easy to create database applications with AppWizard, and don't use the contents of the previous sessile. It is true that AppWizard automatically joins many code-related code to the application, greatly simplifies the development of database applications. But AppWizard is not universal, and its established database applications often do not meet the needs of users. Users really want to know how to write their own database applications without relying on AppWizard, which is also the purpose of this chapter. In fact, the analysis of the previous section and the analysis of the Enroll routine is for this purpose.

Before learning ENROLL, readers are first copied from the Visual C 5.0 disc that copied Enroll on the first three steps to the hard disk for reference. In addition, Enroll is to use the Access database stdred32.mdb, which in the STDREG routine of the VC5.0 (in the Samples / MFC / Database / STDREG directory), readers to copy the example to the hard disk.

10.7.1 Register data source

The ODBC application cannot use the database directly, and the user must register the data source for the database you want to use. The work of the registration data source is complete by the ODBC Manager, which is located within 32-bit ODBCs of the Windows 95 Control Panel. Let us register the data source for the Access database stdreg32.mdb.

Open the control panel, double-click the "32-bit ODBC" icon, will display an "ODBC Data Source Manager" as shown in Figure 10.5. Select the "User DSN" page in the manager, the user DSN is only visible to the user and can only be used by the user.

Figure 10.5 ODBC Data Source Manager

Click the "Add" button to pop up a "Create New Data Source" dialog box. Select Microsoft Access Driver (*. MDB) in this dialog and press the completion button. Next, an ODBC Microsoft Access 97 Setup dialog is displayed, as shown in Figure 10.6, which is used to connect the database with a data source name. Enter the Student Registration in the Data Source Name: Bar, then click the Select ... button to find and select stdreg32.mdb in the subsequent dialog box. After connecting two OK buttons, a new data source named Student Registration is registered in the manager.

Figure 10.6 ODBC Microsoft Access 97 Setup dialog

Tip: If you want to register the data source for the DBASE or FoxPro database, you should select a directory instead of a file as a data source. This is because in Access, an MDB file can contain multiple tables, so you can think that an MDB file is a database. In DBASE or FOXPRO, a DBF file can only correspond to a table, and a database may contain several DBF files, so you can think that a directory containing several DBF files is a database.

10.7.2 The first version of Enroll ENROLL The first version of ENROLL is shown in Figure 10.3, which has the two basic functions of the browsing record set and modify the record. After modifying the records in the form, you can save your changes to the original record on a new record. Note that the Course and Section editing boxes in the form are read-only because the contents of these two fields are more important, and the user cannot modify. Enroll uses stdreg32.mdb's section table, which is a curriculum, which is shown in Table 10.2. Let us now build an Enroll application. First, use AppWizard to complete the establishment of the Enroll program framework, please read by: Start AppWizard, specify a MFC project called Enroll. Select Single Document in the first step in MFC AppWizard. In the second step in the MFC AppWizard, select the Database View WITHOUT FILE Support, then click the Data Source ... button to select the Student Registration data source in the ODBC combo box in the Database Options dialog, as shown in Figure 10.7. Then press the "OK" button, open a Select Database Table dialog as shown in Figure 10.8. Select the section table in this dialog. Press the OK button to exit. In the sixth step of the MFC AppWizard, the class cenrollset is renamed CsectionSet, and the CSECTIONFORM is changed to Csectionform. Press the Finish button to establish an Enroll project.

Figure 10.7 Database Options Dialog Figure 10.8 Select Database Table dialog Opens the class view of the workspace, you can find that AppWizard automatically creates a record category CsectionSet and a recorded view class Csectionform, which is Crecordset and CRecordView derived class. AppWizard also automatically creates a domain data member for the CSECTIONSET class. Open the resource view of the workspace, the reader is not difficult to find a dialog template for IDD_ENROLL_FORM, which will be recorded to display the form. Clear all the controls in the template and enlarge the size of the template to 183 × 110, then place the control according to the model of Figure 10.3. Here you can take a lazy way: Open the first version of the first version of the VC5.0 Enroll (Enroll.rc), find and open the IDD_ENROLL_FORM dialog template, hold down the Ctrl key and use the mouse to select all controls in the template , Then press the CTRL INSERT key to copy the selected control. Switch to your own IDD_ENROLL_FORM dialog template, then press the SHIFT INSERT button to paste the control you just copied into the template. The next task is to connect the controls in the form to the recorded domain data member with ClassWizard to implement the control with the current recorded DDX data exchange. Readers Please follow the steps below:

Enter ClassWizard and select the Member Variables page and select the CSECTIONFORM class. Double-click the IDC_Capacity item in the variable list, the Add MEMBER Variable dialog is displayed. Note that the MEMBER VARIABLE NAME bar of the dialog is displayed in a combo box instead of the original edit box. As shown in Figure 10.9, select m_pset-> m_capacity in the list of combo boxes. Press the OK button to confirm. In step 2, the domain data member of the record set is connected to other controls. Based on the ID of the control, it is not difficult to determine the corresponding domain data member.

Figure 10.9 ADD MEMBER VARIABLE dialog You can find the following line within the definition of the CSECTIONForm class: CsectionSet * m_pset; Visible m_pset is a member of the CSECTIONFORM class, which points to a CsectionSet object. Use ClassWizard to connect the control with the "external data" such as the image recordset, which is a special application in the database programming in database. Compile and run Enroll, readers will be surprised to find that Enroll is actually a quite a good record browser and the user can modify the record. Now let's analyze what kind of things you have for AppWizard and ClassWizard for Enroll. In the definition of document class CenrollDoc, there is a row: CsectionSet m_sectionSet; Visible AppWizard embeds a CsectionSet object in the CenrollDoc class. This is equivalent to calling the constructor CsectionSet (NULL), the declaration of the constructor of the CSECTIONSET class is as follows: CsectionSet (CDATABASE * PDATABASE = NULL); the definition of the function is listed in Listing 10.5. It can be seen that the constructor calls the constructor of the base class and initializes the domain data. Through 10.5.4 We know, if the NULL parameter is delivered to the CRecordset constructor, the CRecordset :: Open function will automatically build a CDATABASE object and establish a connection to the data source according to the connection string returned by CRecordset :: getDefaultConnect. CsectionSet provides a new version of the virtual function getDefaultConnect, as shown in Listing 10.6, providing a data source Student Registration in this function. Listing 10.5 Constructor of CsectionSet

CsectionSet :: CsectionSet: 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;}

Listing 10.6 GetDefaultConnect functions for derived class

CString CsectionSet :: getDefaultConnect () {return _t ("odbc; dsn = student registration);

As for the establishment of the recordset, it is actually done in CRecordView :: OnInitialUpdate, this part of the code is transparent to the user, here is listed in Listing 10.7. Call CRecordset :: Open in this function to establish records. The ONGETRECORDSET function is called at the beginning of the function to obtain record set objects connected to the recording view. CsectionForm provides a new version of the virtual function online, as shown in Listing 10.8, which submits the m_pset to the caller. As for the initialization of m_pset, it is done in the CSECTIONFORM :: OnInitialUpdate function, as shown in Listing 10.9.

Listing 10.7 CRecordView :: onInitialUpdate function

void CRecordView :: OnInitialUpdate () {CRecordset * pRecordset = OnGetRecordset (); // recordset must be allocated already ASSERT (pRecordset = NULL!); if {CWaitCursor wait (pRecordset-> IsOpen ()!); pRecordset-> Open ( }

CFORMVIEW :: OnInitialupdate ();

Listing 10.8 Distribute class ONGETRECORDSET functions

CRecordset * csectionform :: online {return m_pset;}

Listing 10.9 Repaying the onInitialUpdate function

Void csectionform :: onInitialupdate () {m_pset = & getDocument () -> m_sectionSet; CRecordView :: oninitialupdate ();

Note that any parameters are not provided in CRecordView :: OnInitialUpdate, this means that the Open function will get SQL information from CRecordset :: getDefaultsql. CsectionSet provides a new version of the virtual function getDefaultsql, as shown in Listing 10.10, which returns the "section" table name.

Listing 10.10 GetDefaultsql function for derived class

CString CsectionSet :: getDefaultsql () {return _t ("[section]");}

For the implementation of the scrolling and modification of the record, please see 10.6. The code related to DDX and DFX has been listed in Listing 10.3 and 10.2.

If the reader does not understand the above analysis, then please read it again in the first few sections of this chapter.

10.7.3 ENROLL's second version

The second version of Enroll demonstrates the readers to use two associated record sets in a record view, as well as recorded filtering and sorting technology, which makes readers really touch the relational database. This section will also describe how to use ClassWizard to create records, and methods of parameterized record sets.

Readers can first run the second step of the Enroll example provided by VC 5.0. The interface of the Enroll has a change, and the original Course edit box is replaced with a combo box, as shown in Figure 10.10. The contents of the combo box come from another table Course of the same data source.

Figure 10.10 ENROLL second version

The content of the Course table is shown in Table 10.5, with table 10.2, the reader can find that the Course table and the section table have a public field courseid. The recording view program is using this public field to link two tables. For example, when a user selects Math202 in the Course Combination box, the program will select all CourseIDs in the section table to record and establish a new recordset.

In fact, most of STDREG32.MDB share CourseId. In the primary table COURSE table, each recorded courseid is unique, we call it a primary key. In Course's related tables, CourseId is not necessarily unique, such as section table, we call CourseId in the relevant table for Foreign Key. You can contact multiple tables through the keyword, such a database is a relational database. SectionNo is also a keyword. In the section table, the SectioInno field is the primary keyword, and its value is unique.

Table 10.5 Course Table Courseid (Text) CourseTitle (Text) Hours (int) Math101 Algebra 4 Math201 Calculus I 4 Math202 Calculus II 4

Let us start to make new versions on the basis of the previous section Enroll. If the current project is not Enroll, readers will open the Enroll project created on the previous section.

First, replace the Course edit box to the combo box, including the following steps:

Open the IDD_ENROLL_FORM dialog template and remove the Course edit box.

Add a combo box in the position of the original edit box. Open the property dialog for this control, make your ID to IDC_COURSELIST, and select Drop List in the Styles page. Note To properly adjust the drop-down list size of the combo box (to enlarge its size after tap the downward arrow).

Since the top to the new arrangement of Tab.

Next, use ClassWizard to do some work related to the new combo box:

Enter ClassWizard and select the MEMBER VARIABLES page and select the CSECTIONFORM class. Click the IDC_COURSE item in the list and press the DELETE button to delete the item. Then double-click the IDC_COURSELIST item, select m_pset-> m_courseid in the combo box of the Add MEMBER VARIABLE dialog.

Double-click IDC_CourseList again and join a CCOMBOBOX class member called M_CTLCourseList for the CSECTIONFORM class.

Select the Message Maps page, add the CBN_SELENDOK notification message processing function for the IDC_COURSELIST Combination box, and the function is nameledokcourseList. This function is responsible for responding to changes in the combination box.

Press the OK button to exit the ClassWizard.

Then, you need to create a recordset called CCOURSESET for the courte table. This work can be done by ClassWizard, please follow the steps below:

Enter ClassWizard, click the Add Class ... button and select New ... in the pop-up ..., enter the ccourseSet in the name column in the Create New Class dialog box, select CRecordset in the base class box, press the CREATE button.

In the pop-up Database Options dialog box, select the Student Registration data source in the ODBC combo box. Then press the OK button.

Select the Course table in the SELECT DATABASE TABLES dialog box that pops up. Press OK to confirm.

Look at the new CCOURSESET class, the reader will find that the ClassWizard automatically creates domain data members corresponding to the fields of the Course table, and establishes a DofieldExchange function. ClassWizard also provides new getDefaultConnect and getDefaultsql functions for records.

Next, in the definition of the CenrollDoc class, the M_SEctionSet member is followed, and the following line is added:

CCOURSESET M_COURSESET;

Such cenrolldoc contains two records. Since the CenrollDoc class uses the CCOURSESET class, you must add the following include statement in front of the #include "enroldoc.h" statement in all CPP files containing the #include "enroldoc.h" statement. These CPP files include Cenrollapp, CsectionForm, and CPP files in CenrollDoc class.

#include "coursetet.h"

In the definition of the CSECTIONSET class, the following line is added to the domain data member, add the following line outside the "//}} AFX_Field" comment. CString M_STRCOURSEIDPARAM;

M_STRCOURSEIDPARAM is a parameter data member of the record set, and its role will be described later.

Finally, readers will modify the program by Listing 10.11 and 10.12. Listing 10.11 is listed in the partial source code for the CSECTIONSET class, and Listing 10.12 is listed in the CsectionForm class part of the CSECTIONFORM class.

Listing 10.11 Partial code for CsectionSet classes

CsectionSet :: CsectionSet: CRecordset (PDB) {..

m_nparams = 1; // Only one parameter data member

M_STRCOURSEIDPARAM = "";

Void CsectionSet :: DofieldExchange (cfieldexchange * pfx) {.. Pfx-> setfieldtype (cfieldexchange :: param);

RFX_Text (PFX, "CourseidParam", M_STRCOURSEIDPARAM); // Replace parameters

}

Listing 10.12 Partial code for CsectionForm class

Void csectionform :: onInitialupdate () {m_pset = & getdocument () -> m_sectionSet;

CenrollDoc * pdoc = getDocument (); pdoc-> m_courseset.m_strsort = "courseid"; if (! Pdoc-> m_courseetet.open ()) return; m_pset-> m_strfilter = "courseid =?"; // Use parameter m_pset- > m_strcourseidparam = pdoc-> m_coursesetet.m_courseId; m_pset-> m_strsort = "sectionno";

m_pset-> m_pdatabase = pdoc-> m_courseset.m_pdatabase; // Share CDATABASE

CRecordView :: OnInitialupdate ();

m_ctlcourseList.resetContent (); if (pdoc-> m_courseset.isopen ()) {while (! pdoc-> m_courseset.iseof ()) {m_ctlcourselist.addstring (pdoc-> m_courseset.m_course); // Add CourseID to the table Field pdoc-> m_courseset.movenext ();}}

m_ctlcourselist.setcursel (0);

Void csectionform :: overselendokcourselist () {

IF (! m_pset-> isopen ()) return; m_ctlcourselist.getlbtext (m_ctlcourselist.getcurseel (), m_pset-> m_strcourseidparam); m_pset-> requery (); // Re-query if (m_pset-> ISEOF ()) {m_pset -> setfieldnull (& (m_pset-> m_course), false); m_pset-> m_course = m_pset-> m_strcourseidparam;}

Updatedata (false);} At the beginning of the csectionform :: OnInitialUpdate function, CRECORDSET :: Open is called to establish a CCOURSESET recordset. Before calling the Open function, specify the sequencing record set according to the CoursEID field. Some of the pre-consequences of calling the Open function have been explained earlier, readers should be difficult to analyze. The next code reader may not understand, why will there be a "?" Number in the M_STRFILTER filter string of the record set.

This is because "Parameterized Recording Set" technology is used in this example. In the m_strfilter and m_strsort of the record set, you can use "?" As parameters, which can be more flexible when specifying filters and sorting. For example, in the OnInitialUpdate function, it specifies the filter:

m_pset-> m_strfilter = "courseid =?";

When calling Open or Requuery, "?" Will be replaced by the contents of CsectionSet :: m_STRCOURSEIDPARAM. For example, if the m_strcourseidparam is "Math101", the m_strfilter will become "courseid = Math101". This way users can customize the filter as long as the M_STRCOURSEIDPARAM is specified. Members like M_STRCOURSEIDPARAM are called parameter data members, like the same domain data, is unique to records. ClassWizard does not support parameter data members, users can only manually join, and their name is determined by the user.

The work of the parameter is actually completed by the RFX function in CsectionSet :: DofieldExchange. At the end of the DofieldExchange function, we joined the following two lines:

PFX-> setfieldType (cfieldexchange :: param); RFX_Text (PFX, "CourseidParam", M_STRCOURSEIDPARAM);

DofieldExchange can identify domain data members and parameter data members. The first line call is used to indicate that the subsequent RFX functions are used for parameters. The second line is an RFX function for m_strcourseidparam parameters. The name of the second parameter of the RFX can be determined by the user, which is specified as "courseidparam".

Users can use one or more parameters in M_Strfilter and M_STRSORT. In the case of multiple parameters, pay attention to the call sequence of the RFX function should correspond to the order of the parameters. The framework specifies that the user should arrange parameters in the m_strfilter before it is M_STRSORT.

CRecordset has two data members m_nfields and m_nparams to count the number of domain data members and parameter data. The former is automatically counted by ClassWizard, and the latter must be maintained by the user. In the constructor of the CSECTIONSET, m_nparams is set to 1 because there is only one parameter data member.

Let us now continue to study OnInitialUpdate. There is such a line of code in the program before calling the base class for OnInitialUpdate.

m_pset-> m_pdatabase = pdoc-> m_courseset.m_pdatabase;

m_pdatabase is a public member of CRecordset, which is a pointer to the CDATABASE object. If the application uses more than two records, in the default, each recordset creates a CDatabase object representing the same data source (see 10.5.4), which is obviously not necessary. The above line of code allows the CSECTIONSET recordset to share the CDatabase object created by the CCOURSESET recordset, so that when calling CRecordView :: OpenInitialUpdate, you will not create a cdatabase object when you call CRecordView :: Open to open the CsectionSet Record Set. Next, the program adds the COURSEID field of each record of the ccourseset to the combo box.

When the user selects a new CourseID in the combo box, in Csectionform :: OnSelendokCourseList, you will set the user selected CourseID to M_STRCOURSEIDPARAM, then call CRecordset :: Requery to rest query and build records according to custom filter and sort set. If the recalled record set is empty, the record set is not NULL in the section table in the section table. In the program, CRecordset :: setfieldnull is called to set the m_courseid field to non-empty. Finally, call CRecordView :: Updatedata update the controls in the form.

It is not difficult to see from the program that the maximum benefit of using the parameterized record set is that the filter and sort can be easily specified during the program operation, which greatly improves the program's user custom query capability.

Compile and run Enroll, try newly added features.

10.7.4 ENROLL third version

The third version of Enroll supports the addition and deletion of records, which also demonstrates the processing of abnormal database. Readers first run the third step in the ENROLL program provided by VC5.0. There are three commands in the third edition Enroll's Record menu: add, delete, and refresh, they are used to add, delete, and refresh records, respectively.

When the user selects the Add command, it enters the add mode. In addition to the Course combo box, all fields are cleared. The user can enter a new recorded field value in each edit box, then move to other records, so that the new record is saved to the data source. Users can also save new records by selecting the add command again.

When the user selects the delete command, the current record is deleted and the program will automatically scroll to the next record.

Use the refresh command to discard the recorded modification or add actions, and restore the original recorded content.

Let us start to make new versions on the basis of the previous section Enroll. If the current project is not Enroll, readers will open the Enroll project created on the previous section.

First, add three menu items to the Record menu, and the properties of the menu item are listed in Table 10.6. Please add these three menu items to the beginning of the Record menu, and separated by a divider and behind.

Table 10.6

CAPTION ID PROMPT & ADD ID_RECORD_ADD Add A New Section & Refresh ID_Record_refresh Cancel Changes ON Form, or Cancel Add & Delete Id_Record_Delete delete Section

Next, create a process function with the three commands above with ClassWizard, and the function name is default. In addition, you need to write a new onmove function to the recording view to handle the scroll command, because the original ONMOVE function does not add a record function. You can find the onmove function in the Messages list of CsectionForm classes in ClassWizard, please read and create this function. When the scroll command is processed in the CSECTIONForm :: OnMove function, it is necessary to have a flag to determine if the current is in the addition mode to add a new record or regular scroll processing to the data source. Please add the following two lines in the appropriate position in the definition of the CSECTIONForm class:

Protected: BOOL M_BADDMODE;

In the first two versions of Enroll, the section edit box is read-only, but when adding a record, you must allow the user to modify the section edit box. This is because the sectionNo field is the primary keyword of the section table. Its value must be unique. If the original sectionNO field is not changed, it will result in abnormal generation due to the main keyword repeat. Obviously, we need a CEDIT object to control the IDC_SECTION edit box, please use ClassWizard to add a CSECTIONFORM class to the CEDIT-type member variable corresponding to IDC_SECTION, the name of the variable is m_ctlsection.

Finally, the reader will modify the program by Listing 10.13.

Listing 10.13 Partial source code for CsectionForm class

CsectionForm :: CSECTIONFORM (): CRecordView (csectionform :: IDd) {... M_baddmode = false;

Void CsectionForm :: OnsendokCourseList () {if (! m_pset-> iSopen ()) Return; m_ctlcourselist.getlbtext (m_ctlcourselist.getcursel (), m_pset-> m_strcourseidparam);

IF (! m_baddmode)

{m_pset-> Requory (); if (m_pset-> ityof ()) {m_pset-> setfieldnull (& (m_pset-> m_course), false); m_pset-> m_course = m_pset-> m_strcourseidparam;} Updatedata (false);

}

Void csectionform :: onRecordAdd () {

if (m_bAddMode) // if mode is added, the process of adding OnMove (ID_RECORD_FIRST); CString strCurrentCourse = m_pSet-> m_CourseID; m_pSet-> AddNew (); m_pSet-> SetFieldNull (& (m_pSet-> m_CourseID), FALSE ); m_pset-> m_course; m_baddmode = true; m_ctlsection.setReadonly (false);

Updatedata (false); // update form view

}

Void CsectionForm :: OnRecorddelete () {

Try {m_pset-> delete ();} catch (cdbexception, e) {AFXMESSAGEBOX (E-> m_strerror); return;} end_catch m_pset-> MoveNext (); // Scroll to the next record IF (m_pset-> ISEOF ))) // If rolled out the boundary of the record set, scroll to the last record m_pset-> MoveLast (); if (m_pset-> isbof ()) // If the record is empty, clear the domain data member m_pset- > Setfieldnull (null); Updatedata (false); // Update form view

}

Void csectionform :: onRecordRefresh () {

IF (m_baddmode == true) {m_pset-> move (AFX_MOVE_REFRESH); // Cancel Add mode m_ctlsection.setReadOnly (true); m_baddmode = false;}

Updatedata (false); // update form view

}

Bool Csectionform :: OnMove (uint nidmovecommand) {

IF (m_baddmode) {if (! updatedata ()) Return False; try {m_pset-> update ();} catch (cdbException, e) {afxMessageBox (e-> m_stroRROR); RETURN FALSE;} end_catch m_pset-> Requory ( ); // Re-query, make new records to users can see Updatedata (false); m_ctlsection.setreadonly; m_baddmode = false; return true;} else

{Return CRecordView :: ONMOVE (NidmoveCommand);

}

Let's first take a look at the processing function of the add command CSECTIONFORM :: OnRecordAdd function. In this function, the most important code is to call CRecordset :: AddNew into the add mode. The explanation of the remaining code is as follows:

If you have been added, CsectionForm :: OnMove is called to other records, which causes the new record to be saved to the data source. The addition operation is a common method by scrolling to another record. In fact, the default CRecordView :: OnMove can complete this feature (see 10.5.6 and 10.6), but Csectionform :: OnMove has additional consideration (see below).

Save the current recorded CourseID and use it as a default value for new records.

Call CEDIT: SETREADOONLY (false) Change the section edit box to the entered so that the user enters the new value.

CsectionForm :: OnMove is responsible for processing scroll commands. Unlike the default CRecordView :: ONMOVE function, this function addresses the scrolling in the add mode:

After calling CRecordset :: Update to save the new record to the data source, call CRecordset :: Requery Reissue Record Set. The reason for this is that Enroll uses a snapshot record set. The snapshot does not reflect the record of the user, so it is necessary to call the Requery to re-query to include the new record. After calling ReQuery, it will automatically scroll to the first record, so scrolling records in the add mode always scroll into the first record.

When CRecordset :: Update is called, the possible abnormality is processed. Abnormal information will be output directly here.

After calling Requery, you want to call CRecordView :: Updatedata (false) to update your form and call Cedit :: SetReadOnly (true) to make the SectioIn editing box into read-only. CrecordSet :: delete calls CRecordset :: delete to delete records in the processform :: delete of the delete command. After calling Delete, scroll into the new location to skip the deleted record.

The processing function of the refresh command csectionform :: onRefresh is used to give up the modification or add a record. The interpretation of this function is:

If the current is currently added, CRECORDSET:: Move (AFX_MOVE_REFRESH) cancels the add mode and restores the original value of the domain data member (see 10.5.6), set the section edit box to read-only.

Call CRecordView :: Updatedata (false) Recovered records in the form view.

The CSECTIONForm :: overselendokcourseList function is used to determine if the current is in the addition mode. If you are in an add mode, you cannot call the Requery to re-query because the role of the Course combo box is only allowing the user to select a field value, not a specified filter.

Compile and run Enroll, try newly added features.

转载请注明原文地址:https://www.9cbs.com/read-84773.html

New Post(0)