📄 ch23.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
<META NAME="Author" Content="Steph Mineart">
<TITLE>Ch 23 -- Creating Components from Scratch</TITLE>
</HEAD>
<BODY BACKGROUND="bg1.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/bg1.gif" BGCOLOR="#FFFFFF">
<P ALIGN="CENTER"><IMG SRC="sams.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/sams.gif" WIDTH="75" HEIGHT="24" ALIGN="BOTTOM"
BORDER="0"><BR>
<BR>
<A HREF="index-3.htm" tppabs="http://pbs.mcp.com/ebooks/0672310228/index.htm"><IMG SRC="toc.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/toc.gif" WIDTH="40" HEIGHT="40" ALIGN="BOTTOM"
ALT="TOC" BORDER="0" NAME="toc4"></A><A HREF="ch22.htm" tppabs="http://pbs.mcp.com/ebooks/0672310228/ch22.htm"><IMG SRC="back-1.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/back.gif"
WIDTH="40" HEIGHT="40" ALIGN="BOTTOM" ALT="BACK" BORDER="0" NAME="toc1"></A><A HREF="ch24.htm" tppabs="http://pbs.mcp.com/ebooks/0672310228/ch24.htm"><IMG
SRC="forward.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/forward.gif" WIDTH="40" HEIGHT="40" ALIGN="BOTTOM"
ALT="FORWARD" BORDER="0"
NAME="toc2"></A></P>
<H2 ALIGN="CENTER"><FONT COLOR="#000077">Charlie Calvert's C++ Builder Unleashed</FONT></H2>
<P>
<H2 ALIGN="CENTER"><A NAME="Heading1"></A><FONT COLOR="#000077">- 23 -</FONT></H2>
<H2 ALIGN="CENTER"><A
NAME="Heading2"></A><FONT COLOR="#000077">Creating Components
from Scratch</FONT></H2>
<P>In this chapter, you learn how to use custom-made components to help create programs
that solve at least a minimal set of real-world problems. In particular, the
program
demonstrated in this chapter provides a minimal implementation of a warehouse-based
inventory program. This chapter also covers designing components and screens that
mirror objects in the real world, as well as creating your own event
handlers.</P>
<P>Much of the material in this chapter follows naturally from the subject matter
in the preceding chapter. However, the code shown here is more advanced, and the
text looks a little more deeply into the theories involved in creating
powerful,
reusable components.</P>
<P>A program called Warehouse forms the core of this chapter. Warehouse uses simple
graphic objects to depict a warehouse in which several different kinds of widgets
are stored. There are seven panels in this
warehouse, each containing from 4 to 12
pallets full of widgets. You are able to stock each pallet with new widgets and ask
questions about the stock stored in the warehouse.</P>
<P>The program in this chapter builds on the object hierarchy discussed
in Chapter
19, "Inheritance," in the program called OBJECT1. The new versions of this
hierarchy advances the code to the point where it can be used for the relatively
practical tasks just described. OOP, which seems highly theoretical and
intangible
at first glance, actually turns out to be a natural tool for tracking and depicting
the status of real objects, such as the inventory in a warehouse.
<H3><A NAME="Heading3"></A><FONT COLOR="#000077">Warehouse</FONT></H3>
<P>As described at
the beginning of this chapter, Warehouse is a simulation that
features a series of panels arranged in a large room. Each panel has from 4 to 12
pallets on it, and each pallet contains a certain number of widgets. Users can stock
additional widgets on
the pallets by dragging and dropping them from a central gateway
that leads into the warehouse. The idea is that the widgets are being transferred
from the point of manufacture to a place where they can be stored before being sold.
<DL>
<DT></DT>
</DL>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>The Warehouse program shows the
outlines of a clean approach to a real-world problem. However, it is not a complete
business application. It shows how objects can be
used to embody actual entities
that we find in day-to-day life, but it's a theoretical example and not a real-world
program. <BR>
<BR>
To bring this program up to the point where it might be used in an office would be
a considerable chore that
would involve adding both features and error checking.
However, in the construction of any large project, one key step is the development
of a methodology that can support a large application. The foundation for a useful
program is found in
Warehouse. It shows a lot about the way any good OOP tool should
be constructed.
<HR>
</BLOCKQUOTE>
<P>The Warehouse program is stocked with hypothetical widgets named <TT>TWidget</TT>,
<TT>TPentium</TT>, and <TT>TPentiumPro</TT>. Another
application might have <TT>TChairs</TT>,
<TT>TTables</TT>, <TT>TBureaus</TT>, and so on, instead of chips. The issue is not
the names or traits of the individual widgets but the fact that a series of different
<TT>TWidget</TT> descendants needs to be
created.</P>
<P>You will find that <TT>TPentium</TT> and <TT>TPentiumPro</TT> share many traits.
This is a somewhat artificial aspect of this program; in a real-world application,
each of these objects would be more varied. For instance, a
<TT>TChair</TT> would
have an <TT>FLegs</TT> data store, a <TT>TBed</TT> would have an <TT>FFrame</TT>
data store, and so on.
<DL>
<DT></DT>
</DL>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>When studying Warehouse,
you will
find that the <TT>TWidget</TT> object has changed slightly from its appearance in
OBJECT3. These types of minor structural changes should be expected in OOP. Developers
don't start with a base class and build up a hierarchy without ever
deciding that
changes need to be made to the structures they are creating. Frameworks and hierarchies
evolve over time; they do not burst into the world fully formed. <BR>
<BR>
If you are building a certain kind of tool, after the first release,
it is very dangerous
to go back and start changing the way base classes work. Nevertheless, during development,
changes need to be made to the base classes in your hierarchy. This is one of the
major "gotchas" of object-oriented
programming, and I would be remiss if
I didn't lay it out in clear terms. Right now, there are no good remedies for this
problem, but the lesson it teaches is clear: Don't release objects to unsuspecting
programmers until you are sure you have the
proper design! If you are looking for
some relief, my experience has shown that most major companies don't think beta testers
fit the definition of "unsuspecting." <BR>
<BR>
Furthermore, to the best of your ability, you should do
everything possible to hide
the actual implementation of your object from your user. Use properties heavily.
Hide your data. Create public functions or even public objects that call the functions
and objects that are part of your real
implementation. Nobody ever hides their implementation
completely, but it is usually better to err on the side of safety, rather than striving
always to save a few bytes of memory.
<HR>
</BLOCKQUOTE>
<P>The Warehouse program features one main
form and two child forms used to display
reports on the data in the warehouse. The main form depicts the floor of the warehouse,
as shown in Figure 23.1. The left-center of the main form contains three widgets
you can drag onto the various pallets by
using the mouse. To do this, left-click
on one of the widgets and drag the mouse over one of the pallets. When you release
the mouse, a dialog box pops up prompting you for the number of widgets of a particular
type you want to drop on a pallet. You
can type in a number and then click OK, as
shown in Figure 23.2.<BR>
<BR>
<A NAME="Heading6"></A><A HREF="23ebu01.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/23/23ebu01.gif">FIGURE 23.1.</A><FONT COLOR="#000077">
</FONT><I>The Warehouse form shows the floor of the warehouse.</I>
<H6></H6>
<P><A
NAME="Heading7"></A><A HREF="23ebu02.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/23/23ebu02.gif">FIGURE 23.2.</A><FONT COLOR="#000077">
</FONT><I>Specifying the number of items you want to drop on a particular pallet.</I></P>
<P>If you select File | Show Table from the menu on the main form, you
can see a
table that lists all the items in the warehouse, as shown in Figure 23.3. If you
select Options | List by Product from the menu, you get a report on all the products
in the warehouse, as shown in Figure 23.4. If you select Options | List by
Pallet
from the menu, you get a report on all the pallets in the warehouse, as shown in
Figure 23.5.<BR>
<BR>
<A NAME="Heading8"></A><A HREF="23ebu03.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/23/23ebu03.jpg">FIGURE 23.3.</A><FONT COLOR="#000077">
</FONT><I>The Report form shows the status of the
objects on an individual pallet.</I>
<H6></H6>
<P><A NAME="Heading9"></A><A HREF="23ebu04.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/23/23ebu04.jpg">FIGURE 23.4.</A><FONT COLOR="#000077">
</FONT><I>A report on all the products in the warehouse, including their count and
value.</I>
<H6></H6>
<P><A
NAME="Heading10"></A><A HREF="23ebu05.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/23/23ebu05.jpg">FIGURE 23.5.</A><FONT COLOR="#000077">
</FONT><I>A report on all the pallets in the warehouse, including the number of widgets
they contain and the value of the widgets.</I></P>
<P>If you right-click
on a particular pallet, you can bring up a popup menu that
lets you explore the contents of a particular pallet. For instance, you can see the
items on a pallet, as shown in Figure 23.6, or you can see the value of the items
on a particular pallet, as
shown in Fig- ure 23.7.</P>
<P>Because of time constraints, I have not added any provisions to the program for
selling items. However, you do have a fairly interesting simulation that models a
portion of a business.</P>
<P>Perhaps the most interesting
thing about the program is the small amount of top-level
code needed to create it, as shown in Listing 23.1.<BR>
<BR>
<A NAME="Heading11"></A><A HREF="23ebu06.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/23/23ebu06.jpg">FIGURE 23.6.</A><FONT COLOR="#000077">
</FONT><I>A report on the items found on
a particular pallet.</I>
<H6></H6>
<P><A NAME="Heading12"></A><A HREF="23ebu07.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/23/23ebu07.jpg">FIGURE 23.7.</A><FONT COLOR="#000077">
</FONT><I>A report on the value of the items found on a particular pallet.</I>
<H3 ALIGN="CENTER"></H3>
<P><A
NAME="Heading13"></A><FONT COLOR="#000077"><B>Listing 23.1. The project file
for the Warehouse program is listed here; the rest of the program is found on the
CD.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">///////////////////////////////////////
//
Warehouse.cpp
// Warehouse example: learning about objects
// Copyright (c) 1997 by Charlie Calvert
//
#include <vcl\vcl.h>
#pragma hdrstop
USEFORM("Main.cpp", Form1);
USERES("WareHouse.res");
USEUNIT("\SrcC\PUnleash\Utils\MyObject.cpp");
USEUNIT("\SrcC\PUnleash\Utils\Widgets.cpp");
USEDATAMODULE("DMod1.cpp", DMod);
USEFORM("DataForm1.cpp", DataForm);
USEFORM("QueryForm1.cpp",
QueryForm);
USEFORM("HierarchyDlg1.cpp", HierarchyDlg);
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
Application->Initialize();
Application->CreateForm(__classid(TForm1), &Form1);
Application->CreateForm(__classid(TDMod), &DMod);
Application->CreateForm(__classid(TDataForm), &DataForm);
Application->CreateForm(__classid(TQueryForm), &QueryForm);
Application->CreateForm(__classid(THierarchyDlg), &HierarchyDlg);
Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
return 0;
}
</FONT></PRE>
<P>If you wind
your way down the hierarchy of objects used in this program (see Listings
23.2 through 23.15), there is, of course, a considerable amount of complexity. But
from the point of view of the application developer, the code for this program is
very easy to
create. Most of the complexity is in the VCL itself, and some degree
of complexity is hidden in the <TT>TWidget</TT> and <TT>TPallet</TT> objects created
in this chapter, and in some of the earlier chapters. But at the top level, where
you find the
main modules for this program, almost all the code is sparse, easy to
understand, and simple to maintain. This is the right way to leverage objects so
they can help you get a lot of high-quality work done quickly.<BR>
<BR>
<A
NAME="Heading14"></A><FONT COLOR="#000077"><B>Listing 23.2. The header file for
the main program.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">///////////////////////////////////////
// Main.h
// Warehouse example: learning about objects
// 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\ExtCtrls.hpp>
#include
<vcl\Buttons.hpp>
#include <vcl\Menus.hpp>
#include "Widgets.h"
class TForm1 : public TForm
{
__published:
TPanel *Panel1;
TPanel *Panel2;
TPanel *Panel3;
TPanel *Panel4;
TDataPallet *sp41;
TDataPallet
*Sp42;
TDataPallet *Sp43;
TDataPallet *Sp44;
TDataPallet *Sp45;
TDataPallet *Sp46;
TDataPallet *Sp47;
TDataPallet *Sp48;
TDataPallet *Sp49;
TDataPallet *Sp410;
TPanel *Panel5;
TDataPallet *DataPallet10;
TPanel *Panel6;
TPanel *Panel7;
TMainMenu *A;
TMenuItem *List;
TPentiumPro *PentiumPro;
TPentium *Pentium;
TWidget *Widget;
TDataPallet *DataPallet35;
TMenuItem *File1;
TMenuItem *ShowTable1;
TMenuItem *N1;
TMenuItem *Exit1;
TPopupMenu *PopupMenu1;
TMenuItem *ItemsOnPallet1;
TMenuItem *ValueofItems1;
TMenuItem *Options1;
TMenuItem *ListbyPallet1;
TMenuItem *GetHierarchy1;
TLabel *Label1;
TLabel *Label2;
void __fastcall SpeedButton1DragOver(TObject
*Sender, TObject *Source, int X,
int Y, TDragState State, bool &Accept);
void __fastcall WidgetMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X,
int Y);
void __fastcall Exit1Click(TObject *Sender);
void __fastcall ShowTable1Click(TObject *Sender);
void __fastcall DataPallet10MouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int
X, int Y);
void __fastcall ItemsOnPallet1Click(TObject *Sender);
void __fastcall ValueofItems1Click(TObject *Sender);
void __fastcall ListClick(TObject *Sender);
void __fastcall ListbyPallet1Click(TObject *Sender);
void __fastcall
GetHierarchy1Click(TObject *Sender);
private:
public:
virtual __fastcall TForm1(TComponent* Owner);
};
extern TForm1 *Form1;
#endif
</FONT></PRE>
<P><A NAME="Heading15"></A><FONT COLOR="#000077"><B>Listing 23.3. The main form for
the
Warehouse program.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">///////////////////////////////////////
// Main.cpp
// Warehouse example: learning about objects
// Copyright (c) 1997 by Charlie Calvert
//
#include <vcl\vcl.h>
#pragma hdrstop
#include "Main.h"
#include "DMod1.h"
#include "DataForm1.h"
#include "QueryForm1.h"
#include "HierarchyDlg1.h"
#pragma link "Widgets"
#pragma resource "*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
void __fastcall TForm1::SpeedButton1DragOver(TObject *Sender, TObject *Source,
int X, int Y,
TDragState State, bool &Accept)
{
if (!dynamic_cast<TWidget *>(Source))
Accept = False;
}
void __fastcall TForm1::WidgetMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X,
int Y)
{
if (!dynamic_cast<TWidget *>(Sender))
return;
TWidget *W = (TWidget *)(Sender);
if (Shift.Contains(ssLeft))
{
W->BeginDrag(False);
}
else
{
HierarchyDlg->ListBox1->Items =
W->GetHierarchy();
HierarchyDlg->ShowModal();
}
}
void __fastcall TForm1::ShowTable1Click(TObject *Sender)
{
DataForm->Show();
}
void __fastcall TForm1::Exit1Click(TObject *Sender)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -