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

📄 ch09.htm

📁 好书《C++ Builder高级编程技术》
💻 HTM
📖 第 1 页 / 共 5 页
字号:
this process works.</P>
<P>Place two 
buttons on a form and label them Next and Prior, as shown in Figure
9.2.<BR>
<BR>
<A NAME="Heading7"></A><A HREF="09ebu02.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/09/09ebu02.jpg">FIGURE 9.2.</A><FONT COLOR="#000077">
</FONT><I>The Prior and Next buttons in <TT>Navy.dpr</TT> enable you to 
maneuver
through a database.</I></P>
<P><BR>
Double-click once on the Next button to create an <TT>OnClick</TT> method, and fill
it in like this:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TForm1::bbNextClick(TObject *Sender)

{

  
BioLife-&gt;Next();

}

</FONT></PRE>
<P>Perform the same action with the Prior button, so that the function associated
with it looks like this:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TForm1::bbPriorClick(TObject *Sender)

{

  
BioLife-&gt;Prior();

}

</FONT></PRE>
<P>Now run the program and click the two buttons. You will find that they easily
let you iterate through the records in a dataset.</P>
<P>Now drop down two more buttons and label them First and Last, as shown in 
Figure
9.3.<BR>
<BR>
<A NAME="Heading8"></A><A HREF="09ebu03.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/09/09ebu03.jpg">FIGURE 9.3.</A><FONT COLOR="#000077">
</FONT><I>The Navy program with all four buttons inserted.</I></P>
<P><BR>
Do the same thing for the calls to <TT>Table-&gt;First</TT> and 
<TT>Table-&gt;Last</TT>
as you did with <TT>Next</TT> and <TT>Prior</TT>:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TForm1::bbFirstClick(TObject *Sender)

{

  BioLife-&gt;First();

}

void __fastcall TForm1::bbLastClick(TObject *Sender)

{

  
BioLife-&gt;Last();

}

</FONT></PRE>
<P>Nothing could be more straightforward than these navigational functions. <TT>First</TT>
takes you to the beginning of a dataset, <TT>Last</TT> takes you to the end, and
the <TT>Next</TT> and <TT>Prior</TT> 
functions move you one record forward or backward.
<H3><A NAME="Heading9"></A><FONT COLOR="#000077">Checking for the End or Beginning
of a Dataset</FONT></H3>
<P><TT>TDataSet</TT>'s <TT>Bof</TT> is a read-only Boolean property used to check
whether or 
not you are at the beginning of a dataset. The <TT>Bof</TT> property returns
<TT>True</TT> on three occasions:

<UL>
	<LI>After you first open a file
	<P>
	<LI>After you call <TT>TDataSet-&gt;First()</TT>
	<P>
	<LI>After a call to<TT>Prior</TT> fails

</UL>

<P>The first two items listed should be obvious. Specifically, when you open a dataset,
BCB places you on the first record, and when you call <TT>First</TT>, BCB again moves
you to the beginning of the dataset. The third item, however, requires 
a little more
explanation: After you have called <TT>Prior</TT> enough times to get to the beginning
of a file, and have then tried one more time and found that the call failed, <TT>Bof</TT>
will return <TT>True</TT>.</P>
<P>The following code shows a 
common method for using <TT>Prior</TT> to get to the
beginning of a file:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TForm1::bLastToFirstClick(TObject *Sender)

{

  ListBox1-&gt;Items-&gt;Clear();

  tblAnimals-&gt;Last();

  while 
(!tblAnimals-&gt;Bof)

  {

    ListBox1-&gt;Items-&gt;Add(tblAnimals-&gt;Fields[0]-&gt;AsString);

    tblAnimals-&gt;Prior();

  }

}

