C++ builder (no idea what to do with this code) - c++builder

Sorry if this is wrong place to ask. I have 2 pieces of code given to me:
IdHTTP1->Head("http://dsrt.dyndns.org/files/MAIN.zip");
Memo1->Lines->Add(DateTimeToStr(IdHTTP1->Response->Date));
Memo1->Lines->Add(DateTimeToStr(IdHTTP1->Response->Expires));
Memo1->Lines->Add(DateTimeToStr(IdHTTP1->Response->LastModified));
and also this:
TDateTime dt;
AnsiString str = DateToStr(dt);
IdHTTP1->Head("http://dsrt.dyndns.org/files/MAIN.zip");
if(DateToStr(IdHTTP1->Response->Date) != str)
Memo1->Lines->Add(DateTimeToStr(IdHTTP1->Response->Date));
if(DateToStr(IdHTTP1->Response->Expires) != str)
Memo1->Lines->Add(DateTimeToStr(IdHTTP1->Response->Expires));
if(DateToStr(IdHTTP1->Response->LastModified) != str)
Memo1->Lines->Add(DateTimeToStr(IdHTTP1->Response->LastModified));
Somehow it's supposed to return a date when file was uploaded. But I have no clue how to get c++ builder to compile it. I get syntax errors and "multiple memo1 something" error. Please help.

TMemo is an Embarcadero visual UI component. TIdHTTP is a component of the Indy Project, which ships preinstalled in Delphi and C++Builder.
The code you were given is UI-related code, so create UI for it. In the C++Builder IDE, create a new TForm class, drop a TMemo on it and name it Memo1, and drop a TIdHTTP component and name it IdHTTP1, and then use something like a button OnClick handler to invoke the HTTP code, eg:
Unit1.h:
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <IdHTTP.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TMemo *Memo1;
TButton *Button1;
TButton *Button2;
TIdHTTP *IdHTTP1;
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Unit1.cpp:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include <System.Sysutils.hpp>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
IdHTTP1->Head("http://dsrt.dyndns.org/files/MAIN.zip");
Memo1->Lines->Add(DateTimeToStr(IdHTTP1->Response->Date));
Memo1->Lines->Add(DateTimeToStr(IdHTTP1->Response->Expires));
Memo1->Lines->Add(DateTimeToStr(IdHTTP1->Response->LastModified));
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
TDateTime dt = ...; // assign some value
// see functions such as Date(), Now(), EncodeDateTime(), etc,
// or use the TDateTimePicker component...
System::String str = DateToStr(dt);
IdHTTP1->Head("http://dsrt.dyndns.org/files/MAIN.zip");
if (DateToStr(IdHTTP1->Response->Date) != str)
Memo1->Lines->Add(DateTimeToStr(IdHTTP1->Response->Date));
if (DateToStr(IdHTTP1->Response->Expires) != str)
Memo1->Lines->Add(DateTimeToStr(IdHTTP1->Response->Expires));
if (DateToStr(IdHTTP1->Response->LastModified) != str)
Memo1->Lines->Add(DateTimeToStr(IdHTTP1->Response->LastModified));
}
//---------------------------------------------------------------------------
That being said, using strings to compare date/time values is not a good idea in general. Such strings are subject to locale issues. You are using conversion functions that are dependent on the local machine's current locale, not HTTP's standardized date/time formats. The TIdHTTP properties you are using are TDateTime values, where TIdHTTP has already translated the HTTP-provided values into binary values in local date/time (based on the local machine's current timezone). You can compare those values as-is without worrying about any string conversions, eg:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
TDateTime dt = ...; // assign some value
// see functions such as Date(), Now(), EncodeDateTime(), etc,
// or use the TDateTimePicker component...
IdHTTP1->Head("http://dsrt.dyndns.org/files/MAIN.zip");
if (IdHTTP1->Response->Date != dt)
{
//...
}
if (IdHTTP1->Response->Expires != dt)
{
//...
}
if (IdHTTP1->Response->LastModified != dt)
{
//...
}
}
Doing TDateTime comparisons is much more accurate and reliable than string comparisons. And you are not limited to just the == and != operators, you can use the < and > operators as well:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
TDateTime dt = Date();
IdHTTP1->Head("http://dsrt.dyndns.org/files/MAIN.zip");
if (IdHTTP1->Response->Date < dt)
{
// older than today...
}
if (IdHTTP1->Response->Expires < dt)
{
// expired prior to today...
}
if (IdHTTP1->Response->LastModified < dt)
{
// last modified prior to today...
}
}

