如何存储(流式传输)TColor 数组属性?

问题描述 投票:0回答:1

我正在编写一个非窗口 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 流中的位置。

c++builder vcl
1个回答
0
投票

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();
}
© www.soinside.com 2019 - 2024. All rights reserved.