📄 ch20.htm
字号:
{
void __fastcall Register()
{
TComponentClass classes[1] = {__classid(TWidget)};
RegisterClasses(classes, 0);
}
}
TWidget
*ReadWidgetFromStream(AnsiString StreamName)
{
Widgets::Register();
TFileStream *Stream = new TFileStream(StreamName, fmOpenRead);
TWidget *Widget = (TWidget *)Stream->ReadComponent(NULL);
delete Stream;
return Widget;
}
</FONT></PRE>
<P>This code first registers the <TT>TWidget</TT> type with the system. This is necessary
because the VCL needs to know what type of object you want to stream. Of course,
when working with components that are placed on the Component
Palette, you can be
sure the system has already registered the object for you. However, if you did not
drop a component on a form but created it by hand, you might have to register the
component before you can stream it.</P>
<P>The <TT>Register</TT>
method needs to appear in its own namespace because there
will be many register functions in a typical application--at least one for each component.
Most of the time this function will be called automatically by the compiler, and
it is a bit unusual
for you to have to call it explicitly.</P>
<P>Notice that the compiler will automatically construct an object for you if you
pass in <TT>NULL</TT> when calling <TT>ReadComponent</TT>:</P>
<PRE><FONT COLOR="#0066FF">TWidget *Widget = (TWidget
*)Stream->ReadComponent(NULL);
</FONT></PRE>
<P>Alternatively, you can create the component yourself and then pass it to <TT>ReadComponent</TT>
so that its properties will be lifted from the stream.</P>
<P>In the last few pages, you had a good
look at the Widget2 program. There are several
additional traits of properties that should be explored, however, before moving on
to the colorful warehouse simulation found in the next chapter.
<H3><A NAME="Heading23"></A><FONT COLOR="#000077">More on
Properties</FONT></H3>
<P>BCB provides support for five different types of properties:
<UL>
<LI>Simple properties are declared to be integers, characters, or strings.
<P>
<LI>Enumerated properties are declared to be of some enumerated type. When
shown
in the Object Inspector, you can view them with a drop-down list.
<P>
<LI>Set properties are declared to be of type <TT>Set</TT>. <TT>BorderIcons</TT>
from <TT>TForm</TT> is an example of this type of property. You can choose only one
enumerated value at a time, but you can combine several values in a property of type
<TT>Set</TT>.
<P>
<LI>Object properties are declared to be of some object type, such as the <TT>Items</TT>
property from the <TT>TListBox</TT> component, which is
declared to be of type <TT>TStrings</TT>.
<P>
<LI>Array properties are like standard arrays, but you can index on any type, even
a string. The classic example of this kind of property is the <TT>Strings</TT> property
in a <TT>TStringList</TT>.
</UL>
<P>The PropertyTest program (in Listing 20.6) gives an example of each of the five
types of properties. It also gives the <TT>TStringList</TT> object a fairly decent
workout. The program itself is only minimally useful outside the range of a
purely
academic setting such as this book.<BR>
<BR>
<A NAME="Heading24"></A><FONT COLOR="#000077"><B>Listing 20.6. The main unit for
the PropertyTest program.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">///////////////////////////////////////
//
Main.cpp
// Learning about properties
// Copyright (c) 1997 by Charlie Calvert
//
#include <vcl\vcl.h>
#pragma hdrstop
#include "Main.h"
#include "propertyobject1.h"
#pragma resource "*.dfm"
TForm2 *Form2;
//--------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------
void __fastcall
TForm2::bCreateObjectsClick(TObject *Sender)
{
TMyProps *M;
char Ch;
int i;
M = new TMyProps(this);
M->Parent = this;
M->SimpleProp = 25;
M->EnumProp = teEnum;
M->SetProp = TSetProp() << teEnum <<
teSet;
M->StrArrayProp["Jones"] = "Sam, Mary";
M->StrArrayProp["Doe"] = "John, Johanna";
ListBox1->Items->Add(M->StrArrayProp["Doe"]);
ListBox1->Items->Add(M->StrArrayProp["Jones"]);
for (i = 0; i < M->ObjectProp->Count; i++)
ListBox2->Items->Add(M->ArrayProp[i]);
Ch = M->Default1;
ListBox1->Items->Add(Ch);
}
</FONT></PRE>
<P><A NAME="Heading25"></A><FONT COLOR="#000077"><B>Listing 20.7. The header file
for the PropertyObject unit.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">///////////////////////////////////////
// PropertyObject.h
// Learning about
properties
// Copyright (c) 1997 by Charlie Calvert
//
#ifndef PropertyObject1H
#define PropertyObject1H
enum TEnumType {teSimple, teEnum, teSet, teObject, teArray};
typedef Set<TEnumType, teSimple, teArray> TSetProp;
class TCouple:
public TObject
{
public:
AnsiString Husband;
AnsiString Wife;
TCouple() {}
};
class TMyProps: public TCustomControl
{
private:
int FSimple;
TEnumType FEnumType;
TSetProp FSetProp;
TStringList
*FObjectProp;
char FDefault1;
AnsiString __fastcall GetArray(int Index);
AnsiString __fastcall GetStrArray(AnsiString S);
void SetStrArray(AnsiString Index, AnsiString S);
protected:
void virtual __fastcall Paint();
public:
virtual __fastcall TMyProps(TComponent *AOwner);
virtual __fastcall ~TMyProps();
__property AnsiString ArrayProp[int i]={read=GetArray};
__property AnsiString StrArrayProp[AnsiString i]=
{read=GetStrArray,write=SetStrArray};
__published:
__property int SimpleProp={read=FSimple, write=FSimple};
__property TEnumType EnumProp={read=FEnumType, write=FEnumType};
__property TSetProp SetProp={read=FSetProp, write=FSetProp};
__property TStringList *ObjectProp={read=FObjectProp, write=FObjectProp};
__property char Default1={read=FDefault1, write=FDefault1, default= `1'};
};
#endif
</FONT></PRE>
<P><A NAME="Heading26"></A><FONT COLOR="#000077"><B>Listing 20.8.
The source for
the PropertyTest unit shows how to work with properties.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">///////////////////////////////////////
// PropertyObject.cpp
// Learning about properties
// Copyright (c) 1997 by Charlie Calvert
//
#include <vcl\vcl.h>
#pragma hdrstop
#include "PropertyObject1.h"
#include "codebox.h"
__fastcall TMyProps::TMyProps(TComponent *AOwner)
:TCustomControl(AOwner)
{
Width = 100;
Height = 100;
Left =
(((TForm*)(AOwner))->ClientWidth / 2) - (Width / 2);
Top = (((TForm*)(AOwner))->ClientHeight / 2) - (Height / 2);
FObjectProp = new TStringList();
Default1 = `1';
};
__fastcall TMyProps::~TMyProps()
{
int i;
for (i = 0; i <
FObjectProp->Count; i++)
{
FObjectProp->Objects[i]->Free();
}
FObjectProp->Free();
}
void __fastcall TMyProps::Paint()
{
Canvas->Brush->Color = clBlue;
TCustomControl::Paint();
Canvas->Rectangle(0, 0,
Width, Height);
Canvas->TextOut(1, 1, "FSimple: " + IntToStr(FSimple));
Canvas->TextOut(1, Canvas->TextHeight("Blaise"), GetArray(0));
Canvas->TextOut(1, Canvas->TextHeight("Blaise") * 2,
FObjectProp->Strings[1]);
};
AnsiString __fastcall TMyProps::GetArray(int Index)
{
return FObjectProp->Strings[Index];
}
AnsiString __fastcall TMyProps::GetStrArray(AnsiString S)
{
TCouple *Couple;
Couple =
(TCouple*)(FObjectProp->Objects[FObjectProp->IndexOf(S)]);
return Couple->Husband + ", " + Couple->Wife;
}
AnsiString GetHusband(AnsiString S)
{
return StripLastToken(S, `,');
}
AnsiString GetWife(AnsiString S)
{
return StripFirstToken(S, `,');
}
void TMyProps::SetStrArray(AnsiString Index, AnsiString S)
{
TCouple *Couple;
Couple = new TCouple();
Couple->Husband = GetHusband(S);
Couple->Wife = GetWife(S);
FObjectProp->AddObject(Index, Couple);
}
</FONT></PRE>
<P>The structure of the PropertyTest program is simple. There is a main form with
a button on it. If you click the button, you instantiate an object of type <TT>TMyObject</TT>,
as shown in
Figure 20.3.<BR>
<BR>
<A NAME="Heading27"></A><A HREF="20ebu03.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/20/20ebu03.jpg">FIGURE 20.3.</A><FONT COLOR="#000077">
</FONT><I>The main form of the PropertyTest program.</I></P>
<P><TT>TMyObject</TT> has five properties, one for each of the major types
of properties.
These properties have self-explanatory names:</P>
<PRE><FONT COLOR="#0066FF">__property int SimpleProp={read=FSimple, write=FSimple};
__property TEnumType EnumProp={read=FEnumType, write=FEnumType};
__property TSetProp
SetProp={read=FSetProp, write=FSetProp};
__property TStringList *ObjectProp={read=FObjectProp, write=FObjectProp};
__property AnsiString ArrayProp[int i]={read=GetArray};
</FONT></PRE>
<P>Before exploring these properties, I should mention that
<TT>TMyProps</TT> is
descended from the native VCL object called <TT>TCustomCo
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -