[ Pobierz całość w formacie PDF ]
.I hope that in somefuture version of this program, I will add these features, but for now it is best if I push on and finish the book before myeditors tell me what they are really thinking about the timeline for this book's development.Descending from TChip are TPentium and TPentiumPro.As implemented here, the only thing unique aboutthese two objects is their virtual Paint methods:class TPentium: public TChip{protected:virtual void __fastcall Paint(void);public:virtual __fastcall TPentium(TComponent *AOwner): TChip(AOwner) {}virtual __fastcall TPentium(TComponent *AOwner, int ACol, int ARow): TChip(AOwner, ACol, ARow) {}};class TPentiumPro: public TChipfile:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch23.htm (35 of 48) [10/10/2000 1:15:04 AM]Ch 23 -- Creating Components from Scratch{protected:virtual void __fastcall Paint(void);public:virtual __fastcall TPentiumPro(TComponent *AOwner): TChip(AOwner) {}virtual __fastcall TPentiumPro(TComponent *AOwner, int ACol, int ARow): TChip(AOwner, ACol, ARow) {}};void __fastcall TPentium::Paint(){Canvas->Brush->Color = clPurple;Canvas->Rectangle(0, 0, ClientWidth, ClientHeight);Canvas->Brush->Color = clRed;Canvas->Ellipse(0, 0, ClientWidth, ClientHeight);}void __fastcall TPentiumPro::Paint(){Canvas->Brush->Color = clGreen;Canvas->Rectangle(0, 0, ClientWidth, ClientHeight);Canvas->Brush->Color = clBlue;Canvas->Ellipse(0, 0, ClientWidth, ClientHeight);}In other words, my implementation doesn't do much to differentiate these objects other than to leverage polymorphismto make them appear differently when they are shown on-screen.A nice touch to add to this project would be to show abitmap of a processor rather than the simple graphic I include here.As you saw in earlier chapters, all TWidget descendants also have the capability to report on their hierarchy.Thisfeature will play a role in this program when a user right-clicks on a component with the mouse.In particular, if youright-click on any of the Widget objects, a form that shows their hierarchy pops up.I will discuss that aspect of theprogram later in the chapter.Because the TWidget components are descendants of TCustomControl, they all can be hung on the Componentpallet.The following code from the Widgets unit registers the Widget and Pallet controls:void __fastcall Register()file:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch23.htm (36 of 48) [10/10/2000 1:15:04 AM]Ch 23 -- Creating Components from Scratch{TComponentClass classes[5] = {__classid(TWidget),__classid(TPentium), __classid(TPentiumPro),__classid(TPallet ), __classid(TDataPallet ) };©Copyright, Macmillan Computer Publishing.All rights reserved.RegisterComponents("Unleash", classes, 4);}That's all that needs to be said about the technical aspect of the Widget components.When all is said and done, themost important fact about these simple objects is that they all descend from the same parent.As a result, the programwill be able to use polymorphism when handling them.This turns out to be very useful, particularly duringdrag-and-drop operations.The drag-and-drop aspect of the program will be covered over the next few sections of thischapter.Introducing the Pallet ControlsThe TPallet controls are a little more complex than the Widget controls in that they can support drag and drop.Inparticular, they know how to respond when a user drops a TWidget control onto them.Before describing the drag-and-drop operation, I should spend a moment covering the heritage of the pallet controls.The TCustomPallet control from which the TDataPallet descends is pretty straightforward:class TCustomPallet : public TCustomControl{private:int FPalletNumber;TListHierarchy *FHierarchy;protected:virtual void __fastcall Paint(void);public:virtual __fastcall TCustomPallet(TComponent *AOwner);virtual __fastcall ~TCustomPallet(void){ delete FHierarchy; }TStringList *GetHierarchy() { return FHierarchy->GetHierarchy(this); }__property int PalletNumber={read=FPalletNumber, write=FPalletNumber};};This object has a field for storing the number of the pallet and, through aggregation, the capability to report on itshierarchy.file:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch23.htm (37 of 48) [10/10/2000 1:15:04 AM]Ch 23 -- Creating Components from ScratchNOTE: One of my goals in these chapters is to convince some readers of the merits of aggregation.Multiple inheritance is a powerful tool, but it adds considerable complexity to your program.In the lastfew chapters, you have had several opportunities to look at aggregation.This technique takes a little morework to implement than multiple inheritance, but I believe it often ends up saving you time in the long run,because it is so much easier to understand and maintain than multiple inheritance.My point here is not to criticize multiple inheritance, but rather to point out that aggregation is a valuabletool in its own right.There are certain settings in which each technology shines, and good programmersshould explore the benefits of both aggregation and multiple inheritance so that they will know when tofavor one method over the other.When you are in doubt, I would suggest using aggregation, because it almost never causes trouble.Multiple inheritance is easier to implement, but under certain circumstances it can cause enormousconfusion that leaves even the best programmers feeling frustrated.This is literally true.Some of the bestprogrammers I have ever met have spent days, sometimes even weeks, trying to untie the knots caused bysomeone else's unintelligent or ill-advised use of multiple inheritance.Of course, if you use multiple inheritance intelligently, it is a great tool.But one of the prerequisites forusing it intelligently is knowing when not to use it.If you are not going to use it, you need to understandthe alternatives.There is really only one good alternative to multiple inheritance, and that is aggregation.As a result, all programmers should understand both multiple inheritance and aggregation.In Widgets.h, I declare a direct descendant of TCustomPallet called TPallet:class TPallet : public TCustomPallet{public:virtual __fastcall TPallet(TComponent *AOwner): TCustomPallet(AOwner){ Width = 25; Height = 25; }__published:__property PalletNumber;__property OnDragDrop;__property OnDragOver;__property Color;};This object adds no functionality to TCustomPallet but only publishes certain of its properties.I place this objecthere for no other reason than to point out the correct way to design objects from which others may descend.If you wantto be sure that you are following the best techniques, you might want to create two classes when it might at first appearthat one will do:1.The first class provides all the functionality needed by an object.2.The second class descends from the first and publishes the properties you think you will need to use for yourparticular version of the object.When you do things this way, others can descend from the first class you created but get the option of deciding whichclasses they want to publish.file:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch23
[ Pobierz całość w formacie PDF ]