C ++ Builder XE4,10.2东京>TStreamWriter>clWhite无法复制 [英] C++ Builder XE4, 10.2 Tokyo > TStreamWriter > clWhite cannot be copied

查看:52
本文介绍了C ++ Builder XE4,10.2东京>TStreamWriter>clWhite无法复制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的环境:

  • RadStudio 10.2 Tokyo(以及XE4)

我正在实现一个copy属性方法来复制TShape属性.

I was implementing a copy property method to copy TShape properties.

以下是我执行的操作:

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    // set Shape1 color to [clWhite]
    Shape1->Brush->Color = clRed;   // clWhite
    Shape2->Brush->Color = clAqua;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::copyProperties(TControl *srcCtrl, TControl *dstCtrl)
{
    // to Keep original names
    String orgName_src = srcCtrl->Name;
    String orgName_dst = dstCtrl->Name;

    // copy properties
    TMemoryStream *strm = new TMemoryStream;
    Shape1->Name = L"";  // to avoid source collision
    try {
        strm->WriteComponent(srcCtrl);
        strm->Position = 0;
        strm->ReadComponent(dstCtrl);
    }
    __finally
    {
        delete strm;
    }

    srcCtrl->Name = orgName_src;
    dstCtrl->Name = orgName_dst;
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    copyProperties((TControl *)Shape1, (TControl *)Shape2);

    // shift to avoid position-overlapping
    Shape2->Left = Shape1->Left + 150;
}
//---------------------------------------------------------------------------

代码似乎可以正常工作.

The code seems work fine.

但是在唯一的情况下,代码不起作用.即当Shape1的Brush-> Color = clWhite时.

But there is a single case, in which the code does not work. i.e. when the Brush->Color = clWhite for Shape1.

这个错误?XE4也可以复制.

This bug? can be reproduced also for XE4.

我想知道为什么只有clWhite会出现这种错误?其他颜色没有这种错误.

I wonder why only the clWhite has this kind of bug? Other colors does not have this kind of bug.

推荐答案

流中没有错误.它按设计运行.您只是以一种不适合其使用的方式使用它.

There is no bug in the streaming. It is operating as designed. You are simply using it in a way that it is not intended for.

clWhite TBrush.Color 属性的声明的 default 值.DFM流系统不会流传输当前设置为其默认值的属性,除非这些属性声明为 nodefault stored = true . TBrush.Color 都不是.因此,当当前的 Brush.Color 值设置为 clWhite 时,不会将其流式传输.

clWhite is the declared default value of the TBrush.Color property. The DFM streaming system does not stream properties that are currently set to their default values, unless those properties are declared as nodefault or stored=true. TBrush.Color is neither. So the current Brush.Color value will not be streamed when it is set to clWhite.

请考虑直接使用RTTI系统而不是使用DFM系统将属性从一个对象复制到另一个对象.然后,您可以选择复制属性值,而无需考虑默认值(如果选择这样做).而且,您可以选择忽略 Name 属性,而不必每次都(重新)存储它.

Consider using the RTTI system directly instead of using the DFM system to copy properties from one object to another. Then you can copy property values regardless of defaults, if you choose to do so. And you can opt to ignore the Name property without having to (re)store it each time.

例如:

#include <System.TypInfo.hpp>

void __fastcall TForm1::copyProperties(TControl *srcCtrl, TControl *dstCtrl)
{
    PTypeInfo pDstTypeInfo = static_cast<PTypeInfo>(dstCtrl->ClassInfo());

    PPropList srcPropList;
    int srcPropCount = GetPropList(srcCtrl, srcPropList);
    try
    {
        for (int i = 0; i < srcPropCount; ++i)
        {
            PPropInfo pSrcPropInfo = (*srcPropList)[i];
            if (pSrcPropInfo->Name == "Name") continue;

            PTypeInfo pSrcPropTypeInfo = *(pSrcPropInfo->PropType);

            if (pSrcPropTypeInfo->Kind == tkClass)
            {
                PPropInfo pDstPropInfo = GetPropInfo(pDstTypeInfo, pSrcPropInfo->Name, TTypeKinds() << tkClass);
                if (pDstPropInfo)
                {
                    TPersistent *pDstObj = static_cast<TPersistent*>(GetObjectProp(dstCtrl, pDstPropInfo, __classid(TPersistent)));
                    if (pDstObj)
                    {
                        TPersistent *pSrcObj = static_cast<TPersistent*>(GetObjectProp(srcCtrl, pSrcPropInfo, __classid(TPersistent)));
                        pDstObj->Assign(pSrcObj);
                    }
                }
            }
            else
            {
                PPropInfo pDstPropInfo = GetPropInfo(pDstTypeInfo, pSrcPropInfo->Name);
                if (pDstPropInfo)
                {
                    Variant value = GetPropValue(srcCtrl, pSrcPropInfo);
                    SetPropValue(dstCtrl, pDstPropInfo, value);
                }
            }
        }
    }
    __finally
    {
        FreeMem(srcPropList);
    }
}

或者:

#include <System.Rtti.hpp>

void __fastcall TForm1::copyProperties(TControl *srcCtrl, TControl *dstCtrl)
{
    TRttiContext ctx;

    TRttiType *pSrcType = ctx.GetType(srcCtrl->ClassInfo());
    TRttiType *pDstType = ctx.GetType(dstCtrl->ClassInfo());

    DynamicArray<TRttiProperty*> srcProps = pSrcType->GetProperties();
    for (int i = 0; i < srcProps.Length; ++i)
    {
        TRttiProperty *pSrcProp = srcProps[i];
        if (pSrcProp->Name == L"Name") continue;

        if (pSrcProp->PropertyType->TypeKind == tkClass)
        {
            TRttiProperty *pDstProp = pDstType->GetProperty(pSrcPropInfo->Name);
            if ((pDstProp) && (pDstProp->PropertyType->TypeKind == tkClass))
            {
                TPersistent *pDstObj = dynamic_cast<TPersistent*>(pDstProp->GetValue(dstCtrl).AsObject());
                if (pDstObj)
                {
                    TPersistent *pSrcObj = dynamic_cast<TPersistent*>(pSrcProp->GetValue(srcCtrl).AsObject());
                    pDstObj->Assign(pSrcObj);
                }
            }
        }
        else
        {
            TRttiProperty *pDstProp = pDstType->GetProperty(pSrcPropInfo->Name);
            if (pDstProp)
            {
                TValue value = pSrcProp->GetValue(srcCtrl);
                pDstProp->SetValue(dstCtrl, value);
            }
        }
    }
}

这篇关于C ++ Builder XE4,10.2东京&gt;TStreamWriter&gt;clWhite无法复制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