📄 ch22.htm
字号:
<pre><font color="#008000">void CEmployeeView::OnFilterDepartment() </font></pre>
<pre><font color="#008000">{</font></pre>
<pre><font color="#008000"> </font><font color="#008000">DoFilter("DeptID");</font></pre>
<pre><font color="#008000">}</font></pre>
<pre><font color="#008000">void CEmployeeView::OnFilterId() </font></pre>
<pre><font color="#008000">{</font></pre>
<pre><font color="#008000"> </font><font color="#008000">DoFilter("EmployeeID");</font></pre>
<pre><font color="#008000">}</font></pre>
<pre><font color="#008000">void CEmployeeView::OnFilterName() </font></pre>
<pre><font color="#008000">{</font></pre>
<pre><font color="#008000"> </font><font color="#008000">DoFilter("EmployeeName");</font><font color="#008000"> </font></pre>
<pre><font color="#008000">}</font></pre>
<pre><font color="#008000">void CEmployeeView::OnFilterRate() </font></pre>
<pre><font color="#008000">{</font></pre>
<pre><font color="#008000"> </font><font color="#008000">DoFilter("EmployeeRate");</font><font color="#008000"> </font></pre>
<pre><font color="#008000">}</font></pre>
<P>These four functions all call <font color="#008000">DoFilter()</font>. You will write this function to filter the database records represented by the record set class. Right-click <font color="#008000">CEmployeeView</font> in ClassView and choose Add
Member Function. The type is <font color="#008000">void</font> and the declaration is <font color="#008000">DoFilter(CString col)</font>. It’s a protected member function, because it’s only called from other member functions of <font
color="#008000">CEmployeeView</font>. Double-click <font color="#008000">DoFilter()</font> in ClassView and add the code from Listing 22.9.</P>
<P><I>Listing 22.9—</I>CEmployeeView::DoFilter()</P>
<pre><font color="#008000">void CEmployeeView::DoFilter(CString col)</font></pre>
<pre><font color="#008000">{</font></pre>
<pre><font color="#008000"> CFilterDlg dlg;</font></pre>
<pre><font color="#008000"> int result = dlg.DoModal();</font></pre>
<pre><font color="#008000"> </font></pre>
<pre><font color="#008000"> if (result == IDOK)</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> CString str = col + " = '" + dlg.m_filterValue + "'";</font></pre>
<pre><font color="#008000"> m_pSet->Close();</font></pre>
<pre><font color="#008000"> m_pSet->m_strFilter = str;</font></pre>
<pre><font color="#008000"> m_pSet->Open();</font></pre>
<pre><font color="#008000"> int recCount = m_pSet->GetRecordCount();</font></pre>
<pre><font color="#008000"> </font></pre>
<pre><font color="#008000"> if (recCount == 0)</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> MessageBox("No matching records.");</font></pre>
<pre><font color="#008000"> m_pSet->Close();</font></pre>
<pre><font color="#008000"> m_pSet->m_strFilter = "";</font></pre>
<pre><font color="#008000"> m_pSet->Open();</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> </font></pre>
<pre><font color="#008000"> UpdateData(FALSE);</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000"> </font></pre>
<pre><font color="#008000">}</font></pre>
<P>You've now added the ability to sort and filter records in the employee database. Build the application and run it. When you do, the application's main window appears, looking the same as before. Now, however, you can sort the records on any field,
just by selecting a field from the <U>S</U>ort menu. You can also filter the records by selecting a field from the <U>F</U>ilter menu, and then typing the filter string into the Filter dialog box that appears. You can tell how the records are sorted or
filtered by moving through them one at a time. Try sorting by department, or rate, for example. Then try filtering on one of the departments you saw scroll by.</P>
<P><A ID="I17" NAME="I17"><B>Examining the </B><B><I>OnSortDept()</I></B><B> Function</B></A></P>
<P>The sorting functions all have the same structure. They close the recordset, set its <font color="#008000">m_strSort</font> member variable, open it again, and then call <font color="#008000">UpdateData()</font> to refresh the view with the values from
the newly sorted recordset. You don't see any calls to a member function with <font color="#008000">Sort</font> in its name. So when does the sort happen? When the recordset is reopened.</P>
<P>A <font color="#008000">CRecordset</font> object (or any object of a class derived from <font color="#008000">CRecordset</font>, such as this program's <font color="#008000">CEmployeeSet</font> object) uses a special string, called <font
color="#008000">m_strSort</font>, to determine how the records should be sorted. When the recordset is being created, the object checks this string and sorts the records accordingly.</P>
<P><A ID="I18" NAME="I18"><B>Examining the </B><B><I>DoFilter()</I></B><B> Function</B></A></P>
<P>Whenever the user selects a command from the <U>F</U>ilter menu, the framework calls the appropriate member function, either <font color="#008000">OnFilterDept()</font>, <font color="#008000">OnFilterID()</font>, <font
color="#008000">OnFilterName()</font>, or <font color="#008000">OnFilterRate()</font>. Each of these functions does nothing more than call the local member function <font color="#008000">DoFilter()</font> with a string representing the field on which to
filter.</P>
<p><font color="#008000">DoFilter() </font>displays the same dialog box no matter which filter menu item was chosen, by creating an instance of the dialog box class and calling its <font color="#008000">DoModal()</font> function. </P>
<P>If <font color="#008000">result</font> does not equal <font color="#008000">IDOK</font>, the user must have clicked Cancel: the entire <font color="#008000">if</font> statement gets skipped over and the <font color="#008000">DoFilter()</font> function
does nothing but return.</P>
<P>Inside the <font color="#008000">if</font> statement, the function first creates the string that will be used to filter the database. Just as you set a string to sort the database, so too do you set a string to filter the database. In this case, the
string is called <font color="#008000">m_strFilter</font>. The string you use to filter the database must be in a form like this:</P>
<P><I><font color="#008000">ColumnID</font></I><font color="#008000"> = </font><I><font color="#008000">'ColumnValue'</font></I></P>
<P>The column ID was provided to <font color="#008000">DoFilter()</font> as a <font color="#008000">CString</font> parameter, and the value was provided by the user. So if, for example, the user chooses to filter by department and types <B>hardware</B> in
the filter value box, <font color="#008000">DoFilter()</font> would set <font color="#008000">str</font> to <font color="#008000">DeptID = 'hardware'</font>.</P>
<P>With the string constructed, the program is ready to filter the database. Just as with sorting, the record set must first be closed, then <font color="#008000">DoFilter()</font> sets the recordset's filter string, then it reopens the recordset. </P>
<P>What happens when the given filter results in no records being selected? Good question. The <font color="#008000">DoFilter()</font> function handles this by getting the number of records in the new recordset and comparing them to zero. If the record
set is empty, the program displays a message box telling the user of the problem. Then the program closes the recordset, resets the filter string to an empty string, and reopens the recordset. This restores the recordset to include all the records in the
Employees table.</P>
<P>Finally, whether the filter resulted in a subset of records or the recordset had to be restored, the program must redisplay the data, by calling <font color="#008000">UpdateData()</font>, as always.</P>
<H3><A ID="I19" NAME="I19"><B>Choosing Between OBDC and DAO</B></A></H3>
<P>In the previous section, you read an introduction to Visual C++'s ODBC classes and how they're used in an AppWizard-generated application. Visual C++ also features a complete set of DAO classes that you can use to create database applications. DAO is,
in many ways, almost a superset of the ODBC classes, containing most of the functionality of the OBDC classes and adding a great deal of its own. Unfortunately, although DAO can read ODBC data sources for which ODBC drivers are available, it's not
particularly efficient at the task. For this reason, the DAO classes are best suited for programming applications that manipulate Microsoft's .mdb database files, which are created by Microsoft Access. Other file formats that DAO can read directly are
those created by Fox Pro and Excel.</P>
<P>The DAO classes, which use the Microsoft Jet Database Engine, are so much like the ODBC classes that you can often convert a ODBC program to DAO simply by changing the class names in the program: <font color="#008000">CDatabase</font> becomes <font
color="#008000">CDaoDatabase</font>, <font color="#008000">CRecordset</font> becomes <font color="#008000">CDaoRecordset</font>, and <font color="#008000">CRecordView</font> becomes <font color="#008000">CDaoRecordView</font>. One big difference between
ODBC and DAO, however, is the way in which the system implements the libraries. ODBC is implemented as a set of DLLs, whereas DAO is implemented as OLE objects. Using OLE objects makes DAO a bit more up to date, at least as far as architecture goes, than
ODBC.</P>
<P>Although DAO is implemented as OLE objects, you don't have to worry about dealing with those objects directly. The MFC DAO classes handle all the details for you, providing data and function members that interact with the OLE objects. The <font
color="#008000">CDaoWorkspace</font> class provides more direct access to the DAO database-engine object through static member functions. Although MFC handles the workspace for you, you can access its member functions and data members in order to
explicitly initialize the database connection.</P>
<P>Another difference is that the DAO classes feature a more powerful set of methods that you can use to manipulate a database. These more powerful member functions enable you to perform sophisticated database manipulations without having to write a lot
of complicated C++ code or SQL statements.</P>
<ul>
<li> ODBC and DAO can both manipulate ODBC data sources. However, DAO is less efficient at this task because it is best used with .mdb database files.</P>
<li> AppWizard can create a basic database application based on either the ODBC or DAO classes. Which type of application you want to create depends—at least in some part—on the type of databases with which you'll be working.</P>
<li> ODBC and DAO both use objects of an MFC database class to provide a connection to the database being accessed. In ODBC, this database class is called <font color="#008000">CDatabase</font>, whereas in DAO the class is called <font
color="#008000">CDaoDatabase</font>. Although these classes have different names, the DAO database class contains some similar members to those found in the ODBC class.</P>
<li> ODBC and DAO both use objects of a recordset class to hold the currently selected records from the database. In ODBC, this recordset class is called <font color="#008000">CRecordset</font>, whereas in DAO the class is called <font
color="#008000">CDaoRecordset</font>. Although these classes have different names, the DAO recordset class contains not only almost the same members as the ODBC class but also a large set of additional member functions.</P>
<li> ODBC and DAO use similar procedures for viewing the contents of a data source. That is, in both cases, the application must create a database object, create a recordset object, and then call member functions of the appropriate classes to manipulate
the database.</P>
<P>Some differences between ODBC and DAO include:</P>
<li> Although both ODBC and DAO MFC classes are similar (very similar in some cases), some similar methods have different names. In addition, the DAO classes feature many member functions not included in the ODBC classes.</P>
<li> ODBC uses macros and enumerations to define options that can be used when opening record sets. DAO, on the other hand, defines constants for this purpose.</P>
<li> Under ODBC, snapshot recordsets are the default, whereas under DAO, dynamic recordsets are the default.</P>
<li> The many available ODBC drivers make ODBC useful for many different database file formats, whereas DAO is best suited to applications that will need to access only .mdb files.</P>
<li> ODBC is implemented as a set of DLLs, whereas DAO is implemented as OLE objects.</P>
<li> Under ODBC, an object of the <font color="#008000">CDatabase</font> class transacts directly with the data source. Under DAO, a <font color="#008000">CDaoWorkspace</font> object sits between the <font color="#008000">CDaoRecordset</font> and <font
color="#008000">CDaoDatabase</font> objects, thus enabling the workspace to transact with multiple database objects.</P>
</ul>
<H3><A ID="I20" NAME="I20"><B>OLE DB</B></A></H3>
<P><I>OLE DB</I> is a collection of OLE (ActiveX) interfaces that simplify access to data stored in non-database applications such as e-mail mailboxes or flat files. An application using OLE DB can integrate information from DBMS systems like Oracle, SQL
Server, or Access with information from non-database systems using the power of OLE (ActiveX).</P>
<P>A full treatment of OLE DB is outside the scope of this chapter. You need to be comfortable with OLE interfaces to use this powerful tool. If you have only created OLE (ActiveX) applications with MFC and AppWizard, you may be in for a shock when you
see what Microsoft considers "simplified." There are lots of calls to <font color="#008000">QueryInterface()</font>, and lots of variables with names like <font color="#008000">pIColsInfo</font> or <font color="#008000">rgColInfo</font>. Still,
when you wander down through all the interfaces and all the setting up, you can call a function like <font color="#008000">GetData()</font> and take information out of a non-database application just as though it was a database, and that can be a big
time-saver.</P>
<P>There is an OLE DB Programmer's Reference in the Visual C++ online documentation. Once you are familiar with OLE and ActiveX concepts, that's a great place to start.</P>
<H3><A ID="I21" NAME="I21"><B>From Here</B></A><B>...</B></H3>
<P>There's no doubt that using AppWizard and MFC's database classes makes writing database applications infinitely easier than the old-fashioned, roll-up-your-sleeves method. In fact, AppWizard can generate an fully-functional database browser with very
little help from you. Even when you have to get your hands dirty, though, implementing additional database commands in your application is just a matter of calling a few member functions. And, although the ODBC classes are adequate for most database
projects, the DAO classes are newer, more powerful, and best suited for manipulating .mdb files, such as those created by Microsoft Access.</P>
<P>For more information on related topics, please consult the following chapters:</P>
<ul>
<li> <A HREF="index02.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index02.htm" target="text">Chapter 2</A>, "Dialog Boxes and Controls," teaches you about MFC's many control classes and how you can incorpor
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -