Is there a way to cast a TObject to another type using the ClassType property, for example;
TLizardNode *node = static_cast<TObject->ClassType()>(in);
I am sure I now what the answer will be but thought I would ask anyway..
Moderator: 2ffat
theLizard wrote:Is there a way to cast a TObject to another type using the ClassType property
TLizardNode *node = static_cast<TLizardNode*>(in);TLizardNode *node = dynamic_cast<TLizardNode*>(in);
if( node != NULL ) ...
No. Such type-casts are evaluated at compile-time, and as such need a class type known at compile-time, not dynamically at run-time. Besides, you are casting the wrong way to begin with. You need to specify the class type you are casting to, which in this case is a TLizardNode and is known at compile-time:
theLizard wrote:TLizardNode *node = static_cast<TObject->ClassType()>(in); this was only a given as an example of what would have been a wishful way to do it, I expected that it could not be done but thought I would ask just in case there was a way.
What exactly are you trying to accomplish?
int __fastcall TLizardAgent::SetEditOrdinals(TWinControl *p)
{
int ordinal;
UnicodeString name1, name2;
int type;
int j;
fieldCount = 0;
//compare the edit controls on the TWinControl using ClassName, if they match one of these
//cast the control to one of the TLizard controls e.g. TLizardComboBox * c = static_cast<TLizardComboBox *>(p->Controls[i]);
//once cast to the edit control we can get the exended properties and set their values
//from the info obtained from the database. These were obtained with a call to TLizardAgent->getColDef(db, "vessels", "");
//type: is an enum
//name1: is the FieldName property of the control
//name2: is the field name extracted from the database and placed in Fields[n].field
for(int i =0; i<p->ControlCount; i++)
{
type = coNone;
if(p->Controls[i]->ClassName() == "TLizardComboBox")
{
c = static_cast<TLizardComboBox *>(p->Controls[i]);
name2 = c->FieldName;
type = coCombo;
}
if(p->Controls[i]->ClassName() == "TLizardEdit")
{
e = static_cast<TLizardEdit *>(p->Controls[i]);
name2 = e->FieldName;
type = coEdit;
}
if(p->Controls[i]->ClassName() == "TLizardDateTimePicker")
{
dt = static_cast<TLizardDateTimePicker *>(p->Controls[i]);
name2 = dt->FieldName;
type = coDateTime;
}
switch(type)
{
case coCombo:
case coEdit:
case coDateTime:
for(j = 0; j< (int)Fields.size()-1; j++)
{
name1 = Fields[j]->Field.LowerCase();
if(name1 == name2.LowerCase())
{
ordinal = Fields[j]->OrdinalPosition;
fieldCount++;
break;
}
}
switch(type)
{
case coCombo:
c->DbOrdinal = ordinal;
Fields[j]->Lookup = c->Lookup;
Fields[j]->LookupTable = c->LookupTable;
Fields[j]->LookUpIdentName = c->LookUpIdentName;
break;
case coEdit:
e->DbOrdinal = ordinal;
break;
case coDateTime:
dt->DbOrdinal = ordinal;
break;
}
break;
}
}
return(fieldCount-1);
}
//---------------------------------------------------------------------------
void __fastcall TLizardAgent::FillRecord(TLizardODBConnect *db, TWinControl *p, UnicodeString sql)
{
int i = 0, numbFields;
SQLINTEGER count = 1;
sqlConnect q;
SQLCHAR val[STR_LEN];
SQLINTEGER cb;
AnsiString dsn;
AnsiString s = sql;
SQLRETURN retcode;
SQLPOINTER rgbValue = &i;
bool found = false;
dsn = db->ODBCDatasourceName;
db->AllocHandles(&q);
//number of Fields to load
numbFields = Fields.size();
// SQL Native Client - for now
q.retcode=SQLConnect(q.hdbc,(SQLCHAR*)dsn.c_str() /*dbInfo.odbcDbName.c_str()*/ ,SQL_NTS,NULL,0,NULL,0);
//SQLRETURN SQLConnect(ConnectionHandle, ServerName, NameLength1, UserName, NameLength2,Authentication,NameLength3);
q.retcode = SQLExecDirect(q.hstmt, s.c_str(), SQL_NTS);
if (!MYSQLSUCCESS(q.retcode))
{
//error_out(SQL_HANDLE_STMT, q.hstmt);
}
if (q.retcode == SQL_SUCCESS || q.retcode == SQL_SUCCESS_WITH_INFO)
{
while (TRUE)
{
q.retcode = SQLFetch(q.hstmt);
//if (q.retcode == SQL_ERROR || q.retcode == SQL_SUCCESS_WITH_INFO)
//error_out(SQL_HANDLE_DBC, q.hdbc);
if(q.retcode == SQL_SUCCESS || q.retcode == SQL_SUCCESS_WITH_INFO)
{
//ordinarily you would specify the field name and data type you want to read from the database
//but this is no good since I do not want to have a function for every table in a database
//so we tell the database to return the value as an SQL_C_CHAR and fill the Fields[x].value with
//the result returned by val.
//count is the field number (ordinal) so while the field count
//does not match the number of Fields in Fields.size() get the field[n] value
while(count != numbFields)
{
SQLGetData(q.hstmt, count+1, SQL_C_CHAR, &val, STR_LEN, &cb);
Fields[count]->Value = (char *)val;
count++;
}
}
else
{
break;
}
}
if (q.retcode == SQL_SUCCESS || q.retcode == SQL_SUCCESS_WITH_INFO || SQL_NO_DATA) {
SQLCancel(q.hstmt);
SQLFreeHandle(SQL_HANDLE_STMT, q.hstmt);
}
SQLDisconnect(q.hdbc);
}
//we can now populate the edit controls which shows the values from the record.
ShowRecord(db, p);
}
//---------------------------------------------------------------------------
void __fastcall TLizardAgent::ShowRecord(TLizardODBConnect *db, TWinControl *p)
{
TDateTime DT;
UnicodeString name1, name2, value, sql;
int type;
int j;
//This is pretty much a reversal of making an sql statement, we have all the field values
//in the Fields vector so put the value into the relative edit control. simple!!
for(int i =0; i<p->ControlCount; i++)
{
type = coNone;
if(p->Controls[i]->ClassName() == "TLizardComboBox")
{
c = static_cast<TLizardComboBox *>(p->Controls[i]);
name2 = c->FieldName;
type = coCombo;
}
if(p->Controls[i]->ClassName() == "TLizardEdit")
{
e = static_cast<TLizardEdit *>(p->Controls[i]);
name2 = e->FieldName;
type = coEdit;
}
if(p->Controls[i]->ClassName() == "TLizardDateTimePicker")
{
dt = static_cast<TLizardDateTimePicker *>(p->Controls[i]);
name2 = dt->FieldName;
type = coDateTime;
}
switch(type)
{
case coCombo:
case coEdit:
case coDateTime:
for(j = 0; j < (int)Fields.size(); j++)
{
name1 = Fields[j]->Field.LowerCase();
if(name1 == name2.LowerCase())
{
value = Fields[j]->Value;
break;
}
}
switch(type)
{
case coCombo:
//is the combo a lookup list?
//if the combo box control shows values from a lookup table and the value
//we have obtained in this function for this field is an identity field we need to
//show the text value in the combo box.
//Note: if TlizardComboBox is a lookup and the text value entered does not exist in the database
//you are prompted to add the new value or abort, if you abort, the whole action will be aborted
//on the basis that you cannot have a lookup without an index into the lookup table.
if(c->Lookup)
{
//we have the field name, table name, the identity field name and the value
//create the sql and find the text value for the id value
sql = "SELECT " + c->LookUpFieldName + " FROM " + c->LookupTable + " WHERE ";
sql += c->LookUpIdentName + " = " + value;
value = GetFieldValue(db, sql);
//value now has the field value in field name, now we iterate through the combo box list
//to find the matching value then set the index into the combobox list so that it appears in
//the text part of the combo box.
for(int k =0; k<c->Items->Count; k++)
{
if(c->Items->Strings[k] == value)
{
c->ItemIndex = k;
break;
}
}
}
else
{
//can't see a combo being used for any other reason, if need to will look at this
//at that time.
}
break;
case coEdit:
e->Text = FormatValue(value, Fields[j]->DataType);
break;
case coDateTime:
if(value.Length() > 10)
value = value.SubString(1,10); //only want the date part, this should always be formated with a 4 digit year
dt->Date = SetDate(value);
break;
}
break;
}
}
}
//---------------------------------------------------------------------------
theLizard wrote:Wanted to see if there was a way to cast a generic TObject to a class without having to explicitly name the class using the TObjects ClassType() or CLassName() or Class anything in functions calls to maybe simplify the following
#include <TypInfo.hpp>
int __fastcall TLizardAgent::SetEditOrdinals(TWinControl *p)
{
String name;
TControl *ctrl;
PPropInfo propinfo;
TLizardComboBox *cb;
fieldCount = 0;
//compare the edit controls on the TWinControl, if they match one of these
//we can get the exended properties and set their values from the info
//obtained from the database. These were obtained with a call to
//TLizardAgent->getColDef(db, "vessels", "");
for(int i = 0; i < p->ControlCount; ++i)
{
ctrl = p->Controls[i];
propinfo = GetPropInfo(ctrl, "FieldName");
if( !propinfo )
continue;
name = GetStrProp(ctrl, propinfo);
if( name.IsEmpty() )
continue;
for(int j = 0; j < (int)Fields.size(); ++j)
{
if( AnsiSameText(Fields[j]->Field, name) )
{
++fieldCount;
propinfo = GetPropInfo(ctrl, "DbOrdinal");
if( propinfo )
SetOrdProp(ctrl, propinfo, Fields[j]->OrdinalPosition);
cb = dynamic_cast<TLizardComboBox*>(ctrl);
if( cb != NULL )
{
Fields[j]->Lookup = cb->Lookup;
Fields[j]->LookupTable = cb->LookupTable;
Fields[j]->LookUpIdentName = cb->LookUpIdentName;
}
break;
}
}
}
return fieldCount;
}
void __fastcall TLizardAgent::FillRecord(TLizardODBConnect *db, TWinControl *p, AnsiString sql)
{
int numbFields;
SQLINTEGER count = 0;
sqlConnect q;
SQLCHAR val[STR_LEN];
SQLINTEGER cb;
AnsiString dsn = db->ODBCDatasourceName;
db->AllocHandles(&q);
//number of Fields to load
numbFields = Fields.size();
// SQL Native Client - for now
q.retcode = SQLConnect(q.hdbc, (SQLCHAR*)dsn.c_str() /*dbInfo.odbcDbName.c_str()*/, SQL_NTS, NULL, 0, NULL, 0);
//SQLRETURN SQLConnect(ConnectionHandle, ServerName, NameLength1, UserName, NameLength2,Authentication,NameLength3);
q.retcode = SQLExecDirect(q.hstmt, sql.c_str(), SQL_NTS);
if( !MYSQLSUCCESS(q.retcode) )
{
//error_out(SQL_HANDLE_STMT, q.hstmt);
}
if( (q.retcode == SQL_SUCCESS) || (q.retcode == SQL_SUCCESS_WITH_INFO) )
{
q.retcode = SQLFetch(q.hstmt);
//if( (q.retcode == SQL_ERROR) || (q.retcode == SQL_SUCCESS_WITH_INFO) )
//error_out(SQL_HANDLE_DBC, q.hdbc);
if( (q.retcode == SQL_SUCCESS) || (q.retcode == SQL_SUCCESS_WITH_INFO) )
{
//ordinarily you would specify the field name and data type you want to read from the database
//but this is no good since I do not want to have a function for every table in a database
//so we tell the database to return the value as an SQL_C_CHAR and fill the Fields[x].value with
//the result returned by val.
//count is the field number (ordinal) so while the field count
//does not match the number of Fields in Fields.size() get the field[n] value
while( count != numbFields )
{
SQLGetData(q.hstmt, count+1, SQL_C_CHAR, &val, STR_LEN, &cb);
Fields[count]->Value = AnsiString((char *)val, cb);
++count;
}
}
SQLCancel(q.hstmt);
SQLDisconnect(q.hdbc);
}
SQLFreeHandle(SQL_HANDLE_STMT, q.hstmt);
//we can now populate the edit controls which shows the values from the record.
ShowRecord(db, p);
}
void __fastcall TLizardAgent::ShowRecord(TLizardODBConnect *db, TWinControl *p)
{
String name, value, sql;
TControl *ctrl;
PPropInfo propinfo;
TLizardComboBox *cb;
TLizardEdit *e;
TLizardDateTimePicker *dtp;
//This is pretty much a reversal of making an sql statement, we have all the field values
//in the Fields vector so put the value into the relative edit control. simple!!
for(int i = 0; i < p->ControlCount; ++i)
{
ctrl = p->Controls[i];
propinfo = GetPropInfo(ctrl, "FieldName");
if( !propinfo )
continue;
name = GetStrProp(ctrl, propinfo);
if( name.IsEmpty() )
continue;
for(int j = 0; j < (int)Fields.size(); ++j)
{
if( AnsiSameText(Fields[j]->Field, name) )
{
value = Fields[j]->Value;
if( (cb = dynamic_cast<TLizardComboBox*>(ctrl)) != NULL )
{
//is the combo a lookup list?
//if the combo box control shows values from a lookup table and the value
//we have obtained in this function for this field is an identity field we need to
//show the text value in the combo box.
//Note: if TlizardComboBox is a lookup and the text value entered does not exist in the database
//you are prompted to add the new value or abort, if you abort, the whole action will be aborted
//on the basis that you cannot have a lookup without an index into the lookup table.
if( cb->Lookup )
{
//we have the field name, table name, the identity field name and the value
//create the sql and find the text value for the id value
sql = "SELECT " + cb->LookUpFieldName + " FROM " + cb->LookupTable + " WHERE " + cb->LookUpIdentName + " = " + value;
value = GetFieldValue(db, sql);
//value now has the field value in field name, now we iterate through the combo box list
//to find the matching value then set the index into the combobox list so that it appears in
//the text part of the combo box.
cb->ItemIndex = cb->Items->IndexOf(value);
}
else
{
//can't see a combo being used for any other reason, if need to will look at this
//at that time.
}
}
else if( (e = dynamic_cast<TLizardEdit*>(ctrl)) != NULL )
{
e->Text = FormatValue(value, Fields[j]->DataType);
}
else if( (dtp = dynamic_cast<TLizardDateTimePicker*>(ctrl)) != NULL )
{
if( value.Length() > 10 )
value = value.SubString(1, 10); //only want the date part, this should always be formated with a 4 digit year
dtp->Date = SetDate(value);
}
break;
}
}
}
}
Users browsing this forum: Google [Bot], Yahoo [Bot] and 1 guest