E2034 Cannot convert 'TImage * *' to 'TImage *'
(szukałem na necie jak to naprawić i właśnie coś takiego tam było, część błędów zniknęła chociaż średnio mam pojęcie co właściwie wtedy zrobiłem)
Zapewne ktoś kto odpowiedział nie do końca wiedział co i jak. Jednak faktycznie na pierwszy rzut oka takie błędy kompilacji można stosować (bez głębszego zastanowienia) dokładając gwiazdki, ampersandy ;)
Z ciekawości spytam, bo nie rozumiem jak działa w Twoim kodzie linia:
int i = ((TImage*)Sender)->Tag;
A dokładniej "((TImage*)Sender)", wiem jakie ma znaczenie w całej funkcji jednak niezbyt pojmuję skąd to pobiera informacje które pole zostało kliknięte.
Spójrzmy na to co dokumentacja mówi. Dla ułatwienia przytoczę fragment dokumentacji TImage http://docwiki.embarcadero.com/Libraries/Sydney/en/Vcl.ExtCtrls.TImage oraz zdarzenie http://docwiki.embarcadero.com/Libraries/Sydney/en/Vcl.Controls.TControl.OnClick
Jest to zdarzenie które jest wywoływane podczas kliknięcia każdego komponentu jaki masz na formatce (o ile posiada ono zdarzenie OnClick). Każdy komponent ma swoje zdarzenia. Co więcej kilka komponentów może mieć podłączone tą samą metodę pod zdarzenie OnClick
(tak jak pokazałem w przykładzie) Samo zdarzenie jest typu TNotifyEvent
http://docwiki.embarcadero.com/Libraries/Sydney/en/System.Classes.TNotifyEvent
Widzisz w dokumentacji, że jako argument jest przekazany TObject* Sender
i przechodząc do sedna zacytuję dokumentację:
The Sender parameter is the object whose event handler is called. For example, with the OnClick event of a button, the Sender parameter is the button component that is clicked.
Zatem parametr Sender
wskazuje na komponent który wywołał owe zdarzenie. Jako, że zdarzenie ma być uniwersalne to wybrano jako typ parametru wskaźnik na TObject
po którym dziedziczą kontrolki. Zatem można bezpiecznie rzutować wskaźnik do kontrolki na wskaźnik na typ TObject
Sam TObject
nie posiada takiej właściwości jak Tag
jednak my pisząc program wiemy, że możemy rzutować w dół w hierarchii obiektów z TObject*
na TImage*
robimy to by móc dostać się do właściwości Tag
A wiemy że takie rzutowanie jest prawidłowe, ponieważ sami podpięliśmy zdarzenie pod kontrolkę TImage i Sender wskazuje na poprawny obiekt Timage.
Jednak ten mój kod który Ci przedstawiłem jest nieco zamotany, chciałem połączyć tablicę wskaźników na komponenty TImage
wraz ze wspólnym zdarzeniem OnClick
. Taki obrazowy przykład który pokaże, że Sender
zawiera wskaźnik na konkretny obiekt.
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Image1->Tag = 0;
Image2->Tag = 1;
Image3->Tag = 2;
Image4->Tag = 3;
Image1->OnClick = OnImageClick;
Image2->OnClick = OnImageClick;
Image3->OnClick = OnImageClick;
Image4->OnClick = OnImageClick;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnImageClick(TObject *Sender)
{
if (Sender == Image1)
{
ShowMessage("Image 1 clicked!");
}
if (Sender == Image2)
{
ShowMessage("Image 2 clicked!");
}
if (Sender == Image3)
{
ShowMessage("Image 3 clicked!");
}
if (Sender == Image4)
{
ShowMessage("Image 4 clicked!");
}
TImage* currentImage = (TImage*)Sender;
ShowMessage(currentImage->Tag);
}
//---------------------------------------------------------------------------
Zatem nie wiem czy nie lepiej tego zrobić w ten sposób niż kombinować z tablicami. Przecież o ile dobrze myślę chcesz po prostu w zdarzeniu załadować odpowiednią bitmapę X albo O. Więc wystarczy tylko rzutować Sender na TImage
void __fastcall TForm1::OnImageClick(TObject *Sender)
{
TImage* currentImage = (TImage*)Sender;
currentImage->Picture->LoadFromFile("img/x.bmp");
}