Board index » cppbuilder » Creating component with TStringList property

Creating component with TStringList property

I have created a control with a TStringList property.  It works fine at
design time.  You can view the strings in
the TStringList by double clicking on (TStringsList) property in the object
inspector.  However,
When I run an application containing the control, I get exception errors
like:

Project... has raised an exception EREADERROR. Error reading
B2Dataset->Tablenames.Strings.  Property does not exist.

If I dump the .dfm file for the form containing the control, I can see the
property and its associated list of string values.

Any ideas?

Here is a bit of the control's code.

class  PACKAGE TB2DataSet : public TComponent
{
   private:
     ...
     TStringList *FTableNames;
     ...
    public:
      __fastcall  TB2DataSet(TComponent *Owner) { FTableNames = new
TStringList; ...};
     __fastcall ~TB2DataSet(); { delete FTableNames; };
        ...
 __published:
     ...
     __property TStringList *TableNames   ={read=FTableNames,
write=SetTableNames,nodefault,

stored=true};

Quote
}

 

Re:Creating component with TStringList property


Jeb
Do you use Bcb3 ? If so, I can mail you my test
component. It has several types of property editors,
including a TStringList. This problem does not occur,
so by comparison of your source and mine maybe you
could find the cause of your exception.
HTH
Gerard

On Fri, 3 Jul 1998 12:22:17 -0700, "Jeb Long" <jebl...@loop.com>
wrote:

Quote
>I have created a control with a TStringList property.  It works fine at
>design time.  You can view the strings in
>the TStringList by double clicking on (TStringsList) property in the object
>inspector.  However,
>When I run an application containing the control, I get exception errors
>like:

>Project... has raised an exception EREADERROR. Error reading
>B2Dataset->Tablenames.Strings.  Property does not exist.

>If I dump the .dfm file for the form containing the control, I can see the
>property and its associated list of string values.

>Any ideas?

>Here is a bit of the control's code.

>class  PACKAGE TB2DataSet : public TComponent
>{
>   private:
>     ...
>     TStringList *FTableNames;
>     ...
>    public:
>      __fastcall  TB2DataSet(TComponent *Owner) { FTableNames = new
>TStringList; ...};
>     __fastcall ~TB2DataSet(); { delete FTableNames; };
>        ...
> __published:
>     ...
>     __property TStringList *TableNames   ={read=FTableNames,
>write=SetTableNames,nodefault,

>stored=true};
>}

Re:Creating component with TStringList property


Gerald,
Yes, I am using BCB3.  I would be interesting in looking at your component.
Please e-mail it to me
Thanks!!!!
Jeb Long

jebl...@loop.com

Re:Creating component with TStringList property


Harold,
Actually, I did use the Assign function to set the strings.  However, I did
find the problem.

I discovered that the designer uses the package .BPL file in the \lib
directory. No problem.  However,
the actual execution of the test program, it depends on a copy of the .BPL
file in the \Windows\System directory.   It appears that THE VERY FIRST TIME
you install the component package, the package installer
copies the .BPL file to the \Windows\System directory.  However, on
subsequent package installations, the
package installer sees your .BPL file already exists in the \Windows\System
directory AND DOESN'T COPY
the new version.  I manually copied the .BPL component package file to the
\Windows\System directory
and the component test program ran fine....

Thanks for youir suggestion.
Jeb

Quote
Harold Howe (TeamB) wrote in message <6noh96$d...@forums.borland.com>...

>Jeb Long wrote in message <6njb43$9...@forums.borland.com>...
>>I have created a control with a TStringList property.  It works fine at
>>design time.  You can view the strings in
>>the TStringList by double clicking on (TStringsList) property in the
object
>>inspector.  However,
>>When I run an application containing the control, I get exception errors

>I see that you had a set method for the stringlist, but you didn't show
what
>it was doing internally. Your mistake is probably in that function. You
>should copy the IDE's strings by using the Assign method.

>Harold Howe (TeamB)
>http://www.bcbdev.com

Re:Creating component with TStringList property


Gerald,
Its interesting how you handled the AnsiString/property editor problem with
a method.

I created an AnsiString property editor by first wrapping the AnsiString
string
using the TB2String class (below).

I wanted to be able to pick the property value from a list so I needed a
property editor.  I added the
AnsiString property, Data, and a pointer to my non-borland database
component object to TB2Strings.
The value returned by GetValue(), etc. is a pointer to the wrapped
AnsiString property (TB2String*).
 I used the GetOrdValue() function to fetch  the pointer to TB2Strings.

