Auf Parent der CheckBox zugreifen
-
Hallo,
ich möchte auf das Parent(Panel) eines Objects ,hier CheckBox, zugreifen und
dessen Caption lesen.
Wie stell ich so was an?(((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->Parent->? == "Reserved")
((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->(TPanel*)Parent->Caption == "Reserved")
geht ebenfalls nicht.
-
Hallo
da ist immer erstmal günstiger, Schritt für Schritt durchzugehen (soweit ich den Sinn verstanden habe).
Und vor allem C++ Casts zu verwendenTCheckBox* checkbox = static_cast<TCheckBox*>(AlarmCheck->Items[Cb+(Index*5)]); // was ist AlarmCheck? Was gibt Items zurück? cast vielleicht unnötig TPanel* panel = static_cast<TPanel*>(checkbox->Parent); panel->Caption = "Reserved";Zusammensetzen kannst du es nun selber, aber ich denke das es zu unübersichtlich wird.
Übrigens ist == kein Operator zum Lesen eines Wertes.bis bald
akari
-
Hallo
ich glaube, ich habe das ganze etwas aus dem Zusammenhang geriessen.
Ich erzeuge mir dynamisch eine GroupBox und in der Box Panels auf denen
immer 5 CheckBoxen instanziert werden.Dieses passiert in der Funktion
DrawAlarmList(AnsiString BoxName, unsigned char Mask,const char * List)
hier ist BoxName der Name der GroupBox.
List beinhaltete die Captions der einzelnen Panels.
Mask gibt an welche der 5 CheckBoxenauf dem Panel Enabled sein sollen.
Die CheckBoxen sollen ebenfalls nicht enabled sein wenn das Caption des
Panels auf dem sie sich befinden "Reserved" ist.Bei der Abfrage gibt es eine
Fehler Meldung.if( !((1<<Cb)&Mask) || ( ((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->(TPanel*)Parent->Caption == "Reserved") ) { ((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->Enabled = false; }Das ganze sieht dann so aus.
//------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ void __fastcall TRelayData::FormCreate(TObject *Sender) { const char SupplyAlarmList[] = { "AC MAINS L1 FAIL ""\0" "AC MAINS L2 FAIL ""\0" "AC MAINS L3 FAIL ""\0" "DC OVERVOLTAGE ""\0" "DC UNDERVOLTAGE ""\0" "POWER LIMIT ""\0" "MODULE OVERTEMP ""\0" "MODUL1 FAIL ""\0" "MODUL2 FAIL ""\0" "MODUL3 FAIL ""\0" "MODUL4 FAIL ""\0" "ALARM1 ""\0" "ALARM2 ""\0" "ALARM3 ""\0" "ALARM4 ""\0" "ALARM5 ""\0" "ALARM6 ""\0" "ALARM7 ""\0" "ALARM8 ""\0""\0" }; const char UltraCapList[] = { "OVERTEMP ""\0" "SYMMETRIE ERROR ""\0" "Reserved ""\0""\0" }; const char InverterList[] = { "Reserved ""\0" "Reserved ""\0" "Reserved ""\0" "Reserved ""\0" "Reserved ""\0""\0" }; const char Hallo[] = { "bbbbbbbbbb ""\0" "aaaaaaa ""\0" "RESERVE ""\0""\0" }; DrawAlarmList("Supply",0x13,SupplyAlarmList); DrawAlarmList("EnergieBlock",0x13,UltraCapList); DrawAlarmList("Reserve",0x13,InverterList); ((TPanel*)Alarme->Items[0])->Color = clYellow; } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ void TRelayData::DrawAlarmList(AnsiString BoxName, unsigned char Mask,const char * List) { #define BOX_WIDTH 740 #define PANEL_TOP 20 #define PANEL_LEFT 10 #define PANEL_HEIGHT 20 #define PANEL_WIDTH 700 #define CHECK_BOX_LEFT 500 #define CHECK_BOX_STEP 30 #define ENABLE 0x1f static int LastTopPos = 21; static int LastIndex = 0; //Bei der ersten AlarmBox "AlarmPanel sowie CheckBox" - Listen instanzieren if(LastIndex == 0) { Alarme = new TList; AlarmCheck = new TList; Alarme->Count = 500; AlarmCheck->Count = 500; } ListLenght = 0; while(List[ListLenght*29] != 0)ListLenght++;; //Neu Box erzeugen AlarmBox = new TGroupBox((TComponent*)this); AlarmBox->Parent = Gesamt; AlarmBox->Caption = BoxName; AlarmBox->Width = BOX_WIDTH; AlarmBox->Height = ((ListLenght+1)*PANEL_HEIGHT)+10; AlarmBox->Left = 10; AlarmBox->Top = LastTopPos; LastTopPos += AlarmBox->Height+1; AlarmBox->Visible = true; //-------------------------------------------- TextIndex = 0; for(int Index = LastIndex; Index < (ListLenght+LastIndex); Index++) { //Panels erzeugen Alarme->Items[Index] = new TPanel((TComponent*)this); ((TPanel*)Alarme->Items[Index])->Parent = AlarmBox; ((TPanel*)Alarme->Items[Index])->Alignment = taLeftJustify; ((TPanel*)Alarme->Items[Index])->Height = PANEL_HEIGHT; ((TPanel*)Alarme->Items[Index])->Width = PANEL_WIDTH; ((TPanel*)Alarme->Items[Index])->Top = PANEL_TOP+(TextIndex*20); ((TPanel*)Alarme->Items[Index])->Left = PANEL_LEFT; ((TPanel*)Alarme->Items[Index])->Caption = AnsiString().sprintf(" %3d",Index)+" "+ (List+(TextIndex*29)); // ((TPanel*)Alarme->Items[Index])->OnMouseMove = MouseOnPanel; ((TPanel*)Alarme->Items[Index])->DoubleBuffered = true; ((TPanel*)Alarme->Items[Index])->Visible = true; //CheckBoxen erzeugen for(int Cb = 0; Cb <= 4; Cb++) { AlarmCheck->Items[Cb+(Index*5)] = new TCheckBox((TComponent*)this); ((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->OnClick = CheckBoxClick; ((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->OnMouseMove = MouseOnPanel; ((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->Parent = ((TPanel*)Alarme->Items[Index]); ((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->Top = 1; ((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->Left = CHECK_BOX_LEFT+(Cb*CHECK_BOX_STEP); ((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->Width = 15; //Zeiger auf Ram Array sowie die Maske ((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->Tag = (Index<<16)|1<<Cb; if( !((1<<Cb)&Mask) || ( ((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->(TPanel*)Parent->Caption == "Reserved") ) { ((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->Enabled = false; } ((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->DoubleBuffered = true; ((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->Visible = true; } TextIndex++; } LastIndex += ListLenght; AllAlerts = LastIndex; }Das ganze etwas vereinfacht.
void __fastcall TForm1::FormCreate(TObject *Sender) { TPanel *Panel = new TPanel((TComponent*)this); Panel->Parent = this; Panel->Caption = "Reserved"; TCheckBox *CheckBox = new TCheckBox((TComponent*)this); CheckBox->Parent = Panel; if(CheckBox->(TPanel*)Parent->Caption == "Reserved") CheckBox->Enabled = true; }Hier kommt eine Fehlermeldung "Elemente Bezeichner erwartet".
-
Hallo,
Du hast scheinbar das Prinzip des Castens noch nicht richtig verstanden.
Mit(TComponent*)TestKomponentewandelst du einen den die Variable TestKomponente in eine Variable vom Typ Zeiger auf TComponent um. Das geschieht hier ohne Typprüfung (da C-Style Cast).
1. Verwende C++-Style Casts (static_cast, dynamic_cast) statt deinen C-Style
http://www.c-plusplus.net/forum/viewtopic-var-t-is-39493.html
http://www.c-plusplus.net/forum/viewtopic-var-t-is-39463.html
2. Caste nur wenn es nötig ist.TPanel *Panel = new TPanel((TComponent*)this);Warum castest du hier this in TComponent?
3. Wenn du die zu castende Variable mehrfach benötigst erzeuge dir eine temporäre Variable und verwende dann diese
Bsp. statt((TPanel*)Alarme->Items[Index])->Parent = AlarmBox; ((TPanel*)Alarme->Items[Index])->Alignment = taLeftJustify; ((TPanel*)Alarme->Items[Index])->Height = PANEL_HEIGHT; ((TPanel*)Alarme->Items[Index])->Width = PANEL_WIDTH; ((TPanel*)Alarme->Items[Index])->Top = PANEL_TOP+(TextIndex*20); ((TPanel*)Alarme->Items[Index])->Left = PANEL_LEFT;lieber
TPanel* panel = dynamic_cast<TPanel*>(Alarme->Items[Index]); if( panel ) { panel->Parent = AlarmBox; panel->Alignment = taLeftJustify; panel->Height = PANEL_HEIGHT; panel->Width = PANEL_WIDTH; panel->Top = PANEL_TOP+(TextIndex*20); panel->Left = PANEL_LEFT; // usw.4. Was soll das hier
if(CheckBox->(TPanel*)Parent->Caption == "Reserved") CheckBox->Enabled = true;Das Cast ist hier falsch positioniert
TPanel* panel = dynamic_cast<TPanel*>(CheckBox->Parent); if(panel && panel->Caption == "Reserved") CheckBox->Enabled = true;oder hier besser gleich
if(Panel->Caption == "Reserved") CheckBox->Enabled = true;Belies dich bitt auch ein wenig bezüglich Polymorphie
http://www.tutorialpage.de/Cpp2/index.php?ziel=http://www.tutorialpage.de/Cpp2/chap5.php
http://www.volkard.de/vcppkold/polymorphie.html
-
Danke für die Hilfe, werde mich näher damit beschäftigen.
Du hast scheinbar das Prinzip des Castens noch nicht richtig verstanden.
Ich denke schon
unsigned char Buffer[2];
unsigned short Test = (unsigned short)((Buffer[1]<<8)&0xff00) | (unsigned short)(Buffer[0] & 0xff);Ich Caste hier für diese Operation Buffer auf unsigned short.
TPanel *Panel = new TPanel((TComponent*)this);
Warum castest du hier this in TComponent?Du hast recht, ich habe das ganze gerade probiert
TPanel *Panel = new TPanel(this);
irgendwie ist der Cast da reingewandert, weil die Fehlermeldung
Mehrdeutigkeit zwischen ...... kam, kann das ganze aber nicht mehr nachvollziehen
da der Fehler nun nicht mehr auftritt.
Irgenwie habe ich bei dem Object 3 Konstruktoren zur Auswahl unter anderem
einen mit dem Übergabeparameter TComponent *Owner, deswegen habe ich gecastet und der Fehler kam nicht mehr.Zum dynamic_cast, hier caste ich den Pointer Sender dynamisch ist Sender nicht
vom Datentyp TPanel wird ein NULL Pointer zurückgegeben.void _fastcall TRelayData::MouseOnPanel(TObject *Sender, TShiftState Shift, int X, int Y) { TPanel *Panel = dynamic_cast<TPanel*>(Sender); if(!Panel) { //Wenn nicht Panel dann war der Auslöser ein Object das das //Panel als Parent hat. Panel = dynamic_cast<TPanel*>(((TControl*)Sender)->Parent); }Wie gesagt, ich kann mir immer noch nicht erklären wie Oben der Fehler
Mehrdeutigkeit zwischen ...... kam.Das Cast ist hier falsch positioniert
TPanel* panel = dynamic_cast<TPanel*>(CheckBox->Parent); if(panel && panel->Caption == "Reserved") CheckBox->Enabled = true; TPanel* panel = dynamic_cast<TPanel*>(CheckBox->Parent); if(panel && panel->Caption == "Reserved") CheckBox->Enabled = true; TPanel* panel = dynamic_cast<TPanel*>(CheckBox->Parent); if(panel && panel->Caption == "Reserved") CheckBox->Enabled = true; oder hier besser gleich if(Panel->Caption == "Reserved") CheckBox->Enabled = true; if(Panel->Caption == "Reserved") CheckBox->Enabled = true; if(Panel->Caption == "Reserved") CheckBox->Enabled = true;Ok sieht gut aus. Meine Idee war CheckBox->Parent, hier ist Parent ja ein Objectzeiger auf das Parent(Panel) von CheckBox, über diesen Zeiger kann ich dann
doch gecastet auf den Datentypen TPanel* auf dessen Caption zugreifen oder.
Ist das nicht analog zu Panel->Caption?3. Wenn du die zu castende Variable mehrfach benötigst erzeuge dir eine temporäre Variable und verwende dann diese
Bsp. statt((TPanel*)Alarme->Items[Index])->Parent = AlarmBox; ((TPanel*)Alarme->Items[Index])->Alignment = taLeftJustify; ((TPanel*)Alarme->Items[Index])->Height = PANEL_HEIGHT; ((TPanel*)Alarme->Items[Index])->Width = PANEL_WIDTH; ((TPanel*)Alarme->Items[Index])->Top = PANEL_TOP+(TextIndex*20); ((TPanel*)Alarme->Items[Index])->Left = PANEL_LEFT; lieber TPanel* panel = dynamic_cast<TPanel*>(Alarme->Items[Index]); if( panel ) { panel->Parent = AlarmBox; panel->Alignment = taLeftJustify; panel->Height = PANEL_HEIGHT; panel->Width = PANEL_WIDTH; panel->Top = PANEL_TOP+(TextIndex*20); panel->Left = PANEL_LEFT; // usw.Finde ich auch besser so und vor allem sicherer durch den dynamic_cast, obwohl
sich in der Liste ausschließlich Pointer vom Datentyp TPanel* befinden.Belies dich bitt auch ein wenig bezüglich Polymorphie
Oh je das Wort hört sich schon kompliziert an, werde mal sehen.
Ach das ist die Sache mit der virtuellen Funktion, diese Funktion kann
in einer von der BasisKlasse abgeleiteten Klasse überschrieben werden.
Passiert dies nicht wird die Funktion der BasisKlasse ausgeführt.Was hat das mit den Sachen weiter Oben zu tun?
An die C++ Style Casts muss ich mich gewönnen, da ich sehr viel C
Programmiere ist man schnell dabei diese C Style Casts auch unter C++
zu verwenden. Werde mich diesbezüglich etwas am "Riemen reissen" und
C++ style Casts verwenden.Danke für die Lehreiche Hilfe.
-
Wenn du dir sicher bist, dass du den Typ des Objektes in Sender genau kennst, kannst du auch statt dynamic_cast einen static_cast verwenden und die Prüfung auf 0 weglassen. Falls es aber nicht stimmt, bekommst du interessante Fehlermeldungen.

-
Braunstein schrieb:
Wenn du dir sicher bist, dass du den Typ des Objektes in Sender genau kennst, kannst du auch statt dynamic_cast einen static_cast verwenden und die Prüfung auf 0 weglassen. Falls es aber nicht stimmt, bekommst du interessante Fehlermeldungen.

Ich denke mal es kommt im schlimmsten Fall eine Speicherzugriffsverletzung.
Ich würde das ganze etwas anders Formulieren, in deinem Kommentar sieht es so aus
als ob bei beiden Cast Arten im Fehler Fall ein NULL Pointer zurückgegeben
wird "kannst du auch statt dynamic_cast einen static_cast verwenden und die Prüfung auf 0 weglassen."
Natürlich kommt im beim static_cast im Fehlerfall kein NULL Pointer zurück.. Wenn du die zu castende Variable mehrfach benötigst erzeuge dir eine temporäre Variable und verwende dann diese
Bsp. statt((TPanel*)Alarme->Items[Index])->Parent = AlarmBox; ((TPanel*)Alarme->Items[Index])->Alignment = taLeftJustify; ((TPanel*)Alarme->Items[Index])->Height = PANEL_HEIGHT; ((TPanel*)Alarme->Items[Index])->Width = PANEL_WIDTH; ((TPanel*)Alarme->Items[Index])->Top = PANEL_TOP+(TextIndex*20); ((TPanel*)Alarme->Items[Index])->Left = PANEL_LEFT; lieber TPanel* panel = dynamic_cast<TPanel*>(Alarme->Items[Index]); if( panel ) { panel->Parent = AlarmBox; panel->Alignment = taLeftJustify; panel->Height = PANEL_HEIGHT; panel->Width = PANEL_WIDTH; panel->Top = PANEL_TOP+(TextIndex*20); panel->Left = PANEL_LEFT; // usw.Warum denn.
Alarme->Items[Index] = new TPanel(this); ((TPanel*)Alarme->Items[Index])->Parent = AlarmBox; ((TPanel*)Alarme->Items[Index])->Alignment = taLeftJustify; ((TPanel*)Alarme->Items[Index])->Height = PANEL_HEIGHT; ((TPanel*)Alarme->Items[Index])->Width = PANEL_WIDTH; ((TPanel*)Alarme->Items[Index])->Top = PANEL_TOP+(TextIndex*PANEL_HEIGHT); ((TPanel*)Alarme->Items[Index])->Left = PANEL_LEFT; ((TPanel*)Alarme->Items[Index])->Caption = AnsiString().sprintf(" %3d",Index)+" "+ (List+(TextIndex*29)); // ((TPanel*)Alarme->Items[Index])->OnMouseMove = MouseOnPanel; ((TPanel*)Alarme->Items[Index])->DoubleBuffered = true; ((TPanel*)Alarme->Items[Index])->Visible = true;Hier Instanziere ich mir ein Panel Object und schreibe es gleich in das
List Object, nun greife ich mit einem C Style Cast auf den in der Liste
instanzierten Pointer des Panels zu. Ist doch OK so.((TPanel*)Alarme->Items[Index])->Parent = AlarmBox;Warum sollte ich hier nicht einen C Style Cast nehmen, ist doch kein Unterschied
zum static_cast in beiden Fällen wird der Pointer Typ nicht überprüft.Zu meinem anfänglichem Problem, das habe ich nun so gelöst.
if( NULL != (TmpPanel = dynamic_cast<TPanel*>(((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->Parent)) ) PanelCaption = TmpPanel->Caption.SubString(7,8); if( !((1<<Cb)&Mask) || (PanelCaption == "Reserved") ) { ((TCheckBox*)AlarmCheck->Items[Cb+(Index*5)])->Enabled = false; }