Related

Reading stream of Data using TIdIOHandlerStream and TIdTCPClient

I have an app that needs to connect to a server using TCP/IP and then just wait for server to send data, and what ever server sends should be saved into a file.
Here is what I did:
The Header file
#ifndef MainH
#define MainH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <FMX.Controls.hpp>
#include <FMX.Forms.hpp>
#include <FMX.Controls.Presentation.hpp>
#include <FMX.StdCtrls.hpp>
#include <FMX.Types.hpp>
#include <IdBaseComponent.hpp>
#include <IdComponent.hpp>
#include <IdIOHandler.hpp>
#include <IdIOHandlerStream.hpp>
#include <IdTCPClient.hpp>
#include <IdTCPConnection.hpp>
#include <boost/scoped_ptr.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TIdTCPClient *pTCP;
TIdIOHandlerStream *IdIOHandlerStream;
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
void __fastcall IdIOHandlerStreamGetStreams(TIdIOHandlerStream *ASender, TStream *&VReceiveStream, TStream *&VSendStream);
private: // User declarations
boost::scoped_ptr<TFileStream> mFile;
boost::scoped_ptr<TMemoryStream> mMem;
void __fastcall StopTcpClick(TObject* Sender);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
and the CPP file:
include <fmx.h>
#pragma hdrstop
#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.fmx"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner),
mFile(new TFileStream(L"C:\\IbsData.txt", fmCreate | fmOpenReadWrite | fmShareDenyWrite)),
mMem(new TMemoryStream())
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
pTCP->Connect();
Button1->Text = L"Stop";
Button1->OnClick = StopTcpClick;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StopTcpClick(TObject* Sender)
{
pTCP->Disconnect();
Button1->Text = L"Start";
Button1->OnClick = Button1Click;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdIOHandlerStreamGetStreams(TIdIOHandlerStream *ASender, TStream *&VReceiveStream, TStream *&VSendStream)
{
VReceiveStream = mFile.get();
VSendStream = mMem.get();
}
I have to note that IdIOHandlerStream has been set as the IOHandler of pTCP.
The problem is, I know server is sending lots of data, but nothing gets written into the file.
Does anyone know why?
You are using the wrong IOHandler class.
TIdIOHandlerStream performs I/O using TStream objects. It is typically used for replaying previously captured sessions for debugging purposes, without needing a physical connection to a real server.
You need to use TIdIOHandlerStack instead, which performs I/O using a TCP/IP socket connection. It is Indy's default IOHandler class, so you don't even need to create an instance of it 1, TIdTCPClient::Connect() will create one internally for you if you do not assign your own.
1: unless you need more advanced usage, like connecting to a server through a proxy, etc, then you need your own instance so you can configure it as needed.
For what you are attempting, let TIdTCPClient use TIdIOHandlerStack and then you can call the TIdIOHandler::ReadStream() method after connecting to the server. Pass in a TFileStream for it to read into, and set its AByteCount parameter to -1 and AReadUntilDisconnect parameter to True so it will read continuously until the socket connection is closed.
Also, like most operations in Indy, ReadStream() blocks the calling thread until finished, so to avoid blocking your UI, you should call ReadStream() in a worker thread. But, if you don't want to use a thread, you can alternately put a TIdAntiFreeze component on your Form instead.

How to cast Interfaces with VCL components in C++Builder

The accepted answer in this question shows how to check for and use an interface on a VCL-derived object in Delphi.
How to use Interface with VCL Classes - Part 2
procedure Test;
var
O1: TSomeThing;
Intf: ISomething;
begin
O1 := TSomeThing.Create(nil);
if Supports(O1, ISomething, Intf) then
begin
Intf.DoSomething;
end;
Basically, I want to do the same in C++Builder but haven't worked out how to use "Supports" from C++.
Attempting to use <dynamic_cast> fails at compile time when using VCL-derived classes...
TSomeThing * O1;
ISomething *i = dynamic_cast<ISomething*>(O1); // Error: Can't cast
The suggested Inheritance and Interfaces article mentions TObject::GetInterface() but when I try that I get an error "Pure Virtual Function called".
_di_IFoo mc;
if (this->GetInterface(mc)) ...
Update: First, the objects I'm adding interfaces to are existing VCL controls so NOT derived from TInterfacedObject.
Second - there's no COM involved - I hope! The use of Interfaces is purely to allow me to use the concept of interfaces for multiple inheritance with VCL components which C++Builder (at least, in 2010) does not support.
So my interface looks like this (NOTE that there's no __addref/__release etc...):
__interface INTERFACE_UUID("{C527B88F-3F8E-1134-80e0-01A04F57B270}") IMyInterface : public IInterface
{
public:
virtual UTF8String getHello() = 0;
};
And my objects looks like this
class TMyPanel: public TPanel, IMyInterface
{
...
public:
UTF8String getHello() { return "Hello from a TMyPanel";}
...
};
class TMyLabel: public TLabel, IMyInterface
{
...
public:
UTF8String getHello() { return "Hello from a TMyLabel";}
...
};
That's straightforward, and as described in the Embarcadero docs for Interfaces.
But, how to tell if a particular TObject supports IMyInterface???
The following template function does this for me, based on TObject.GetInterfaceEntry() from system.pas:
template<typename T>
T* getInterface(TObject *obj)
{
T *intf = NULL;
PInterfaceEntry interfaceEntry = obj->GetInterfaceEntry(__uuidof(T) );
if (interfaceEntry && interfaceEntry->IOffset != 0)
{
intf = (T*)(((char *)obj) + interfaceEntry->IOffset);
}
return intf;
}
And we use it like this:
IMyInterface *myIf = getInterface<IMyInterface>(aRandomTObject);
if (myIf)
{
UTF8String s = myIf->getHello();
}
Please let me know if there's a better way than this, as the VTable/Pointer spelunking makes my teeth itch...
You do it the same way in C++ as in Delphi - via the Sysutils::Supports() function.
This works for me when I try it:
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
void __fastcall FormClick(TObject *Sender);
private: // User declarations
TPanel *p;
TLabel *l;
void Test();
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm7 *Form1;
//---------------------------------------------------------------------------
__interface INTERFACE_UUID("{C527B88F-3F8E-1134-80e0-01A04F57B270}") IMyInterface : public IInterface
{
public:
virtual UTF8String getHello() = 0;
};
#if !defined(INTFOBJECT_IMPL_IUNKNOWN)
#define INTFOBJECT_IMPL_IUNKNOWN(BASE) \
ULONG __stdcall AddRef() { return BASE::_AddRef();} \
ULONG __stdcall Release(){ return BASE::_Release();} \
HRESULT __stdcall QueryInterface(REFIID iid, void** p){ return BASE::QueryInterface(iid, p);}
#endif
class TMyPanel : public TPanel, public IMyInterface
{
INTFOBJECT_IMPL_IUNKNOWN(TPanel)
public:
__fastcall TMyPanel(TComponent *Owner) : TPanel(Owner) {}
UTF8String getHello() { return "Hello from a TMyPanel"; }
};
class TMyLabel : public TLabel, public IMyInterface
{
INTFOBJECT_IMPL_IUNKNOWN(TLabel)
public:
__fastcall TMyLabel(TComponent *Owner) : TLabel(Owner) {}
UTF8String getHello() { return "Hello from a TMyLabel"; }
};
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
p = new TMyPanel(this);
p->Parent = this;
l = new TMyLabel(this);
l->Parent = p;
l->Caption = L"Test";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClick(TObject *Sender)
{
Test();
}
//---------------------------------------------------------------------------
void TForm1::Test()
{
DelphiInterface<IMyInterface> Intf;
if (Supports(p, __uuidof(IMyInterface), (void*)&Intf))
{
UTF8String s = Intf->getHello();
ShowMessage(s);
Intf.Release();
}
if (Supports(l, __uuidof(IMyInterface), (void*)&Intf))
{
UTF8String s = Intf->getHello();
ShowMessage(s);
Intf.Release();
}
}
//---------------------------------------------------------------------------

How to put TEdit data into String C++ Builder

I am new in programming. Actually I am in 2nd year of college and starting an internship. They want me to do a program in C++ builder but I only know C. What I studied. And I don't have any knowledge about OOP.
So my question is.
I have TEdit1 and I want to verify if the data introduced in that textbox is a number. I know to verify if it is a number but I don't know how to put data from TEdit into string.
I wrote some code but it doesn't work.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int Size = Edit1->GetTextLen(); //Get length of string in Edit1
Size++; //Add room for null character
Char *Buffer = new Char[Size]; //Creates Buffer dynamic variable
std::auto_ptr<Char> Buffer(new Char[Size]);
Edit1->GetTextBuf(Buffer.get(),Size); //Puts Edit1->Text into Buffer
ShowMessage(Buffer);
}
And I get these errors:
E2034 Cannot convert 'std::auto_ptr<wchar_t>' to 'UnicodeString'
E2342 Type mismatch in parameter 'Msg' (wanted 'const UnicodeString', got std::auto_ptr<wchar_t>')
Can you please explain what i did wrong, or where i can found Embarcadero C++ Builder tutorials? I searched all google and didn't find something to help me.
Your code has several mistakes in it:
you are declaring two Buffer variables in the same scope. That is not allowed. You need to remove one of them.
you are passing the std::auto_ptr itself to ShowMessage(), but it expects a System::UnicodeString instead, thus the compiler error message. You can use the std::auto_ptr::get() method to get the wchar_t* pointer and pass it to ShowMessage(), as UnicodeString has a constructor that accepts wchar_t* as input:
ShowMessage(Buffer.get());
despite the above, you actually cannot use a pointer from new[] with std::auto_ptr to begin with. std::auto_ptr uses delete instead of delete[] to free the memory being pointed at. You must always use delete with new, and delete[] with new[]. So, while the code will compile, it will not free the memory correctly at runtime. C++11 introduced a new std::unique_ptr class to replace std::auto_ptr, and std::unique_ptr supports new[] and delete[] (however, C++Builder's 32bit compiler does not support C++11 yet - that is in the works - but its 64bit compiler does):
#include <memory>
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int Size = Edit1->GetTextLen(); //Get length of string in Edit1
Size++; //Add room for null character
std::unique_ptr<Char[]> Buffer(new Char[Size]); //Creates Buffer dynamic variable
Edit1->GetTextBuf(Buffer.get(), Size); //Puts Edit1->Text into Buffer
ShowMessage(Buffer.get());
}
Now, with that said, if you are going to continue using C++Builder, you should learn how to use its built-in functionalities, like UnicodeString, which the RTL/VCL relies heavily on (use the System::String alias for most code, use UnicodeString directly only when absolutely necessary).
Your example can be vastly simplified using the TEdit::Text property:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String s = Edit1->Text; //Get string in Edit1
ShowMessage(s);
}
The simplest solution to your problem would be to use the TCSpinEdit component instead of TEdit, as TCSpinEdit only allows numeric input in the first place, and has a Value property that returns an int:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int number = CSpinEdit1->Value;
ShowMessage("It is a number");
// use number as needed...
}
But, if you have to stick with TEdit, there are many ways to check a UnicodeString for numeric content.
You can set the TEdit::NumbersOnly property to true so the user cannot enter a non-numeric value (unless they use copy/paste, but let's ignore that for the moment), and then use the RTL's StrToInt() function, or System::UnicodeString::ToInt() method, to convert it as-is:
#include <System.SysUtils.hpp>
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int number;
try
{
number = StrToInt(Edit1->Text);
// or: number = Edit1->Text.ToInt();
}
catch (const EConvertError&)
{
// not a number, do something else...
ShowMessage("It is not a number");
return;
}
ShowMessage("It is a number");
// use number as needed...
}
Or you can use the RTL's System::Sysutils::TryStrToInt() function:
#include <System.SysUtils.hpp>
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int number;
if (TryStrToInt(Edit1->Text, number))
{
// use number as needed...
ShowMessage("It is a number");
}
else
{
// not a number, do something else...
ShowMessage("It is not a number");
}
}
Or you can use the STL's std::wistringstream class:
#include <sstream>
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int number;
std::wistringstream iss(Edit1->Text.c_str());
if (iss >> number)
{
// use number as needed...
ShowMessage("It is a number");
}
else
{
// not a number, do something else...
ShowMessage("It is not a number");
}
}
Or, since you have a C background, you can use the C _wtoi() function (which doesn't offer much in the way of error checking):
#include <cstdlib>
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int number = std::_wtoi(Edit1->Text.c_str());
if (number != 0)
{
// use number as needed...
ShowMessage("It is a valid number");
}
else
{
// not a number, do something else...
ShowMessage("It is not a valid number");
}
}
Or you can use the C wcstol() function:
#include <cstdlib>
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String s = Edit1->Text;
Char *p = s.c_str(), *end;
int number = std::wcstol(p, &end, 10);
if (end != p)
{
// use number as needed...
ShowMessage("It is a number");
}
else
{
// not a number, do something else...
ShowMessage("It is not a number");
}
}
Or you can use the C swscanf() function:
#include <cstdio>
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int number;
if (std::swscanf(Edit1->Text.c_str(), L"%d", &number) == 1)
{
// use number as needed...
ShowMessage("It is a number");
}
else
{
// not a number, do something else...
ShowMessage("It is not a number");
}
}

Problems with property editor in Embarcadero XE6

As usual, every new release of c++ builder takes days of changes...
I'm having trouble fixing a property editor, the code is:
***************** THE H FILE ****************************
//---------------------------------------------------------------------------
#ifndef ufrmLabelEditorH
#define ufrmLabelEditorH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.Buttons.hpp>
#include <Vcl.ExtCtrls.hpp>
#include <DesignIntf.hpp>
#include <TypInfo.hpp>
#include <DesignEditors.hpp>
#include <Classes.hpp>
// Add DesignIDE.bpi to your package's Requires list in the Project Manager
#pragma comment(lib, "DesignIDE.bpi")
//---------------------------------------------------------------------------
class TfrmLabelEditor : public TForm
{
__published: // IDE-managed Components
TPanel *Panel1;
TMemo *Memo1;
TBitBtn *BitBtn1;
TBitBtn *BitBtn2;
private: // User declarations
public: // User declarations
__fastcall TfrmLabelEditor(TComponent* Owner);
};
class PACKAGE TLabelProperty : public TStringProperty
{
public:
virtual Designintf::TPropertyAttributes __fastcall GetAttributes() {
return TStringProperty::GetAttributes()<<paDialog;
}
virtual void __fastcall Edit(void) {
TfrmLabelEditor *frmEditor = new TfrmLabelEditor(Application);
frmEditor->Memo1->Lines->Text = GetStrValue();
try {
if (frmEditor->ShowModal()==mrOk) {
int i;
for (i = 0; i < PropCount; i++) {
((TLabel*)GetComponent(i))->Caption = frmEditor->Memo1->Lines->Text;
}
Modified();
}
} catch (...) {
}
frmEditor->Free();
}
};
//---------------------------------------------------------------------------
extern PACKAGE TfrmLabelEditor *frmLabelEditor;
//---------------------------------------------------------------------------
#endif
************** THE CPP FILE *************************
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "ufrmLabelEditor.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TfrmLabelEditor *frmLabelEditor;
//---------------------------------------------------------------------------
__fastcall TfrmLabelEditor::TfrmLabelEditor(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
namespace Labelproperty {
void __fastcall PACKAGE Register()
{
TTypeInfo* typeInfo = new TTypeInfo();
typeInfo->Name = "AnsiString";
typeInfo->Kind = tkLString;
Designintf::RegisterPropertyEditor(typeInfo,__classid(TfrmLabelEditor),"Caption", __classid(TLabelProperty));
TComponentClass classes[1] = {__classid(TfrmLabelEditor)};
RegisterComponents(L"SGM", classes, 0);
}
}
Both files are part of a design time only c++ package....
Any help? If not, please tell me about some c++ ide that realy works!!!!! THANKS.....
Your Register() function relies on an unnecessary hack to fake AnsiString RTTI. Not only that, but the VCL uses Unicode strings in XE6, so unless your Caption property is actually declared as AnsiString then your property editor will not register correctly.
Let the property itself provide the correct RTTI to you. The RegisterPropertyEditor() documentation even demonstrates this. This approach works in every version of C++Builder (and Delphi):
void __fastcall PACKAGE Register()
{
PPropInfo pProp = GetPropInfo(__typeinfo(TfrmLabelEditor), "Caption");
RegisterPropertyEditor(*(pProp->PropType), __classid(TfrmLabelEditor), "Caption", __classid(TLabelProperty));
TComponentClass classes[1] = {__classid(TfrmLabelEditor)};
RegisterComponents(L"SGM", classes, 0);
}
Update: That being said, this registration will never work, because you are setting the second parameter of RegisterPropertyEditor() to the wrong value.
TfrmLabelEditor is itself implemented and exists only in a design-time package. By setting the second parameter to TfrmLabelEditor, the Object Inspector will invoke TLabelProperty only when an instance of TfrmLabelEditor is active in the Form Designer and its Caption property is edited in the Object Inspector. But the Form Designer will never see instances of TfrmLabelEditor in projects, so the Object Inspector will never invoke your TLabelProperty editor. That is why you don't see anything happen.
Read the documentation more carefully. The second parameter specifies a specific runtime component type, or NULL for all component types, that have the specified property of the specified property type. TfrmLabelEditor does not qualify for that.
A little adaptation of REMY SOLUTION have worked, not sure why:
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TfrmLabelEditor)};
//********* register my editors ******************
PPropInfo PropInfo = GetPropInfo(__typeinfo(TForm), "Caption");
Designintf::RegisterPropertyEditor(*(PropInfo->PropType),NULL,"Caption", __classid(TLabelProperty));
//*************************************************
RegisterComponents(L"SGM", classes, 0);
}

