📄 chap10_7.htm
字号:
<p ALIGN="JUSTIFY">m_pSet->m_strFilter = "CourseID = ?"; //</font><font SIZE="3">使用参数</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">m_pSet->m_strCourseIDParam = pDoc->m_courseSet.m_CourseID;</p>
<p ALIGN="JUSTIFY">m_pSet->m_strSort = "SectionNo";</p>
<p ALIGN="JUSTIFY">m_pSet->m_pDatabase = pDoc->m_courseSet.m_pDatabase; //</font><font SIZE="3">共享</font><font FACE="Times New Roman" SIZE="3">CDatabase</b></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">CRecordView::OnInitialUpdate();</p>
<p ALIGN="JUSTIFY"></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
<p></font><b><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">m_ctlCourseList.ResetContent();</p>
<p ALIGN="JUSTIFY">if (pDoc->m_courseSet.IsOpen())</p>
<p ALIGN="JUSTIFY">{</p>
<p ALIGN="JUSTIFY">while (!pDoc->m_courseSet.IsEOF())</p>
<p ALIGN="JUSTIFY">{</p>
<p ALIGN="JUSTIFY">m_ctlCourseList.AddString(</p>
<p ALIGN="JUSTIFY">pDoc->m_courseSet.m_CourseID); //</font><font SIZE="3">向表中加入</font><font FACE="Times New Roman" SIZE="3">CourseID</font><font SIZE="3">字段</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">pDoc->m_courseSet.MoveNext();</p>
<p ALIGN="JUSTIFY">}</p>
<p ALIGN="JUSTIFY">}</p>
<p ALIGN="JUSTIFY">m_ctlCourseList.SetCurSel(0);</b></p>
<p ALIGN="JUSTIFY">}</p>
<p ALIGN="JUSTIFY"></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">void CSectionForm::OnSelendokCourselist()</p>
<p ALIGN="JUSTIFY">{</p>
<p></font><b><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">if (!m_pSet->IsOpen())</p>
<p ALIGN="JUSTIFY">return;</p>
<p ALIGN="JUSTIFY">m_ctlCourseList.GetLBText(m_ctlCourseList.GetCurSel(),</p>
<p ALIGN="JUSTIFY">m_pSet->m_strCourseIDParam);</p>
<p ALIGN="JUSTIFY">m_pSet->Requery(); //</font><font SIZE="3">重新查询</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">if (m_pSet->IsEOF())</p>
<p ALIGN="JUSTIFY">{</p>
<p ALIGN="JUSTIFY">m_pSet->SetFieldNull(&(m_pSet->m_CourseID), FALSE);</p>
<p ALIGN="JUSTIFY">m_pSet->m_CourseID = m_pSet->m_strCourseIDParam;</p>
<p ALIGN="JUSTIFY">}</p>
<p ALIGN="JUSTIFY">UpdateData(FALSE);</b></p>
<p ALIGN="JUSTIFY">}</p>
<p ALIGN="JUSTIFY"></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">在</font><font FACE="Times New Roman" SIZE="3">CSectionForm::OnInitialUpdate</font><font SIZE="3">函数的开头部分,调用了</font><font FACE="Times New Roman" SIZE="3">CRecordset::Open</font><font SIZE="3">建立</font><font FACE="Times New Roman" SIZE="3">CCourseSet</font><font SIZE="3">记录集,在调用</font><font FACE="Times New Roman" SIZE="3">Open</font><font SIZE="3">函数之前,指定了按</font><font FACE="Times New Roman" SIZE="3">CourseID</font><font SIZE="3">字段排序记录集。关于调用</font><font FACE="Times New Roman" SIZE="3">Open</font><font SIZE="3">函数的一些前因后果在前面已经解释过了,读者应该不难分析。接下来的代码读者可能就看不懂了,为什么在记录集的</font><font FACE="Times New Roman" SIZE="3">m_strFilter</font><font SIZE="3">过滤字符串中会有一个“</font><font FACE="Times New Roman" SIZE="3">?</font><font SIZE="3">”号呢。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">这是因为在本例中使用了“参数化记录集”技术。在记录集的</font><font FACE="Times New Roman" SIZE="3">m_strFilter</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">m_strSort</font><font SIZE="3">中,可以用“</font><font FACE="Times New Roman" SIZE="3">?</font><font SIZE="3">”号作为参数使用,这样在指定过滤器和排序时可以更具灵活性。例如,在</font><font FACE="Times New Roman" SIZE="3">OnInitialUpdate</font><font SIZE="3">函数中,是这样指定过滤器的:</font><font FACE="Times New Roman" SIZE="3"><b></p>
<p ALIGN="JUSTIFY">m_pSet->m_strFilter = "CourseID = ?";</b></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">在调用</font><font FACE="Times New Roman" SIZE="3">Open</font><font SIZE="3">或</font><font FACE="Times New Roman" SIZE="3">Requery</font><font SIZE="3">时,“</font><font FACE="Times New Roman" SIZE="3">?</font><font SIZE="3">”将会被</font><font FACE="Times New Roman" SIZE="3">CSectionSet::m_strCourseIDParam</font><font SIZE="3">中的内容取代。例如,如果指定</font><font FACE="Times New Roman" SIZE="3">m_strCourseIDParam</font><font SIZE="3">为“</font><font FACE="Times New Roman" SIZE="3">MATH101</font><font SIZE="3">”,则</font><font FACE="Times New Roman" SIZE="3">m_strFilter</font><font SIZE="3">将变成</font><font FACE="Times New Roman" SIZE="3">"CourseID = MATH101"</font><font SIZE="3">。这样用户只要指定了</font><font FACE="Times New Roman" SIZE="3">m_strCourseIDParam</font><font SIZE="3">,就可以定制过滤器。象</font><font FACE="Times New Roman" SIZE="3">m_strCourseIDParam</font><font SIZE="3">这样的成员被称作参数数据成员,同域数据成员一样,它是记录集所特有的。</font><font FACE="Times New Roman" SIZE="3">ClassWizard</font><font SIZE="3">不支持参数数据成员,用户只能手工加入之,且其名字由用户自己确定。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">参数替换的工作实际上是由</font><font FACE="Times New Roman" SIZE="3">CSectionSet::DoFieldExchange</font><font SIZE="3">中的</font><font FACE="Times New Roman" SIZE="3">RFX</font><font SIZE="3">函数完成的,在</font><font FACE="Times New Roman" SIZE="3">DoFieldExchange</font><font SIZE="3">函数的末尾,我们加入了下面两行:</font><font FACE="Times New Roman" SIZE="3"><b></p>
<p ALIGN="JUSTIFY">pFX->SetFieldType(CFieldExchange::param);</p>
<p ALIGN="JUSTIFY">RFX_Text(pFX, "CourseIDParam", m_strCourseIDParam);</b></p>
<p ALIGN="JUSTIFY">DoFieldExchange</font><font SIZE="3">可以识别域数据成员和参数数据成员。第一行调用用来表明随后的</font><font FACE="Times New Roman" SIZE="3">RFX</font><font SIZE="3">函数用于参数替换。第二行是一个用于</font><font FACE="Times New Roman" SIZE="3">m_strCourseIDParam</font><font SIZE="3">参数的</font><font FACE="Times New Roman" SIZE="3">RFX</font><font SIZE="3">函数。</font><font FACE="Times New Roman" SIZE="3">RFX</font><font SIZE="3">第二个参数的名字可由用户确定,这里指定其为“</font><font FACE="Times New Roman" SIZE="3">CourseIDParam</font><font SIZE="3">”。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">用户可以在</font><font FACE="Times New Roman" SIZE="3">m_strFilter</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">m_strSort</font><font SIZE="3">中使用一个或多个参数。在有多个参数的情况下,要注意</font><font FACE="Times New Roman" SIZE="3">RFX</font><font SIZE="3">函数的调用次序应与参数出现的次序相对应。框架规定,用户应该先在</font><font FACE="Times New Roman" SIZE="3">m_strFilter</font><font SIZE="3">中安排参数,然后才是</font><font FACE="Times New Roman" SIZE="3">m_strSort</font><font SIZE="3">。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">CRecordset</font><font SIZE="3">有两个数据成员</font><font FACE="Times New Roman" SIZE="3">m_nFields</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">m_nParams</font><font SIZE="3">分别用来统计域数据成员和参数数据成员的数目。前者由</font><font FACE="Times New Roman" SIZE="3">ClassWizard</font><font SIZE="3">自动计数,而后者必需由用户来维护。在</font><font FACE="Times New Roman" SIZE="3">CSectionSet</font><font SIZE="3">的构造函数中,</font><font FACE="Times New Roman" SIZE="3">m_nParams</font><font SIZE="3">被置为</font><font FACE="Times New Roman" SIZE="3">1</font><font SIZE="3">,因为只有一个参数数据成员。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">现在让我们继续研究</font><font FACE="Times New Roman" SIZE="3">OnInitialUpdate</font><font SIZE="3">。在调用基类的</font><font FACE="Times New Roman" SIZE="3">OnInitialUpdate</font><font SIZE="3">以前,在程序中有这样一行代码:</font><font FACE="Times New Roman" SIZE="3"><b></p>
<p ALIGN="JUSTIFY">m_pSet->m_pDatabase = pDoc->m_courseSet.m_pDatabase;</b></p>
<p ALIGN="JUSTIFY">m_pDatabase</font><font SIZE="3">是</font><font FACE="Times New Roman" SIZE="3">CRecordset</font><font SIZE="3">的公共成员,它是指向</font><font FACE="Times New Roman" SIZE="3">CDatabase</font><font SIZE="3">对象的指针。如果应用程序使用了两个以上的记录集,在缺省情况下,每个记录集都会创建一个代表同一数据源的</font><font FACE="Times New Roman" SIZE="3">CDatabase</font><font SIZE="3">对象</font><font FACE="Times New Roman" SIZE="3">(</font><font SIZE="3">参见</font><font FACE="Times New Roman" SIZE="3">10.5.4)</font><font SIZE="3">,这显然没有必要。上面一行代码使</font><font FACE="Times New Roman" SIZE="3">CSectionSet</font><font SIZE="3">记录集共享由</font><font FACE="Times New Roman" SIZE="3">CCourseSet</font><font SIZE="3">记录集创建的</font><font FACE="Times New Roman" SIZE="3">CDatabase</font><font SIZE="3">对象,这样,当在</font><font FACE="Times New Roman" SIZE="3">CRecordView:: OnInitialUpdate</font><font SIZE="3">中调用</font><font FACE="Times New Roman" SIZE="3">CRecordset::Open</font><font SIZE="3">打开</font><font FACE="Times New Roman" SIZE="3">CSectionSet</font><font SIZE="3">记录集时,就不会再创建</font><font FACE="Times New Roman" SIZE="3">CDatabase</font><font SIZE="3">对象了。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">接下来,程序把</font><font FACE="Times New Roman" SIZE="3">CCourseSet</font><font SIZE="3">的每一个记录的</font><font FACE="Times New Roman" SIZE="3">CourseID</font><font SIZE="3">字段都加入到组合框中。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">当用户在组合框中选择了新的</font><font FACE="Times New Roman" SIZE="3">CourseID</font><font SIZE="3">时,在</font><font FACE="Times New Roman" SIZE="3">CSectionForm::OnSelendokCourselist</font><font SIZE="3">中,就会把用户选择的</font><font FACE="Times New Roman" SIZE="3">CourseID</font><font SIZE="3">设置到</font><font FACE="Times New Roman" SIZE="3">m_strCourseIDParam</font><font SIZE="3">中,然后调用</font><font FACE="Times New Roman" SIZE="3">CRecordset::Requery</font><font SIZE="3">按照定制的过滤器和排序重新查询和建立记录集。如果重新建立的记录集为空,则说明</font><font FACE="Times New Roman" SIZE="3">Section</font><font SIZE="3">表中没有与指定的</font><font FACE="Times New Roman" SIZE="3">CourseID</font><font SIZE="3">相对应的记录,这时记录集被自动设置为</font><font FACE="Times New Roman" SIZE="3">NULL</font><font SIZE="3">。在程序中,调用了</font><font FACE="Times New Roman" SIZE="3">CRecordset:: SetFieldNull</font><font SIZE="3">把</font><font FACE="Times New Roman" SIZE="3">m_CourseID</font><font SIZE="3">字段设置为非空。最后,调用</font><font FACE="Times New Roman" SIZE="3">CRecordView::UpdateData</font><font SIZE="3">更新表单中的控件。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">从程序中不难看出,使用参数化记录集的最大好处是可以在程序运行期间方便地指定过滤器和排序,这大大提高了程序的用户定制查询能力。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">编译并运行</font><font FACE="Times New Roman" SIZE="3">Enroll</font><font SIZE="3">,试试新增加的功能。</font><font FACE="Times New Roman" SIZE="3"></p>
<p></font><b><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font></b><font color="#3973DE" FACE="Times New Roman" SIZE="3">10.7.4
Enroll</font><font SIZE="3" color="#3973DE">的第三个版本</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">Enroll</font><font SIZE="3">的第三个版本支持记录的添加和删除,该版本也演示了对数据库异常的处理。请读者先运行</font><font FACE="Times New Roman" SIZE="3">VC5.0</font><font SIZE="3">提供的第三步</font><font FACE="Times New Roman" SIZE="3">Enroll</font><font SIZE="3">程序看一看。第三版</font><font FACE="Times New Roman" SIZE="3">Enroll</font><font SIZE="3">的</font><font FACE="Times New Roman" SIZE="3">Record</font><font SIZE="3">菜单中多了三个命令:</font><font FACE="Times New Roman" SIZE="3">Add</font><font SIZE="3">、</font><font FACE="Times New Roman" SIZE="3">Delete</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">Refresh</font><font SIZE="3">,它们分别用来添加、删除和刷新记录。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">当用户选择</font><font FACE="Times New Roman" SIZE="3">Add</font><font SIZE="3">命令后,就进入了添加模式。这时除</font><font FACE="Times New Roman" SIZE="3">Course</font><font SIZE="3">组合框外,所有的字段都被清除。用户可以在各编辑框内输入新记录的字段值,然后移动到别的记录上,这样就把新的记录保存到数据源中。用户也可以通过再次选择</font><font FACE="Times New Roman" SIZE="3">Add</font><font SIZE="3">命令来保存新加的记录。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">当用户选择</font><font FACE="Times New Roman" SIZE="3">Delete</font><font SIZE="3">命令后,当前记录被删除,程序会自动滚动到下一个记录上。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">Refresh</font><font SIZE="3">命令用来放弃记录的修改或添加操作,同时,恢复原记录的内容。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">现在就让我们开始在上一小节</font><font FACE="Times New Roman" SIZE="3">Enroll</font><font SIZE="3">的基础上制作新版本。若当前工程不是</font><font FACE="Times New Roman" SIZE="3">Enroll</font><font SIZE="3">,请读者打开上一小节创建的</font><font FACE="Times New Roman" SIZE="3">Enroll</font><font SIZE="3">工程。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">首先要为</font><font FACE="Times New Roman" SIZE="3">Record</font><font SIZE="3">菜单添加三个菜单项,菜单项的各项属性在表</font><font FACE="Times New Roman" SIZE="3">10.6</font><font SIZE="3">中列出。请把这三个菜单项加到</font><font FACE="Times New Roman" SIZE="3">Record</font><font SIZE="3">菜单的开头,并且用一个分隔线和后面的命令隔开。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><b><font SIZE="3"> </p>
<p ALIGN="CENTER">表</font><font FACE="Times New Roman" SIZE="3">10.6<
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -