Проблема с опубликованием свойства
Добрый день.
Написал компонент для билдера.
В этом компоненте имеется одно непростое свойство, являющееся классом (тоже самодельным), унаследованным от TPersistent.
В компоненте прописаны методы чтения/записи в dfm.
Метод DefineProperties перекрыт.
Если свойство располагается в секции public, то всё нормально. Но когда я перенёс его в published появилась проблема. при сохранении формы с моим компонентом всё штатно прописывается в dfm. Но вот при загрузке формы из dfm выскакивает ошибка "Invalid property value".
Кто может подсказать, в чём дело?
Re: Проблема с опубликованием свойства
От:
wallaby
Дата: 29.07.08 12:33
Оценка:
Здравствуйте, zloy_babay, Вы писали:
_>Кто может подсказать, в чём дело?
Был тут похожий вопрос —
здесьАвтор: Дата: 08.06.07
. Посоветовал почитать Конопку — помогло.
---
The optimist proclaims that we live in the best of all possible worlds; and the pessimist fears this is true
Re: Проблема с опубликованием свойства
От:
Danchik
Дата: 29.07.08 14:51
Оценка:
Здравствуйте, zloy_babay, Вы писали:
_>Добрый день.
_>Написал компонент для билдера.
_>В этом компоненте имеется одно непростое свойство, являющееся классом (тоже самодельным), унаследованным от TPersistent.
_>В компоненте прописаны методы чтения/записи в dfm.
_>Метод DefineProperties перекрыт.
У кого он перекрыт?
_>Если свойство располагается в секции public, то всё нормально. Но когда я перенёс его в published появилась проблема. при сохранении формы с моим компонентом всё штатно прописывается в dfm. Но вот при загрузке формы из dfm выскакивает ошибка "Invalid property value".
_>Кто может подсказать, в чём дело?
Без кода это телепатия
Re[2]: Проблема с опубликованием свойства
Здравствуйте, Danchik, Вы писали:
D>Без кода это телепатия
Хидер:
#ifndef MyCompH
#define MyCompH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <DesignEditors.hpp>
//---------------------------------------------------------------------------
class PACKAGE TTestProp : public TPersistent
{
public :
TTestProp();
AnsiString strA;
AnsiString strB;
};
class PACKAGE TMyComp : public TCustomControl
{
private :
TTestProp *FTestProp;
protected :
void __fastcall ReadTestProp(TReader *r);
void __fastcall WriteTestProp(TWriter *w);
virtual void __fastcall DefineProperties(TFiler* Filer);
void __fastcall setTestProp(TTestProp* p);
public :
__fastcall TMyComp(TComponent* Owner);
__fastcall ~TMyComp();
__published:
__property TTestProp* TestProp = {read = FTestProp, write = setTestProp};
};
class TTestPropProperty : public TPropertyEditor
{
public :
virtual TPropertyAttributes __fastcall GetAttributes(void );
virtual AnsiString __fastcall GetValue();
};
//---------------------------------------------------------------------------
#endif
Имлпементация:
#include <vcl.h>
#include <DesignIntf.hpp>
#pragma hdrstop
#include "MyComp.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//
static inline void ValidCtrCheck(TMyComp *)
{
new TMyComp(NULL);
}
//---------------------------------------------------------------------------
TTestProp::TTestProp()
: TPersistent()
{
strA = "Строка A" ;
strB = "Строка B" ;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
__fastcall TMyComp::TMyComp(TComponent* Owner)
: TCustomControl(Owner)
{
FTestProp = new TTestProp;
}
//---------------------------------------------------------------------------
__fastcall TMyComp::~TMyComp()
{
delete FTestProp;
}
//---------------------------------------------------------------------------
void __fastcall TMyComp::ReadTestProp(TReader *r)
{
try
{
r->ReadListBegin();
int c = 0;
while (!r->EndOfList())
{
AnsiString s = r->ReadString();
if (!c)
FTestProp->strA = s;
else
FTestProp->strB = s;
c++;
}
r->ReadListEnd();
} catch (...) {}
}
//---------------------------------------------------------------------------
void __fastcall TMyComp::WriteTestProp(TWriter *w)
{
w->WriteListBegin();
w->WriteString(FTestProp->strA);
w->WriteString(FTestProp->strB);
w->WriteListEnd();
}
//---------------------------------------------------------------------------
void __fastcall TMyComp::DefineProperties(TFiler* Filer)
{
TCustomControl::DefineProperties(Filer);
Filer->DefineProperty("TestProp" , ReadTestProp, WriteTestProp, true );
}
//---------------------------------------------------------------------------
void __fastcall TMyComp::setTestProp(TTestProp* p)
{
if (p)
{
delete FTestProp;
FTestProp = p;
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
TPropertyAttributes __fastcall TTestPropProperty::GetAttributes(void )
{
TPropertyAttributes res;
res << paReadOnly;
return res;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TTestPropProperty::GetValue()
{
return AnsiString("(TTestProp)" );
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
namespace Mycomp
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TMyComp)};
RegisterComponents("Samples" , classes, 0);
RegisterPropertyEditor(__typeinfo(TTestProp), __classid(TMyComp), "TestProp" , __classid(TTestPropProperty));
}
}
//---------------------------------------------------------------------------
Re[3]: Проблема с опубликованием свойства
От:
wallaby
Дата: 30.07.08 11:55
Оценка:
Здравствуйте, zloy_babay, Вы писали:
[skipped]
_>//---------------------------------------------------------------------------
_>void __fastcall TMyComp::setTestProp(TTestProp* p)
_>{
_> if (p)
_> {
_> delete FTestProp;
_> FTestProp = p;
_> }
_>}
_>//---------------------------------------------------------------------------
Поскольку Билдером не пользуюсь всё не осилил, но вот так публикуемые свойства не присваивают. Нужно в классе TTestProp перекрывать метод Assign и присваивать через Assign, делать delete и присваивать новую ссылку нельзя.
---
The optimist proclaims that we live in the best of all possible worlds; and the pessimist fears this is true
Re[4]: Проблема с опубликованием свойства
Здравствуйте, wallaby, Вы писали:
W>Поскольку Билдером не пользуюсь всё не осилил, но вот так публикуемые свойства не присваивают. Нужно в классе TTestProp перекрывать метод Assign и присваивать через Assign, делать delete и присваивать новую ссылку нельзя.
Согласен с Вашим замечанием. Но это не устраняет самой проблемы.
Re[5]: Проблема с опубликованием свойства
От:
wallaby
Дата: 30.07.08 14:42
Оценка:
Здравствуйте, zloy_babay, Вы писали:
_>Согласен с Вашим замечанием. Но это не устраняет самой проблемы.
OK, смотрим дальше. Метод DefineProperties определяется не в TMyComp, а в TTestProp
Поскольку не пишу на Билдере, скажу как делал бы на Delphi:
procedure TTestProp.DefineProperties(Filer: TFiler);
begin
Filer.DefineProperty('strA' , ReadStrA, WriteStrA, True);
Filer.DefineProperty('strB' , ReadStrB, WriteStrB, True);
end ;
procedure TTestProp.ReadStrA(Reader: TReader);
begin
FstrA:= Reader.ReadString;
end ;
и т.д.
Кстати если строки ровно две, то и собственный редактор свойства не нужен, как и ..ListBegin и ..ListEnd
---
The optimist proclaims that we live in the best of all possible worlds; and the pessimist fears this is true
Re[6]: Проблема с опубликованием свойства
От:
Danchik
Дата: 31.07.08 00:48
Оценка:
Здравствуйте, wallaby, Вы писали:
[Skip]
Подводя итог выще сказанному:
#ifndef MyCompH
#define MyCompH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <DesignEditors.hpp>
//---------------------------------------------------------------------------
class PACKAGE TTestProp : public TPersistent
{
public :
TTestProp();
virtual void __fastcall Assign(TPersistent* source);
__published:
AnsiString strA;
AnsiString strB;
};
class PACKAGE TMyComp : public TCustomControl
{
private :
TTestProp *FTestProp;
protected :
void __fastcall setTestProp(TTestProp* p);
public :
__fastcall TMyComp(TComponent* Owner);
__fastcall ~TMyComp();
__published:
__property TTestProp* TestProp = {read = FTestProp, write = setTestProp};
};
//---------------------------------------------------------------------------
#endif
Имплементация:
#include <vcl.h>
#include <DesignIntf.hpp>
#pragma hdrstop
#include "MyComp.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
TTestProp::TTestProp()
: TPersistent()
{
strA = "Строка A" ;
strB = "Строка B" ;
}
//---------------------------------------------------------------------------
void TTestProp::Assign(TPersistent* source)
{
// здесь допишите Assign не знаю я как в CBuilder делать is
strA = (TPersistent*)source->strA;
strB = (TPersistent*)source->strB;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
__fastcall TMyComp::TMyComp(TComponent* Owner)
: TCustomControl(Owner)
{
FTestProp = new TTestProp;
}
//---------------------------------------------------------------------------
__fastcall TMyComp::~TMyComp()
{
delete FTestProp;
}
//---------------------------------------------------------------------------
void __fastcall TMyComp::setTestProp(TTestProp* p)
{
if (p)
{
FTestProp->Assign(p);
}
}
//---------------------------------------------------------------------------
P.S.
Все что относится к редактору свойства вырезано, допишете если понадобится.
Re[6]: Проблема с опубликованием свойства
Здравствуйте, wallaby, Вы писали:
W>Здравствуйте, zloy_babay, Вы писали:
_>>Согласен с Вашим замечанием. Но это не устраняет самой проблемы.
W>OK, смотрим дальше. Метод DefineProperties определяется не в TMyComp, а в TTestProp
W>Поскольку не пишу на Билдере, скажу как делал бы на Delphi:
W>W>procedure TTestProp.DefineProperties(Filer: TFiler);
W>begin
W> Filer.DefineProperty('strA' , ReadStrA, WriteStrA, True);
W> Filer.DefineProperty('strB' , ReadStrB, WriteStrB, True);
W>end ;
W>procedure TTestProp.ReadStrA(Reader: TReader);
W>begin
W> FstrA:= Reader.ReadString;
W>end ;
W>
W>и т.д.
W>Кстати если строки ровно две, то и собственный редактор свойства не нужен, как и ..ListBegin и ..ListEnd
Спасибо. Именно то, что нужно.
А про строки... На самом деле в реальном случае там не две строки, а массив записей. Это я просто тестовый пример сделал, чтобы не переусложнять.
Пока на собственное сообщение не было ответов, его можно удалить.
Удалить