</FONT></PRE>
<P>The code shown here is from the BofAndEof program found on the CD-ROM that comes
with this book. 
In this case the <TT>ListBox</TT> <TT>Add</TT> method is called on
the current record and then on every other record between the end and beginning rows
of the dataset. The loop continues until a call to <TT>Table-&gt;Prior</TT> fails
to move you back 
any further in the table. At that point <TT>Bof</TT> returns <TT>True</TT>
and the program breaks out of the loop.</P>
<P>If your dataset is connected to a data source, you can optimize a loop like the
one shown previously by setting 
<TT>DataSource1.Enabled</TT> to <TT>False</TT> before
beginning the loop, and then resetting it to <TT>True</TT> after the loop is finished.
These two lines of code enable you to iterate through the table without having to
update the visual tools at 
the same time.</P>
<P>Everything said previously about <TT>Bof</TT> also applies to <TT>Eof</TT>. In
other words, the code that follows provides a simple means of iterating over all
the records in a dataset:</P>
<PRE><FONT COLOR="#0066FF">void 
__fastcall TForm1::bFirstToLastClick(TObject *Sender)

{

  ListBox1-&gt;Clear();

  tblAnimals-&gt;First();

  while (!tblAnimals-&gt;Eof)

  {

    ListBox1-&gt;Items-&gt;Add(tblAnimals-&gt;Fields[0]-&gt;AsString);

    tblAnimals-&gt;Next();

  }


}

</FONT></PRE>
<P>The classic error in cases like this is to enter into a <TT>while</TT> or <TT>repeat</TT>
loop but to forget to call <TT>Table-&gt;Next</TT>:</P>
<PRE><FONT COLOR="#0066FF">do

{

  
ListBox1-&gt;Items-&gt;Add(tblAnimals-&gt;Fields[0]-&gt;AsString);

} while (!tblAnimals-&gt;Eof);

</FONT></PRE>
<P>If you accidentally wrote code like this, your machine would appear to lock up.
You could break out of the loop only by pressing 
Ctrl+Alt+Del and asking Windows
to kill the current process. Also, this code could cause problems if you opened an
empty table. Because the code uses a <TT>do</TT> loop, the <TT>ListBox</TT> <TT>Add</TT>
method would still be called once, even though 
there was nothing to process. As a
result, it's better to use <TT>while</TT> loops rather than <TT>do</TT> loops in
situations like this.</P>
<P><TT>Eof</TT> returns <TT>True</TT> in the following three cases:

<UL>
	<LI>If you open an empty dataset
	
<P>
	<LI>If you call <TT>Table-&gt;Last</TT>
	<P>
	<LI>If a call to<TT>Table-&gt;Next</TT> fails
</UL>


<DL>
	<DT></DT>
</DL>



<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>Iterating through tables as described
	in the 
last few paragraphs is a common process on local databases, but it is not
	as popular a technique to use with SQL servers. In particular, most client/server
	databases expect you to process individual records, or sets of records, but not to
	treat a 
table as a series of contiguous rows. This is rather a fine point to put
	on the discussion at this stage of the game, but it is something to keep in mind
	if you intend to move directly into processing large amounts of data on a server.
	If you must 
perform this kind of operation on a real server, it is probably best
	to do so from inside a stored procedure. 
<HR>


</BLOCKQUOTE>

<P>The last navigational routine that I want to cover is called <TT>MoveBy</TT>.
<TT>MoveBy</TT> enables you to move 
x number of records forward or backward in a
dataset. If you want to move two records forward, you would write the following:</P>
<PRE><FONT COLOR="#0066FF">tblAnimals-&gt;MoveBy(2);

</FONT></PRE>
<P>And if you wanted to move two records backward, 
you would write this:</P>
<PRE><FONT COLOR="#0066FF">tblAnimals-&gt;MoveBy(-2);

</FONT></PRE>
<P>When using this function, you should always remember that when you are working
on a network, datasets are fluid entities, and the record that was five 
records back
a moment ago may now be back four records, or six records, or who knows how many
records. In other words, when you are on a network, someone on another machine may
delete or add records to your database at any time. If that happens, 
<TT>MoveBy</TT>
might not work exactly as you expect. One solution to this &quot;fluidity&quot; problem
is to use the Bookmark functions mentioned later in this chapter.

<DL>
	<DT></DT>
</DL>



<BLOCKQUOTE>
	<P>