Builder c++ TButton problems?

I'm using Builder C++ 6.
in the folowing code I want my function KreirajPOlja() to generate random AnsiString characters on the buttons but what i always gain is just matrix 9*9 with just one generated character as in the picture:
void __fastcall TForm1::KreirajPolja()
{
int tr;
for(int i=0;i<dim_x;i++)
for(int j=0;j<dim_y;j++) {
Dugme[i][j]->Height=20;
Dugme[i][j]->Width=Dugme[i][j]->Height;
Dugme[i][j]->Left=i*Dugme[i][j]->Height;
Dugme[i][j]->Top=j*Dugme[i][j]->Height;
Dugme[i][j]->Parent=this;
tr=PostaviRandom();
Dugme[i][j]->Caption= NizSlova[tr];
}
Button1->Caption="submit";
Button1->Enabled=false;
Form1->Width=dim_x* 20+5;
Form1->Height=(dim_y+2)* 20+25;
}
//---------------------------------------------------------------------------
int __fastcall TForm1::PostaviRandom(){
int k;
srand(time(0));
k=rand()%sizeof(NizSlova);
return k;}
and here is the folowing cpp code
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <time.h>
//--- ------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
void __fastcall FormCreate(TObject *Sender);
public: // User declarations
TButton*** Dugme;
TImage *** Slike;
TEdit *brojac;
int dim_x, dim_y;
int vrijeme,kr;
int BrojSlova, br;
AnsiString NizSlova;
__fastcall TForm1(TComponent* Owner);
void __fastcall KreirajSlova();
void __fastcall AlocirajProstor();
void __fastcall BrisiProstor();
void __fastcall AlocirajProstorZaSlova();
void __fastcall BrisiProstorZaSlova();
void __fastcall KreirajPolja();
virtual int __fastcall PostaviRandom();
AnsiString __fastcall DajSlovo();
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Don't call srand in your loop. Call it once at the start of the program.
Each time you call srand you reset the random number generator. Since you call it with the same parameter each time (your code runs in less than a second so the value of time(NULL) doesn't change), you get the same result from rand().
There is no need to call srand multiple times in the same program unless you intentionally want to reproduce an old sequence of random numbers.

Resources