⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vcg14.htm

📁 Visual C++与数据库的连接经典实例
💻 HTM
📖 第 1 页 / 共 5 页
字号:

<B>            return FALSE;</B>

<B>        }</B>

<B>        try</B>

<B>        {// Hope it works...</B>

<B>            pRecordset-&gt;Update();</B>

<B>        }</B>

<B>        catch (CDaoException* e)</B>

<B>        {// ...but if it doesn't...</B>

<B>            AfxMessageBox(e-&gt;m_pErrorInfo-&gt;m_strDescription);</B>

<B>            e-&gt;Delete();</B>

<B>            return FALSE;</B>

<B>        }</B>

<B>        pRecordset-&gt;Requery();</B>

<B>        UpdateData(FALSE);</B>

<B>        m_bAddMode = FALSE;</B>

<B>        return TRUE;</B>

<B>    }</B>

<B>    else</B>

<B>    {// If not adding records, just move around:</B>

<B>        return CDaoRecordView::OnMove(nIDMoveCommand);</B>

<B>    }</B>

}

void CAddressesView::OnRecordAdd()

{

    // TODO: Add your command handler code here

<B>    // If already in add mode, complete previous new record add:</B>

<B>    if (m_bAddMode)</B>

<B>    {// If adding, first add the current record:</B>

<B>        OnMove(ID_RECORD_FIRST);</B>

<B>    }</B>

<B>    // Switch into the Add mode (even if already adding):</B>

<B>    OnGetRecordset()-&gt;AddNew();</B>

<B>    m_bAddMode = TRUE;</B>

<B>    UpdateData(FALSE);</B>

<B>    return;</B>

}

void CAddressesView::OnRecordDelete()

{

    // TODO: Add your command handler code here

<B>    CDaoRecordset* pRecordset = OnGetRecordset();</B>

<B>    try</B>

<B>    {// It better work...</B>

<B>        pRecordset-&gt;Delete();</B>

<B>    }</B>

<B>    catch (CDaoException* e)</B>

<B>    {// ...but if it didn't...</B>

<B>        AfxMessageBox(e-&gt;m_pErrorInfo-&gt;m_strDescription);</B>

<B>        e-&gt;Delete();</B>

<B>        return;</B>

<B>    }</B>

<B>    // Move to the next record after the one just deleted</B>

<B>    pRecordset-&gt;MoveNext();</B>

<B>    // Ensure that the move is valid:</B>

<B>    if (pRecordset-&gt;IsEOF())</B>

<B>    {</B>

<B>        pRecordset-&gt;MoveLast();</B>

<B>    }</B>

<B>    if (pRecordset-&gt;IsBOF())</B>

<B>    {</B>

<B>        pRecordset-&gt;SetFieldNull(NULL);</B>

<B>    }</B>

<B>    UpdateData(FALSE);</B>

<B>    return;</B>

}

void CAddressesView::OnRecordRefresh()

{

    // TODO: Add your command handler code here

<B>    if (m_bAddMode)</B>

<B>    {// Was the user adding a record? If so, exit add mode.</B>

<B>        try</B>

<B>        {// It better work...</B>

<B>            OnGetRecordset()-&gt;CancelUpdate();</B>

<B>            OnGetRecordset()-&gt;Move(0);</B>

<B>        }</B>

<B>        catch (CDaoException* e)</B>

<B>        {// ...but if it didn't...</B>

<B>            AfxMessageBox(e-&gt;m_pErrorInfo-&gt;m_strDescription);</B>

<B>            e-&gt;Delete();</B>

<B>            return;</B>

<B>        }</B>

<B>        m_bAddMode = FALSE;</B>

<B>    }</B>

<B>    // Restore the user's original values (as necessary):</B>

<B>    UpdateData(FALSE);</B>

<B>    return;</B>

}</FONT></PRE>

<P>To manage the process of record addition, you must add a flag to your view class. I've used a Boolean variable called m_bAddMode, which is set to TRUE whenever the user is adding a new record to the database. This variable is initialized in the constructor to FALSE.

<BR>

<P>In addition to the code to manage the three new functions (add, delete, and refresh), you also must add code to manage the task of record navigation. This is necessary because if the user starts to add a new record and then selects one of the record navigation functions (next, previous, first, or last record), you must add the new record before you perform the navigation action requested by the user.

<BR>

<P>You do this using the add record flag m_bAddMode, which, if TRUE, tells you that a record is being added. When you're in add mode, you must save the record being added (if the database supports updating&#151;that is, if it isn't read-only). The record is saved using the CDaoRecordset::Update() function (use exception handling to catch errors), which will add the current record to the database. Once the database has been updated, it is then requeried, the view is updated, and you return.

<BR>

<P>If the user isn't currently in the add record mode, you simply do the necessary move using the default CDaoRecordView::OnMove(nIDMoveCommand) handler:

<BR>

<PRE>

<FONT COLOR="#000080"><B>CDaoRecordset* pRecordset = OnGetRecordset();</B>

<B>if (m_bAddMode)</B>

<B>{// Do special handling if you are adding records:</B>

<B>    if (!UpdateData())</B>

<B>    { // Could not get updated data from input dialog:</B>

<B>        return FALSE;</B>

<B>    }</B>

<B>    try</B>

<B>    {// Hope it works...</B>

<B>        pRecordset-&gt;Update();</B>

<B>    }</B>

<B>    catch (CDaoException* e)</B>

<B>    {// ...but if it doesn't...</B>

<B>        AfxMessageBox(e-&gt;m_pErrorInfo-&gt;m_strDescription);</B>

<B>        e-&gt;Delete();</B>

<B>        return FALSE;</B>

<B>    }</B>

<B>    pRecordset-&gt;Requery();</B>

<B>    UpdateData(FALSE);</B>

<B>    m_bAddMode = FALSE;</B>

<B>    return TRUE;</B>

<B>}</B>

<B>else</B>

<B>{// If not adding records, just move around:</B>

<B>    return CDaoRecordView::OnMove(nIDMoveCommand);</B>

<B>}</B></FONT></PRE>

<P>The add record handler checks the add flag. If the user is already in the add record mode, it adds the current record and then prepares for a new added record. A user who needs to add several records would simply select add prior to each record to be added:

<BR>

<PRE>

<FONT COLOR="#000080"><B>if (m_bAddMode)</B>

<B>{// If adding, first add the current record:</B>

<B>    OnMove(ID_RECORD_FIRST);</B>

<B>}</B>

<B>// Switch into the Add mode (even if already adding):</B>

<B>OnGetRecordset()-&gt;AddNew();</B>

<B>m_bAddMode = TRUE;</B>

<B>UpdateData(FALSE);</B>

<B>return;</B></FONT></PRE>

<P>Deleting records is straightforward. You call the recordset's delete member function, which should delete the current record (if there is one). Next you must move to the next record (giving the user something to look at). Moving to the next record presents a problem, because the application must compute which record is next. The user could have deleted the last record (then the application must move back one record). Also, the application must handle the situation that arises when the user deletes all the records in the database:

<BR>

<PRE>

<FONT COLOR="#000080"><B>CDaoRecordset* pRecordset = OnGetRecordset();</B>

<B>try</B>

<B>{// It better work...</B>

<B>    pRecordset-&gt;Delete();</B>

<B>}</B>

<B>catch (CDaoException* e)</B>

<B>{// ...but if it didn't...</B>

<B>    AfxMessageBox(e-&gt;m_pErrorInfo-&gt;m_strDescription);</B>

<B>    e-&gt;Delete();</B>

<B>    return;</B>

<B>}</B>

<B>// Move to the next record after the one just deleted</B>

<B>pRecordset-&gt;MoveNext();</B>

<B>// Ensure that the move is valid:</B>

<B>if (pRecordset-&gt;IsEOF())</B>

<B>{</B>

<B>    pRecordset-&gt;MoveLast();</B>

<B>}</B>

<B>if (pRecordset-&gt;IsBOF())</B>

<B>{</B>

<B>    pRecordset-&gt;SetFieldNull(NULL);</B>

<B>}</B>

<B>UpdateData(FALSE);</B>

<B>return;</B></FONT></PRE>

<P>Finally, when the user selects the refresh option, you must restore the current record's contents. This functionality is required to handle the situation in which the user has modified a record in error and realizes the error prior to updating the database by doing a record move. You must handle two situations with the refresh handler: the user is modifying an existing record, and the user has (in error) added a record that he doesn't want.

<BR>

<P>When aborting an add record situation, you must cancel the add using the CDaoRecordset::CancelUpdate() function. After you cancel the add, you move to the current record. You also turn off the add mode by setting m_bAddMode to FALSE. To cancel an update to an existing record, you simply retrieve the record's original contents and redisplay this information. You do this using the view class's UpdateData() member function:

<BR>

<PRE>

<FONT COLOR="#000080"><B>if (m_bAddMode)</B>

<B>{// Was the user adding a record? If so, exit add mode.</B>

<B>    try</B>

<B>    {// It better work...</B>

<B>        OnGetRecordset()-&gt;CancelUpdate();</B>

<B>        OnGetRecordset()-&gt;Move(0);</B>

<B>    }</B>

<B>    catch (CDaoException* e)</B>

<B>    {// ...but if it didn't...</B>

<B>        AfxMessageBox(e-&gt;m_pErrorInfo-&gt;m_strDescription);</B>

<B>        e-&gt;Delete();</B>

<B>        return;</B>

<B>    }</B>

<B>    m_bAddMode = FALSE;</B>

<B>}</B>

