📄 ch17.htm
字号:
sorted first by record type, and secondly by artist. That way, all the Bob Dylan
albums that I consider to be folk records appear together, and all the Dylan albums
that I think are rock albums are grouped
together. Inside of each type, I group the
albums alphabetically. The query also does lookups into the <TT>Types</TT> and <TT>Loudness</TT>
tables so I can substitute human-readable strings for the numeric codes found in
the <TT>Albums</TT> table.
<H3
ALIGN="CENTER"></H3>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>Queries not only have the power
to solve complicated problems, but they are also fun to use and can therefore spice
up the mundane task of creating a
report. They can also be reused in the main body
of your program. Often, it makes sense to place queries like this inside a stored
procedure.
<HR>
</BLOCKQUOTE>
<P>After creating the query, I need to create a calculated field called
<TT>FirstLast</TT>
that gives me a single string containing the first and last names:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TAlbumGroupForm::AlbumQueryCalcFields(TDataSet *DataSet)
{
AlbumQueryFirstLast->Value =
AlbumQueryFIRST->Value + " " + AlbumQueryLAST->Value;
}
</FONT></PRE>
<P>There is no need to create lookup fields for the <TT>Loudness</TT> and <TT>Types</TT>
values because I retrieved the strings associated with these fields from
the <TT>Loudness</TT>
and <TT>Types</TT> tables in the original query.</P>
<P>After writing the query, most of the work I need to do for the report is done.
Now I can simply drop down some <TT>TQRBand</TT> components, a <TT>TQuickReport</TT>
component, and a <TT>TQRGroup</TT> component, and link them together as explained
earlier in the chapter. I perform the grouping on the <TT>Types</TT> field from the
query.</P>
<P>On the <TT>rbGroupHeader</TT> band I drop down a <TT>TQRDBText</TT>
control that
is set equal to the <TT>Types</TT> field. I then add fields <TT>rbDetail</TT> band
that will display each artist's name, each album's name, and each's loudness and
type. The final report looks like the image shown in Figure 17.8, and the
design
time shape of the form is shown in Figure 17.9.<BR>
<BR>
<A NAME="Heading18"></A><A HREF="17ebu08.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/17/17ebu08.jpg">FIGURE 17.8.</A><FONT COLOR="#000077">
</FONT><I>The Album Group report as it appears in print preview mode.<BR>
</I><BR>
<A
NAME="Heading19"></A><A HREF="17ebu09.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/17/17ebu09.jpg">FIGURE 17.9.</A><FONT COLOR="#000077">
</FONT><I>The Album Group report as it appears at design time.</I></P>
<P>That is all I want to say about QuickReport in this book. If you want additional
examples of using QuickReport, you should view the kdAdd program.</P>
<H4><A NAME="Printing Forms"></A><FONT COLOR="#000077">Printing Forms</FONT></H4>
<P>One of the easiest ways to print information in BCB is to simply send the image
of a form to a
printer. The code for doing this is trivial in the extreme:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TForm1::Print1Click(TObject *Sender)
{
Form1->Print();
}
</FONT></PRE>
<P>It doesn't get any easier than this.</P>
<P>On the CD that
accompanies this book, you will find a program called PrintForm
that contains a menu item that will print the contents of the current form. This
option will not help you print a dataset, but it will print whatever you can see
on the current form. For
instance, the PrintForm program prints the current form
as shown in Figure 17.10, minus the menu, border, and caption areas. The quality
of the picture in the printed output can differ depending on a number of factors.<BR>
<BR>
<A
NAME="Heading20"></A><A HREF="17ebu10.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/17/17ebu10.jpg">FIGURE 17.10.</A><FONT COLOR="#000077">
</FONT><I>The main form of the PrintForm application just as the user selects the
Print option from the menu.</I></P>
<P>The Address2 program gives you the
option of printing a series of forms. In particular,
it iterates through the database, printing one form, on one page, for each record
in the database. This is a waste of resources, but it does produce clean-looking,
easy-to-read reports. However, the
user would have to turn the page each time he
or she views a new record. This task is so onerous that it leaves this solution virtually
useless for all but a few, unusual tasks.</P>
<P>Here is the code that prints all the forms in the Address2
program:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TForm1::PrintForms1Click(TObject *Sender)
{
if (ScalingForm->ShowModal() == mrOk)
{
switch (ScalingForm->ScalingOptions->ItemIndex)
{
case 0: PrintScale = poNone;
break;
case 1: PrintScale = poProportional; break;
case 2: PrintScale = poPrintToFit; break;
}
Panel2->Visible = False;
DBGrid1->Visible = False;
DMod->AddressTable->First();
while
(!DMod->AddressTable->Eof)
{
Print();
DMod->AddressTable->Next();
}
DBGrid1->Visible = True;
Panel2->Visible = True;
}
}
</FONT></PRE>
<P>This code first pops up a custom dialog like the one
shown in Figure 17.11. This
dialog lets you choose three printing options provided by the <TT>TForm</TT> object
in a property called <TT>PrintScale</TT>. The print options (<TT>poNone</TT>, <TT>poProportional</TT>,
<TT>poPrintToFit</TT>) are declared
in <TT>Forms.hpp</TT>.</P>
<P>If you choose <TT>PrintToFit</TT>, your form will take up the maximum amount of
space it can on the pages you are printing. In short, it will expand to fill the
available space but will continue to remain in proportion.
That is, it won't be stretched
but will expand as far as it can in both the horizontal and vertical directions.
When it reaches the limit in either direction, it will stop expanding in both directions,
so that the view you have of the form remains
proportional.</P>
<P>The code for this routine also makes invisible all the controls on the form that
are not needed when printing. For instance, the buttons on the form serve no purpose
on the printed form, so I make them invisible. A second solution
is to create a custom
form featuring only the portions of this view that need to be printed.</P>
<P>The code then iterates through the database, printing each form:</P>
<PRE><FONT COLOR="#0066FF">DMod->AddressTable->First();
while
(!DMod->AddressTable->Eof)
{
Print();
DMod->AddressTable->Next();
}
</FONT></PRE>
<P><FONT COLOR="#0066FF"><BR>
<A NAME="Heading21"></A></FONT><A HREF="17ebu11.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/17/17ebu11.jpg">FIGURE 17.11.</A><FONT
COLOR="#000077"> </FONT><I>The
Scaling form dialog gives you a chance to choose how
the reports will look when printed.</I></P>
<P>Be careful, because with this kind of code, it's easy to get stuck in an endless
loop by forgetting to call <TT>Next()</TT>. This is a no-brainer error
that everyone
can see why it is a mistake, but people still tend to make it when they are rushed
or tired.</P>
<H3><A NAME="TPrinter: Printing Text, Shapes,"></A><FONT COLOR="#000077">TPrinter:
Printing Text, Shapes, and Bitmaps</FONT></H3>
<P>There
are two easy ways to send output directly to the printer from a VCL program.
One is to open up the printer as a device and send output to it, and the second is
to use the VCL <TT>TPrinter</TT> object. The program shown in this section uses the
latter
method.</P>
<P><TT>TPrinter</TT> provides a <TT>TCanvas</TT> object initialized to the DC for
the printer. As a result, you can send text or graphics objects to the printer just
as easily as you can send them to the screen.</P>
<P>The PrintGDI program
found on the CD that accompanies this book shows how to print
text, shapes, and bitmaps using the <TT>TPrinter</TT> object. It consists of three
forms, shown in Figures 17.12, 17.13, and 17.14. The source for the program is shown
in Listings 17.1.
through 17.6.<BR>
<BR>
<A NAME="Heading22"></A><A HREF="17ebu12.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/17/17ebu12.jpg">FIGURE 17.12.</A><FONT COLOR="#000077">
</FONT><I>The text from a Shakespearean sonnet shown in a form. You can use the program
to print the text.<BR>
</I><BR>
<A
NAME="Heading23"></A><A HREF="17ebu13.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/17/17ebu13.jpg">Figure 17.13.</A><FONT COLOR="#000077">
</FONT><I>The form shown here has a <TT>TPaintBox</TT> component with some shapes
drawn in it. You can print the contents of the paint box.</I><BR>
<BR>
<A
NAME="Heading24"></A><A HREF="17ebu14.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/17/17ebu14.jpg">FIGURE 17.14.</A><FONT COLOR="#000077">
</FONT><I>This form can display bitmaps and also send their contents to the printer.</I>
<H3 ALIGN="CENTER"></H3>
<P><A NAME="Heading25"></A><FONT
COLOR="#000077"><B>Listing 17.1. The header for
the main module of the PrintGDI program.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">///////////////////////////////////////
// File: Main.h
// Project: PrintText
// Copyright (c) 1997 by Charlie
Calvert
//
#ifndef MainH
#define MainH
#include <vcl\Classes.hpp>
#include <vcl\Controls.hpp>
#include <vcl\StdCtrls.hpp>
#include <vcl\Forms.hpp>
#include <vcl\Buttons.hpp>
#include <vcl\ExtCtrls.hpp>
#include <vcl\Menus.hpp>
#include <vcl\Dialogs.hpp>
class TForm1 : public TForm
{
__published:
TMainMenu *MainMenu1;
TMenuItem *File1;
TMenuItem *ShapeForm1;
TMenuItem *Print1;
TMenuItem *N1;
TMenuItem *Exit1;
TPrintDialog *PrintDialog1;
TMemo *Memo1;
TMenuItem *Open1;
TOpenDialog *OpenDialog1;
TMenuItem *N2;
TMenuItem *BitmapForm1;
void __fastcall Print1Click(TObject *Sender);
void __fastcall Open1Click(TObject *Sender);
void
__fastcall ShapeForm1Click(TObject *Sender);
void __fastcall BitmapForm1Click(TObject *Sender);
private:
void SendToPrinter();
void PrintText(TCanvas *Canvas);
public:
__fastcall TForm1(TComponent* Owner);
};
extern TForm1 *Form1;
#endif
</FONT></PRE>
<P><A NAME="Heading26"></A><FONT COLOR="#000077"><B>Listing 17.2. The main module
for the PrintGDI program.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">///////////////////////////////////////
// File: Main.cpp
// Project:
PrintText
// Copyright (c) 1997 by Charlie Calvert
//
#include <vcl\vcl.h>
#include <vcl\printers.hpp>
#pragma hdrstop
#include "Main.h"
#include "PaintBoxPrint.h"
#include "PrintBmp1.h"
#pragma
resource "*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
void TForm1::PrintText(TCanvas *Canvas)
{
int i, x;
AnsiString S("Test String");
x = Canvas->TextHeight(S);
for
(i = 0; i < Memo1->Lines->Count; i++)
{
S = Memo1->Lines->Strings[i];
Canvas->TextOut(1, x * i, S);
}
}
void TForm1::SendToPrinter()
{
TPrinter *APrinter = Printer();
APrinter->BeginDoc();
PrintText(APrinter->Canvas);
APrinter->EndDoc();
}
void __fastcall TForm1::Print1Click(TObject *Sender)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -