ingalime wrote:ListBox1->Items->AddObject(L"Test", (TObject)(* Pint));
AddObject() expects a TObject*
pointer, but you are trying to pass it a TObject
object instance that is constructed with an 'int' as input. TObject has no such constructor, that is why you are getting an error.
You need to change your type-cast to this:
- Code: Select all
ListBox1->Items->AddObject(L"Test", (TObject*)Pint);
// or:
// ListBox1->Items->AddObject(L"Test", reinterpret_cast<TObject*>(Pint));
ingalime wrote:delete ListBox1->Items->Objects[i];
This is also wrong. You are trying to delete a TObject instance, but you actually allocated an 'int' instead. You need to cast the pointer back to the correct type so 'delete' acts correctly:
- Code: Select all
delete (int*)(ListBox1->Items->Objects[i]);
// or:
// delete reinterpret_cast<int*>(ListBox1->Items->Objects[i]);
That being said, I would not suggest dynamically allocating the 'int' at all. You can store its value as-is, just type-casted to a pointer:
- Code: Select all
int i = 1;
ListBox1->Items->AddObject(L"Test", (TObject*)i);
// or:
// ListBox1->Items->AddObject(L"Test", reinterpret_cast<TObject*>(i));
Then you don't need to call 'delete' at all, since nothing is being allocated with 'new'.
Use a similar cast to read the 'int' value:
- Code: Select all
int value = (int)(ListBox1->Items->Objects[index]);
// or:
// int value = reinterpret_cast<int>(ListBox1->Items->Objects[index]);
In fact, integer-to-pointer and pointer-to-integer casts are one of the main reasons reinterpret_cast even exists in the first place.
Now, that being said, note that this approach only works in VCL, and FMX non-ARC systems. Under ARC, TObject* pointers MUST point at valid TObject instances, so you would have to wrap the 'int' in a TObject-derived class:
- Code: Select all
class TIntWrapper : public TObject
{
public:
int Value;
__fastcall TIntWrapper(int InitialValue = 0) : TObject(), Value(InitialValue) {}
};
...
TIntWrapper * Pint = new TIntWrapper(1);
ListBox1->Items->AddObject(L"Test", Pint);
...
int value = ((TIntWrapper*)(ListBox1->Items->Objects[index]))->Value;
// or:
// int value = static_cast<TIntWrapper*>(ListBox1->Items->Objects[index])->Value;
No need to 'delete', since ARC objects are reference counted.
Otherwise, use a completely different design that does not rely on storing the 'int' in the ListBox itself. Store it in an array/list off to the side, and then use ListBox indexes to access that array/list when needed. This design better separates your data from your UI:
- Code: Select all
private:
std::vector<int> MyValues; // or whatever container you want to use...
...
MyValues.push_back(1);
try {
ListBox1->Items->Add(L"Test");
}
catch (const Exception &) {
MyValues.pop_back();
throw;
}
...
int value = MyValues[index];
This works especially well with TListBox::Style set to lbVirtual or lbVirtualOwnerDraw (VCL only):
- Code: Select all
private:
std::vector<std::pair<String, int> > MyItems;
...
MyItems.push_back(std::make_pair(L"Test", 1));
ListBox1->Count = MyItems.size();
...
int value = MyItems[Index].second;
Then you just need a TListBox::OnData event handler to populate the ListBox with string values (and optionally a TListBox::OnDataFind event handler to handle searches and auto-completion):
- Code: Select all
void __fastcall TForm1::ListBox1Data(TWinControl *Control, int Index, String &Data)
{
Data = MyItems[Index].first;
}
int __fastcall TForm1::ListBox1DataFind(TWinControl *Control, String FindString)
{
auto iter = std::find_if(MyItems.begin(), MyItems.end(),
[=](const std::pair<String, int> &item){ return (item.first == FindString); });
return (iter != MyItems.end())
? (int) std::distance(MyItems.begin(), iter)
: -1;
}