------------------------ The AnsiString wrapper --------------------------
 class PACKAGE TB2String : public TPersistent
{
 private:
   AnsiString FData;
 public:
    __fastcall TB2String() : TPersistent() {FData = "";};
    __fastcall ~TB2String() {};
    TB2DataSet *pDS;  // Pointer to my own (not Borland's) database
datasource object
      .... omitted stuff
 __published:
 __property AnsiString Data={read=FData, write=FData};
    ...  stuff omitted

Quote
};

------------------------------------------------- The
ontrol  ------------------------------------------------
class PACKAGE TB2Edit : public TEdit
{
private:
    ...
    TB2String *FFieldName;
    ...
 __published:
 __property TB2String* Field = {read=FFieldName, write=SetFieldName};
    ...
Quote
};

-------------------------------------- The
registration -----------------------------------------------------
namespace B2edit
{
 void __fastcall  PACKAGE Register()
 {
  TComponentClass classes[1] = {__classid(TB2Edit)};
  RegisterComponents(LoadStr(jDB_Pallette), classes, 0);
        RegisterPropertyEditor(__typeinfo(TB2String), __classid(TB2Edit),
                               "",__classid(TB2DBPropertyEditor));
 }

Quote
}

-------------------- The Property Editor Declaration ---------------
class PACKAGE TB2DBPropertyEditor: public TPropertyEditor
{
    typedef TB2DBPropertyEditor ThisClass;
    typedef TPropertyEditor inherited;
  public:
    __fastcall TB2DBPropertyEditor(void) : TPropertyEditor() { };
    virtual TPropertyAttributes __fastcall GetAttributes(void);
    virtual void __fastcall GetValues(Classes::TGetStrProc Proc);
    virtual System::AnsiString __fastcall GetValue(void);
    virtual void  __fastcall SetValue(const AnsiString aValue);

Quote
};

------------------ Property Editor Methods ---------------------
TPropertyAttributes __fastcall TB2DBPropertyEditor::GetAttributes()
{
  return (TPropertyAttributes() << paValueList << paSortList);
Quote
}

void __fastcall TB2DBPropertyEditor::GetValues(Classes::TGetStrProc Proc)
{
//  fill list of names from database structure. First grab pointer to
//  database component (datasource) from the TB2String object.

    TB2DataSet *pDS1; // Pointer to my own (not Borland's) database
datasource
    pDS1=((TB2String*)GetOrdValue())->pDS; // Points to DataSet object
    AnsiString tablename = pDS1->CurrentTableName;   // fetch name
    if (!tablename.IsEmpty() && pDS1  &&
pDS1->OpenTable(tablename.c_str()) )
    { // do if table name and dataset pointer exists and table opens OK
        AnsiString FieldName;
        for (int iField = 0; iField < 255; iField++)
        {
            FieldName = pDS1->GetField(iField);
            if (FieldName.IsEmpty())
                break;
            Proc(FieldName);
         }
     }

Quote
}

System::AnsiString __fastcall TB2DBPropertyEditor::GetValue()
{
    // Use GetOrdValue() to fetch pointer to AnsiString wrapper and
    //  return value

  return  ((TB2String*)GetOrdValue())->Data;

Quote
}

void  __fastcall TB2DBPropertyEditor::SetValue(const AnsiString aValue)
{
    ((TB2String*)GetOrdValue())->Data = aValue;
    Modified();
Quote
}

Re:Creating component with TStringList property


Jeb
It is good to know that someone has solved this TDataset problem
at last (there is posts from time to time on this subject).

Thanks for the code, there are some things that I will study a little
to see what I could add to my test component (I will acknowledge your
contribution of course <g>)

Gerard

On Sun, 5 Jul 1998 13:21:30 -0700, "Jeb Long" <jebl...@loop.com>
wrote:

Quote
>Gerald,
>Its interesting how you handled the AnsiString/property editor problem with
>a method.

It is to be able to affect directly the property in code , without
having to use a ->Data member.

Quote

>    TB2DataSet *pDS1; // Pointer to my own (not Borland's) database
>datasource
>    pDS1=((TB2String*)GetOrdValue())->pDS; // Points to DataSet object
>    AnsiString tablename = pDS1->CurrentTableName;   // fetch name
>    if (!tablename.IsEmpty() && pDS1  &&
>pDS1->OpenTable(tablename.c_str()) )
>    { // do if table name and dataset pointer exists and table opens OK
>        AnsiString FieldName;
>        for (int iField = 0; iField < 255; iField++)
>        {
>            FieldName = pDS1->GetField(iField);
>            if (FieldName.IsEmpty())
>                break;
>            Proc(FieldName);
>         }
>     }

>}

I *guess* that you are not using GetFieldNames because it would
not be compatible with your implementation of TDataset ?

Re:Creating component with TStringList property


One other thing that I omitted that I should have included, the SetFieldName
function:

     void __fastcall SetFieldName(TB2String *name)
{FFieldName->Assign(name);};

Quote

Other Threads