问题描述
我的环境:
- 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东京>TStreamWriter>clWhite无法复制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!