Проблема с опубликованием свойства
От: zloy_babay  
Дата: 29.07.08 09:22
Оценка:
Добрый день.

Написал компонент для билдера.
В этом компоненте имеется одно непростое свойство, являющееся классом (тоже самодельным), унаследованным от 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]: Проблема с опубликованием свойства
От: zloy_babay  
Дата: 30.07.08 07:18
Оценка:
Здравствуйте, 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]: Проблема с опубликованием свойства
От: zloy_babay  
Дата: 30.07.08 13:36
Оценка:
Здравствуйте, 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]: Проблема с опубликованием свойства
От: zloy_babay  
Дата: 31.07.08 07:30
Оценка:
Здравствуйте, 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


Спасибо. Именно то, что нужно.
А про строки... На самом деле в реальном случае там не две строки, а массив записей. Это я просто тестовый пример сделал, чтобы не переусложнять.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.