我正在编写一个非窗口 VCL 控件,其中包含一个
TColor
数组属性,称为 Colors[]
。 Colors[]
属性可用于在运行时设置控件不同部分的颜色。该控件还将获得一个属性编辑器来在设计时设置 Colors[]
属性。
我知道如何存储数组属性,但我从未对
TColor
值这样做过。通常, TColor
属性存储为颜色常量(例如 clBlack
或 clWindowText
)或数值(对于自定义颜色)。
TReader
和 TWriter
有读取和写入整数和字符串的方法,但没有 TColor
值。我查看了TPersistent
的源代码,但找不到它如何读取和写入TColor
值。
这是我的代码摘要:
class TMyControl : public TGraphicControl
{
typedef TGraphicControl inherited;
private:
TColor* FColors;
int FCount;
TColor __fastcall GetColors (int Index);
void __fastcall SetColors (int Index, TColor Value);
void __fastcall ReadColors (TReader* Reader);
void __fastcall WriteColors (TWriter* Writer);
void __fastcall SetCount (int Value);
void __fastcall CMColorChanged (TMessage &Msg);
protected:
virtual void __fastcall DefineProperties (TFiler *Filer);
public:
__fastcall TMyControl (TComponent *Owner);
__fastcall ~TMyControl ();
__property TColor Colors[int Index] = {read=GetColors, write=SetColors};
__published:
__property Color;
__property int Count = {read=FCount, write=SetCount, default=1};
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(CM_COLORCHANGED, TMessage, CMColorChanged)
END_MESSAGE_MAP(inherited)
};
void ModifyExtents (TColor* &Array, int NewSize, TColor Default)
{
// Allocates/resizes 'Array' to contain 'NewSize' elements and initializes new elements with 'Default'.
}
__fastcall TMyControl::TMyControl (TComponent *Owner) : inherited(Owner)
{
}
__fastcall TMyControl::~TMyControl ()
{
delete[] FColors;
}
TColor __fastcall TMyControl::GetColors (int Index)
{
if (Index < 0 || Index >= FCount)
throw Exception(SIndexOutOfRange);
return(FColors ? FColors[Index] : Color);
}
void __fastcall TMyControl::SetColors (int Index, TColor Value)
{
if (Index < 0 || Index >= FCount)
throw Exception(SIndexOutOfRange);
if (!FColors)
ModifyExtents(FColors, FCount, Color);
if (FColors[Index] != Value)
{
FColors[Index] = Value;
Invalidate();
}
}
void __fastcall TMyControl::SetCount (int Value)
{
if (Value < 0)
Value = 0;
if (FCount != Value)
{
if (FColors)
ModifyExtents(FColors, Value, Color);
FCount = Value;
Invalidate();
}
}
void __fastcall TMyControl::CMColorChanged (TMessage &Msg)
{
inherited::Dispatch(&Msg);
if (FColors)
{
delete[] FColors;
FColors = NULL;
}
}
void __fastcall TMyControl::DefineProperties (TFiler* Filer)
{
inherited::DefineProperties(Filer);
Filer->DefineProperty("Colors", ReadColors, WriteColors, (FColors != NULL));
}
void __fastcall TMyControl::ReadColors (TReader* Reader)
{
Reader->ReadListBegin();
for (int i = 0; i < FCount; i++)
Colors[i] = Reader->Read...(); // ReadInteger, ReadString, ...?
Reader->ReadListEnd();
}
void __fastcall TMyControl::WriteColors (TWriter* Writer)
{
Writer->WriteListBegin();
for (int i = 0; i < FCount; i++)
Writer->Write...(Colors[i]); // WriteInteger, WriteString, ...?
Writer->WriteListEnd();
}
Count
属性指定控件中不同部分的数量,这也是存储在TColor
数组中的FColors
值的数量。仅当写入 FColors
属性时才会分配 Colors[]
数组。如果 FColors
数组不存在,则读取 Colors[]
属性将返回控件的 Color
属性的值。设置控件的 Color
属性会破坏 FColors
数组。
如何读写
TColor
值,以便保留颜色常量(而不是转换为数值)?
更新
TReader::NextValue()
返回值类型,而不增加 DFM 流中的位置。
ReadColors()
和WriteColors()
方法变为:
void __fastcall TMyControl::ReadColors (TReader* Reader)
{
Reader->ReadListBegin();
for (int i = 0; i < FCount; i++)
{
switch (Reader->NextValue())
{
case vaInt8:
case vaInt16:
case vaInt32:
Colors[i] = TColor(Reader->ReadInteger());
break;
case vaIdent:
{
int Value;
if (IdentToColor(Reader->ReadIdent(), Value))
Colors[i] = TColor(Value);
}
break;
default:
Reader->SkipValue();
}
}
Reader->ReadListEnd();
}
void __fastcall TMyControl::WriteColors (TWriter* Writer)
{
Writer->WriteListBegin();
for (int i = 0; i < FItemCount; i++)
{
String S;
if (ColorToIdent(Colors[i], S))
Writer->WriteIdent(S);
else
Writer->WriteInteger(Colors[i]);
}
Writer->WriteListEnd();
}