<B>// Restore the user's original values (as necessary):</B>

<B>UpdateData(FALSE);</B>

<B>return;</B></FONT></PRE>

<BR>

<A NAME="E68E76"></A>

<H3 ALIGN=CENTER>

<CENTER>

<FONT SIZE=5 COLOR="#FF0000"><B>Using <I>CDaoRecordset</I> Directly in a Dialog Box</B></FONT></CENTER></H3>

<BR>

<P>To use the CDaoRecordset object directly, you must add a new class to your application using ClassWizard. Base your new class on CDaoRecordset. ClassWizard will prompt you for the DAO datasource and table to use. As in a typical CDaoRecordView application, all columns in the table(s) selected will be bound into your CDaoRecordset object. To display ClassWizard's Create New Class dialog, shown in Figure 14.6, select the Class Info tab in ClassWizard and then click the Add Class button.

<BR>

<P><B><A HREF="14vcg05.gif" tppabs="http://202.113.16.101/%7eeb%7e/Database%20Developer's%20Guide%20with%20Visual%20C++%204,%20Second%20Edition/14vcg05.gif">Figure 14.6. Adding a CDaoRecordset object in a project.</A></B>

<BR>

<P>To use this new class (in the example, the new CDaoRecordset object is called COurDaoRecordset), simply add the header file to source file. For example, to include a COurDaoRecordset object in your dialog box, add the following to the #include statements in the dialog box's source file:

<BR>

<PRE>

<FONT COLOR="#000080">// DaoRecordsetDemo.h : header file

//

/////////////////////////////////////////////////////////////////////////////

// CDaoRecordsetDemo dialog

<B>#include &quot;OurDaoRecordset.h&quot;</B></FONT></PRE>

<P>Then add a member variable m_Set of type OurDaoRecordset in your DaoRecordsetDemo class definition.

<BR>

<P>You must have controls in your dialog box to bind to your database columns. In this example, two controls&#151;IDC_FIRST_NAME and IDC_LAST_NAME&#151;are used to display the first and last name columns from the database's Addresses table. When the CDaoRecordset object is created, it will have member variables for each of the columns in the table.

<BR>

<P>The following code fragment shows the binding of COurDaoRecordset's variables to the controls in the dialog box. Notice that you must write this code by hand: ClassWizard won't recognize the COurDaoRecordset member variables. Be careful to place these field exchange statements after the ClassWizard block:

<BR>

<PRE>

<FONT COLOR="#000080">void CDaoRecordsetDemo::DoDataExchange(CDataExchange* pDX)

{

    CDialog::DoDataExchange(pDX);

    //{{AFX_DATA_MAP(CDaoRecordsetDemo)

        // NOTE: ClassWizard will add DDX and DDV calls here

    //}}AFX_DATA_MAP

<B>//  Add *after* the //AFX_DATA_MAP block!</B>

<B>    DDX_FieldText(pDX, IDC_FIRST_NAME, m_Set.m_FirstName, &amp;m_Set);</B>

<B>    DDV_MaxChars(pDX, m_Set.m_FirstName, 50);</B>

<B>    DDX_FieldText(pDX, IDC_LAST_NAME, m_Set.m_LastName, &amp;m_Set);</B>

<B>    DDV_MaxChars(pDX, m_Set.m_FirstName, 50);</B>

}</FONT></PRE>

<P>The DDX_FieldText() macros (and all other DDX_Field...() macros) require a pointer to your CDaoRecordset object as the final parameter.

<BR>

<P>Next, the COurDaoRecordset object must be initialized. That is, the datasource must be opened. In a dialog box, you can do this in either the constructor or in the WM_INITDIALOG handler:

<BR>

<PRE>

<FONT COLOR="#000080">BOOL CDaoRecordsetDemo::OnInitDialog()

{

    CDialog::OnInitDialog();

    // TODO: Add extra initialization here

<B>    m_Set.Open();</B>

<B>    UpdateData(FALSE);</B>

    return TRUE;  // Return TRUE unless you set the focus to a control

                  // EXCEPTION: OCX Property Pages should return FALSE

}</FONT></PRE>

<P>When you do the COurDaoRecordset open in the OnInitDialog() handler, you must tell the dialog manager to update the controls with a call to UpdateData(FALSE). If you forget to do this, the controls that reflect records from the datasource will initially be blank.

<BR>

<P>At this stage, you have an open datasource. The first record in the datasource will be displayed in the dialog box's controls. You don't have any way to select another record, because there are no record navigation controls!

<BR>

<P>In the sample program, I've added four buttons to the dialog box: First, Next, Previous, and Last. These controls execute a set of 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -