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

📄 chap10_7.htm

📁 VC++编程实例。非常详细
💻 HTM
📖 第 1 页 / 共 4 页
字号:
          <p align="JUSTIFY">m_pSet-&gt;m_strCourseIDParam = pDoc-&gt;m_courseSet.m_CourseID;</p>
          <p align="JUSTIFY">m_pSet-&gt;m_strSort = &quot;SectionNo&quot;;</p>
           
          <p align="JUSTIFY">m_pSet-&gt;m_pDatabase 
            = pDoc-&gt;m_courseSet.m_pDatabase; //共享CDatabase</p>
          </b> 
          <p align="JUSTIFY">  </p>
           
          <p align="JUSTIFY">CRecordView::OnInitialUpdate();</p>
           
          <p align="JUSTIFY"> </p>
          <p> <b> </b></p>
          <b> 
          <p align="JUSTIFY">m_ctlCourseList.ResetContent();</p>
          <p align="JUSTIFY">if (pDoc-&gt;m_courseSet.IsOpen())</p>
          <p align="JUSTIFY">{</p>
          <p align="JUSTIFY">while (!pDoc-&gt;m_courseSet.IsEOF())</p>
          <p align="JUSTIFY">{</p>
          <p align="JUSTIFY">m_ctlCourseList.AddString(</p>
           
          <p align="JUSTIFY">pDoc-&gt;m_courseSet.m_CourseID); 
            //向表中加入CourseID字段</p>
           
          <p align="JUSTIFY">pDoc-&gt;m_courseSet.MoveNext();</p>
          <p align="JUSTIFY">}</p>
          <p align="JUSTIFY">}</p>
          <p align="JUSTIFY">m_ctlCourseList.SetCurSel(0);</p>
          </b> 
          <p align="JUSTIFY">}</p>
           
          <p align="JUSTIFY"> </p>
           
          <p align="JUSTIFY">void CSectionForm::OnSelendokCourselist()</p>
          <p align="JUSTIFY">{</p>
           
          <p><b> </b></p>
          <b> 
          <p align="JUSTIFY">if (!m_pSet-&gt;IsOpen())</p>
          <p align="JUSTIFY">return;</p>
          <p align="JUSTIFY">m_ctlCourseList.GetLBText(m_ctlCourseList.GetCurSel(),</p>
          <p align="JUSTIFY">m_pSet-&gt;m_strCourseIDParam);</p>
           
          <p align="JUSTIFY">m_pSet-&gt;Requery(); 
            //重新查询</p>
           
          <p align="JUSTIFY">if (m_pSet-&gt;IsEOF())</p>
          <p align="JUSTIFY">{</p>
          <p align="JUSTIFY">m_pSet-&gt;SetFieldNull(&amp;(m_pSet-&gt;m_CourseID), 
            FALSE);</p>
          <p align="JUSTIFY">m_pSet-&gt;m_CourseID = m_pSet-&gt;m_strCourseIDParam;</p>
          <p align="JUSTIFY">}</p>
          <p align="JUSTIFY">UpdateData(FALSE);</p>
          </b> 
          <p align="JUSTIFY">}</p>
           
          <p align="JUSTIFY"> </p>
          <p align="JUSTIFY"> 在CSectionForm::OnInitialUpdate函数的开头部分,调用了CRecordset::Open建立CCourseSet记录集,在调用Open函数之前,指定了按CourseID字段排序记录集。关于调用Open函数的一些前因后果在前面已经解释过了,读者应该不难分析。接下来的代码读者可能就看不懂了,为什么在记录集的m_strFilter过滤字符串中会有一个“?”号呢。</p>
          <p align="JUSTIFY"> 这是因为在本例中使用了“参数化记录集”技术。在记录集的m_strFilter和m_strSort中,可以用“?”号作为参数使用,这样在指定过滤器和排序时可以更具灵活性。例如,在OnInitialUpdate函数中,是这样指定过滤器的:</p>
          <b> 
          <p align="JUSTIFY">m_pSet-&gt;m_strFilter = &quot;CourseID = ?&quot;;</p>
          </b>  
          <p align="JUSTIFY">在调用Open或Requery时,“?”将会被CSectionSet::m_strCourseIDParam中的内容取代。例如,如果指定m_strCourseIDParam为“MATH101”,则m_strFilter将变成&quot;CourseID 
            = MATH101&quot;。这样用户只要指定了m_strCourseIDParam,就可以定制过滤器。象m_strCourseIDParam这样的成员被称作参数数据成员,同域数据成员一样,它是记录集所特有的。ClassWizard不支持参数数据成员,用户只能手工加入之,且其名字由用户自己确定。</p>
          <p align="JUSTIFY"> 参数替换的工作实际上是由CSectionSet::DoFieldExchange中的RFX函数完成的,在DoFieldExchange函数的末尾,我们加入了下面两行:</p>
          <b> 
          <p align="JUSTIFY">pFX-&gt;SetFieldType(CFieldExchange::param);</p>
          <p align="JUSTIFY">RFX_Text(pFX, &quot;CourseIDParam&quot;, m_strCourseIDParam);</p>
          </b>  
          <p align="JUSTIFY">DoFieldExchange可以识别域数据成员和参数数据成员。第一行调用用来表明随后的RFX函数用于参数替换。第二行是一个用于m_strCourseIDParam参数的RFX函数。RFX第二个参数的名字可由用户确定,这里指定其为“CourseIDParam”。</p>
          <p align="JUSTIFY"> 用户可以在m_strFilter和m_strSort中使用一个或多个参数。在有多个参数的情况下,要注意RFX函数的调用次序应与参数出现的次序相对应。框架规定,用户应该先在m_strFilter中安排参数,然后才是m_strSort。</p>
          <p align="JUSTIFY"> CRecordset有两个数据成员m_nFields和m_nParams分别用来统计域数据成员和参数数据成员的数目。前者由ClassWizard自动计数,而后者必需由用户来维护。在CSectionSet的构造函数中,m_nParams被置为1,因为只有一个参数数据成员。</p>
          <p align="JUSTIFY"> 现在让我们继续研究OnInitialUpdate。在调用基类的OnInitialUpdate以前,在程序中有这样一行代码:</p>
          <b> 
          <p align="JUSTIFY">m_pSet-&gt;m_pDatabase = pDoc-&gt;m_courseSet.m_pDatabase;</p>
          </b>  
          <p align="JUSTIFY">m_pDatabase是CRecordset的公共成员,它是指向CDatabase对象的指针。如果应用程序使用了两个以上的记录集,在缺省情况下,每个记录集都会创建一个代表同一数据源的CDatabase对象(参见10.5.4),这显然没有必要。上面一行代码使CSectionSet记录集共享由CCourseSet记录集创建的CDatabase对象,这样,当在CRecordView:: 
            OnInitialUpdate中调用CRecordset::Open打开CSectionSet记录集时,就不会再创建CDatabase对象了。</p>
          <p align="JUSTIFY"> 接下来,程序把CCourseSet的每一个记录的CourseID字段都加入到组合框中。</p>
          <p align="JUSTIFY"> 当用户在组合框中选择了新的CourseID时,在CSectionForm::OnSelendokCourselist中,就会把用户选择的CourseID设置到m_strCourseIDParam中,然后调用CRecordset::Requery按照定制的过滤器和排序重新查询和建立记录集。如果重新建立的记录集为空,则说明Section表中没有与指定的CourseID相对应的记录,这时记录集被自动设置为NULL。在程序中,调用了CRecordset:: 
            SetFieldNull把m_CourseID字段设置为非空。最后,调用CRecordView::UpdateData更新表单中的控件。</p>
          <p align="JUSTIFY"> 从程序中不难看出,使用参数化记录集的最大好处是可以在程序运行期间方便地指定过滤器和排序,这大大提高了程序的用户定制查询能力。</p>
          <p align="JUSTIFY"> 编译并运行Enroll,试试新增加的功能。</p>
          <p> <b> </b></p>
          <p align="JUSTIFY"><b> </b>10.7.4 Enroll的第三个版本</p>
          <p align="JUSTIFY"> Enroll的第三个版本支持记录的添加和删除,该版本也演示了对数据库异常的处理。请读者先运行VC5.0提供的第三步Enroll程序看一看。第三版Enroll的Record菜单中多了三个命令:Add、Delete和Refresh,它们分别用来添加、删除和刷新记录。</p>
          <p align="JUSTIFY"> 当用户选择Add命令后,就进入了添加模式。这时除Course组合框外,所有的字段都被清除。用户可以在各编辑框内输入新记录的字段值,然后移动到别的记录上,这样就把新的记录保存到数据源中。用户也可以通过再次选择Add命令来保存新加的记录。</p>
          <p align="JUSTIFY"> 当用户选择Delete命令后,当前记录被删除,程序会自动滚动到下一个记录上。</p>
          <p align="JUSTIFY"> Refresh命令用来放弃记录的修改或添加操作,同时,恢复原记录的内容。</p>
          <p align="JUSTIFY"> 现在就让我们开始在上一小节Enroll的基础上制作新版本。若当前工程不是Enroll,请读者打开上一小节创建的Enroll工程。</p>
          <p align="JUSTIFY"> 首先要为Record菜单添加三个菜单项,菜单项的各项属性在表10.6中列出。请把这三个菜单项加到Record菜单的开头,并且用一个分隔线和后面的命令隔开。</p>
          <p align="JUSTIFY"> <b> </b></p>
          <b> 
          <p align="CENTER">表10.6</p>
          </b> 
          <table border="1" cellspacing="1" cellpadding="1" width="579">
            <tr> 
              <td width="18%"><b> 
                <p align="JUSTIFY">Caption 
                </b></td>
              <td width="36%"><b> 
                <p align="JUSTIFY">ID 
                </b></td>
              <td width="46%"><b> 
                <p align="JUSTIFY">Prompt 
                </b></td>
            </tr>
            <tr> 
              <td width="18%"> 
                <p align="JUSTIFY">&amp;Add 
                </td>
              <td width="36%"> 
                <p align="JUSTIFY">ID_RECORD_ADD 
                </td>
              <td width="46%"> 
                <p align="JUSTIFY">Add a new section 
                </td>
            </tr>
            <tr> 
              <td width="18%"> 
                <p align="JUSTIFY">&amp;Refresh 
                </td>
              <td width="36%"> 
                <p align="JUSTIFY">ID_RECORD_REFRESH 
                </td>
              <td width="46%"> 
                <p align="JUSTIFY">Cancel changes on form,or cancel Add 
                </td>
            </tr>
            <tr> 
              <td width="18%"> 
                <p align="JUSTIFY">&amp;Delete 
                </td>
              <td width="36%"> 
                <p align="JUSTIFY">ID_RECORD_DELETE 
                </td>
              <td width="46%"> 
                <p align="JUSTIFY">Delete section 
                </td>
            </tr>
          </table>
          <p> </p>
          <p align="JUSTIFY">  </p>
          <p align="JUSTIFY"> 接着,用ClassWizard为上面三个命令创建处理函数,函数名为缺省的。另外,需要为记录视图编写新的OnMove函数来处理滚动命令,这是因为原来的OnMove函数没有添加记录的功能。在ClassWizard的CSectionForm类的Messages列表中可以找到OnMove函数,请读者双击并建立该函数。</p>
          <p align="JUSTIFY"> 在CSectionForm::OnMove函数处理滚动命令时,必需要有一个标志来判断当前是否处于添加模式,以便向数据源中加入新记录或进行普通的滚动处理。请读者在CSectionForm类的定义中的适当位置加入下面两行:</p>
          <b> 
          <p align="JUSTIFY">protected:</p>
          <p align="JUSTIFY">BOOL m_bAddMode;</p>
          </b>  
          <p align="JUSTIFY">在前两个版本的Enroll中,Section编辑框都是只读的,但在添加记录时,必需允许用户修改Section编辑框。这是因为SectionNo字段是Section表的主关键字,它的值必需唯一,如果在加入新记录时不改变原来的SectionNo字段,那么将会因为主关键字重复而导致异常产生。显然,我们需要一个CEdit对象来控制IDC_SECTION编辑框,请读者用ClassWizard为CSectionForm类加入一个与IDC_SECTION对应的CEdit型成员变量,变量的名字为m_ctlSection。</p>
          <p align="JUSTIFY"> 最后,请读者按清单10.13修改程序。</p>
          <p align="JUSTIFY"> <b> </b></p>
          <p align="JUSTIFY"> <b>清单10.13 
            CSectionForm类的部分源代码</b></p>
           
          <p align="JUSTIFY">CSectionForm::CSectionForm()</p>
          <p align="JUSTIFY">: CRecordView(CSectionForm::IDD)</p>
          <p align="JUSTIFY">{</p>
          <p align="JUSTIFY"><b>. . .</b></p>
          <b> 
          <p align="JUSTIFY">m_bAddMode = FALSE;</p>
          </b> 
          <p align="JUSTIFY">}</p>
           
          <p align="JUSTIFY"> </p>
           
          <p align="JUSTIFY">void CSectionForm::OnSelendokCourselist()</p>
          <p align="JUSTIFY">{</p>
          <p align="JUSTIFY">if (!m_pSet-&gt;IsOpen())</p>
          <p align="JUSTIFY">return;</p>
          <p align="JUSTIFY">m_ctlCourseList.GetLBText(m_ctlCourseList.GetCurSel(),</p>
          <p align="JUSTIFY">m_pSet-&gt;m_strCourseIDParam);</p>
           
          <p><b> </b></p>
          <b> 
          <p align="JUSTIFY">if (!m_bAddMode)</p>
          <p align="JUSTIFY">{</p>
          </b> 
          <p align="JUSTIFY">m_pSet-&gt;Requery();</p>
          <p align="JUSTIFY">if (m_pSet-&gt;IsEOF())</p>
          <p align="JUSTIFY">{</p>
          <p align="JUSTIFY">m_pSet-&gt;SetFieldNull(&amp;(m_pSet-&gt;m_CourseID), 
            FALSE);</p>
          <p align="JUSTIFY">m_pSet-&gt;m_CourseID = m_pSet-&gt;m_strCourseIDParam;</p>
          <p align="JUSTIFY">}</p>
          <p align="JUSTIFY">UpdateData(FALSE);</p>
           
          <p><b> </b></p>
          <b> 
          <p align="JUSTIFY">}</p>

⌨️ 快捷键说明

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