<HR>
<FONT 
COLOR="#000077"><B>NOTE:</B></FONT><B> </B><TT>Prior</TT> and <TT>Next</TT>
	are simple one-line functions that call <TT>MoveBy</TT>. If you have the source,
	look up <TT>TDataSet.Next</TT> in <TT>DB.PAS</TT>. The <TT>TDataSet</TT> object is
	a 
beautifully written wrapper around the core functionality in the BDE. 
<HR>


</BLOCKQUOTE>

<P>After reading the last two sections, you should have a good feeling for how to
move around in a dataset. The navigational commands you have been learning 
about
are very easy to use. Take the few moments necessary to be sure you understand them,
because they are likely to be part of your day-to-day BCB programming experience.
<H3><A NAME="Heading12"></A><FONT COLOR="#000077">Fields</FONT></H3>
<P>On 
most occasions when you want to programmatically access the individual fields
of a record, you can use one of the following properties or methods, all of which
belong to <TT>TDataSet</TT>:</P>
<PRE><FONT COLOR="#0066FF">__property TField 
*Fields[System::Integer Index];

__property System::Integer FieldCount;

__property System::Variant Value;

TField *__fastcall FieldByName(const System::AnsiString FieldName);

</FONT></PRE>
<P>The <TT>Fields</TT> property is one of the most important 
single syntactical elements
of the VCL. It consists of an array of <TT>TField</TT> objects, each of which is
automatically assigned to a separate field in a table. For instance, if a table called
<TT>Address</TT> had five fields called <TT>Name</TT>, 
<TT>Address</TT>, <TT>City</TT>,
<TT>State</TT> and <TT>Zip</TT>, BCB would automatically create five field objects
when you accessed the <TT>Address</TT> table. You don't have to do anything to create
these field objects; they are given to you 
automatically.</P>
<P>The <TT>Fields</TT> array for the hypothetical <TT>Address</TT> table mentioned
in the last paragraph would have five members. <TT>Fields[0]</TT> would access the
<TT>Name</TT> field, <TT>Fields[1]</TT> would access the 
<TT>Address</TT> field,
and so on.</P>
<P>The <TT>TField</TT> object is declared in <TT>DB.HPP</TT>. This is an extremely
powerful, and fairly complex object, which is worth your while to study in depth.
For instance, here are some of the methods of 
the <TT>TField</TT> object: <BR>
<BR>

<TABLE BORDER="1">
	<TR ALIGN="LEFT" rowspan="1">
		<TD WIDTH="103" ALIGN="LEFT"><TT>Assign</TT></TD>
		<TD ALIGN="LEFT">Assigns one field to another.</TD>
	</TR>
	<TR ALIGN="LEFT" rowspan="1">
		<TD WIDTH="103" 
ALIGN="LEFT"><TT>Clear</TT></TD>
		<TD ALIGN="LEFT">Sets the field to <TT>NULL</TT>.</TD>
	</TR>
	<TR ALIGN="LEFT" rowspan="1">
		<TD WIDTH="103" ALIGN="LEFT"><TT>FocusControl</TT></TD>
		<TD ALIGN="LEFT">Sets the focus of the form to the first 
control that hosts the field.</TD>
	</TR>
	<TR ALIGN="LEFT" rowspan="1">
		<TD WIDTH="103" ALIGN="LEFT"><TT>GetData</TT></TD>
		<TD ALIGN="LEFT">Gets raw data from a field in a buffer. Contrast with <TT>AString</TT>, <TT>AsInteger</TT>.</TD>
	</TR>
	
<TR ALIGN="LEFT" rowspan="1">
		<TD WIDTH="103" ALIGN="LEFT"><TT>SetData</TT></TD>
		<TD ALIGN="LEFT">Sets the field to raw data held in a pointer. Contrast with <TT>AsString</TT> or
			<TT>AsInteger</TT>.</TD>
	</TR>
	<TR ALIGN="LEFT" rowspan="1">
		
<TD WIDTH="103" ALIGN="LEFT"><TT>IsValidChar</TT></TD>
		<TD ALIGN="LEFT">Tests to see if a character is within the range of valid values for a particular
			field.</TD>

⌨️ 快捷键说明

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