Felder in ListView Komponente
-
Hi,
so in etwa müsste es gehen. Jetzt legst du für jeden Spieler einen neuen Eintrag an. Was korrekt ist! Probier es einfach mal aus, wenn du Zeit hast! Denk aber das es so funktioniert!!!
Gruß
-
xDannyOx schrieb:
Hi,
so in etwa müsste es gehen. Jetzt legst du für jeden Spieler einen neuen Eintrag an. Was korrekt ist! Probier es einfach mal aus, wenn du Zeit hast! Denk aber das es so funktioniert!!!
Gruß
leider nicht ganz, wenn ich auf einen Substring a la
ListView1->Items->Item[rownumber]->SubItems->Strings[0] = player->Strings[e + 1];zugreife bekomme ich wieder List Index out of Bound(0) (wegen SubItems->Strings[0]). Wie allokiere ich substrings zur laufzeit und nicht statisch im Objekt Inspektor
??
-
Verwurschtelst du gerade die Begriffe "SubString" und "SubItem"?
Ah ja, SubItems ist ne StringList. Solltest du also einfach Add verwenden können. (Falls ich jetzt richtig verstanden habe, was du willst. Ich glaube ja nicht.
)
-
Hi,
sorry war mein Fehler hab darauf gar nicht geachtet! Wenn du die Einträge neu anlegst, musst du natürlich auch die Substrings neu anlegen!
if(value == true) //Wenn die Liste fertig empfangen wurde { ListView1->Clear(); //säubern alter Einträge int rownumber = -1; for (e = 0; e < player->Count; e++) //Durch Stringliste iterieren { if(player->Strings[e].AnsiPos("deaths_") == 1) //Neuen Spieler in Liste erkennen und Zeilennummer brechnen { rownumber++; ListView1->Items->Add(); //Neuer eintrag pro Player ListView1->Items->Item[rownumber]->Caption = rownumber + 1; ListView1->Items->Item[rownumber]->SubItems->Add(player->Strings[e + 1]); //Death } if(player->Strings[e].AnsiPos("playername_") == 1) { ListView->Items->Item[rownumber]->SubItems->Add(player->Strings[e + 1]); //NameDas mit den Strings[index] geht nur wenn der Eintrag schon existiert!
Sorry, war mein Fehler!Gruß
-
Also wäre es so am Besten ,oder ?
if(player->Strings[e].AnsiPos("deaths_") == 1) //Neuen Spieler in Liste erkennen und ID berechnen { rownumber++; ListView1->Items->Add(); ListView1->Items->Item[rownumber]->Caption = rownumber + 1; ListView1->Items->Item[rownumber]->SubItems->Add(""); ListView1->Items->Item[rownumber]->SubItems->Strings[0] = player->Strings[e + 1]; //Death } if(player->Strings[e].AnsiPos("playername_") == 1) { ListView1->Items->Item[rownumber]->SubItems->Add(""); ListView1->Items->Item[rownumber]->SubItems->Strings[1] = player->Strings[e + 1]; //Name } }Zwar unsauber,aber.............
Ich kann leider auf den Index beim SubItem nicht verzichten
Denkt ihr das ist so ok wie oben beschrieben ?
-
Warum verwendest Du nicht TListItem* und eine TStringList?
ListView1->Items->Clear(); TListItem* tli; TStringList* tsl = new TStringList(); // für alle hinzuzufügenden Items tsl->Clear(); tli = ListView1->Items->Add(); tli->Caption = "xxx"; tsl->Add("yyy"); // alle Subitems der Stringliste hinzufügen tsl->Add("zzz"); tli->SubItems = tsl; // Subitems aus Stringliste zuweisen // nicht vergessen die StringList am Schluß wieder freizugeben delete tsl
-
@ Joe, genau in diesem Prinzip war mein erster Versuch, wie man an dem jpeg erkennt funktioniert es auch damit solange der Server die liste korrekt sendet.
Das heisst wenn ein Eintrag fehlt hilft mir das sequenzielle durchgehen nichts mehr. Ohne Positionen und AnsiPos bin ich aufgeschmissenWas haltet ihr von diesem Quick and dirty Beispiel ? ist zwar absolut unsauber aber praktikable denk ich mal:
for (e = 0; e < player->Count; e++) //Durch Stringliste iterieren { if(player->Strings[e].AnsiPos("deaths_") == 1) //Neuen Spieler in Liste erkennen und ID berechnen { rownumber++; ListView1->Items->Add(); ListView1->Items->Item[rownumber]->Caption = rownumber + 1; ListView1->Items->Item[rownumber]->SubItems->Add(""); ListView1->Items->Item[rownumber]->SubItems->Add(""); ListView1->Items->Item[rownumber]->SubItems->Add(""); ListView1->Items->Item[rownumber]->SubItems->Add(""); ListView1->Items->Item[rownumber]->SubItems->Add(""); ListView1->Items->Item[rownumber]->SubItems->Add(""); ListView1->Items->Item[rownumber]->SubItems->Add(""); ListView1->Items->Item[rownumber]->SubItems->Strings[0] = player->Strings[e + 1]; //Death } if(player->Strings[e].AnsiPos("playername_") == 1) ListView1->Items->Item[rownumber]->SubItems->Strings[1] = player->Strings[e + 1]; //Name if(player->Strings[e].AnsiPos("score_") == 1) ListView1->Items->Item[rownumber]->SubItems->Strings[2] = player->Strings[e + 1]; //ScoreEDIT: Ok, Joe, jetzt habe ich verstanden was du meinst, vergiss den Komentar oben. Vielen Dank euch allen !

-
Nun habe ich ein ganz kurioses Problem. Der Quelltext oben funktioniert bei 50,30 ,20 Serveranfragen nur bei manchen Server wirft er eine AccessViolation. Habe rausgefunden das er eine Accessviolation nur dann auslöst wenn ich die Stringliste player mit player->Clear() vor jedem erneuten durchlauf lösche. wenn ich player->Clear weglasse läuft die Abfrage bei allen 1500 Server wie geschmiert.
Ist halt klar das die Sringliste "player" pro Server wächst und wächst.Um die Lebensdauer über eine Funktion hinaus zu erhöhen habe ich die Stringliste global angelegt. Ich weiß das Globale Variablen nicht toll sind und in einer Klasse besser aufgehoben wären ,aber es funktioniert ja auch mal so zum Test.
Leider gibt es ja auch nen dicken Fehler wenn ich die Globale mit delete während der Laufzeit freigeben möchte, logisch.Ich bin momentan so Hilflos das ich nicht mehr weiter weiß. Wenn doch der Code bei 50,100,150 Server problemlos die gesendete Liste auswertet und nur sporatisch bei einzelnen Server mit ner AccessViolation rausspringt. Weiß jemand Rat was ich tun kann ?? Wenn doch der Code grundliegend falsch wäre würde ich doch keine 100 Server Problemlos abfragen können, aber beim 101. oder 121. ist mit einem Schlag schluss und die Exeption wird geworfen

Was kann ich da nur tun
-
Von was wird die AccessViolation den geworfen?
-
@ Joe, wenn ich zu Hause bin kann ich dir die ganze Fehlermeldung mal hier Posten. Beim rausspringen makiert der Debugger mir die Zeile Blau. Wenn ich dann mit der maus drüber fahre bekomme ich einen Exxxxx Fehlercode mit einer genauen bezeichnung des Fehlers dahinter. Ich werde es später posten.
Vielen Dank für deine Resonanz !
-
Also, der code Guard meldet "Access in invalid memory" und "Attempt to acces 4 bytes in 0x00000008". Egal ob Debugger Fehlermeldung und Code Guard, es taucht immer die gleiche Adresse "Read of 0x00000008" auf.
Nach einem Klick auf eine ListBox hole ich mir IP+Port aus der Zeile
void __fastcall TForm1::ListBox1Click(TObject *Sender) { char buf[20]; String data = "\\status\\"; int Size,lenght; String ip,iptemp = "",porttemp=""; player->Clear(); for(int i = 0; i < Form1->ListBox1->Items->Count; i++) { if(Form1->ListBox1->Selected[i]) { ip = Form1->ListBox1->Items->Strings[i]; for (int z = 1; z <= ip.Length(); z++) { if (ip[z] != ':') { iptemp = iptemp + ip[z]; } else { z++; for(int a = z;a <= ip.Length();a++) { porttemp = porttemp + ip[a]; } z = ip.Length(); } } Form1->UDPStatus1->RemoteHost = iptemp; Form1->UDPStatus1->RemotePort = StrToInt(porttemp); Form1->UDPStatus1->LocalPort = StrToInt(porttemp); strcpy(buf,data.c_str()); Size = sizeof(buf); lenght = strlen(buf); Form1->UDPStatus1->SendBuffer(buf,Size,lenght); } } }Dieses Ereignis wird ausgelöst wenn das UDP Socket die Daten vom Server empfängt
void __fastcall TForm1::UDPStatus1DataReceived(TComponent *Sender, int NumberBytes, AnsiString FromIP, int Port) { if (NumberBytes>-1 && NumberBytes<5000) { char buf[5000]; int lenght,e; String data,temp = ""; bool value = false; int rownumber = -1; Form1->UDPStatus1->ReadBuffer(buf,5000,lenght); data = buf; for (int r = 1;r <= strlen(data.c_str()) ;r++) { if(data[r] != '\\') { temp = temp + data[r]; //Zusammensetzen jeder Zeile } else { if (temp != "") { if(temp != "queryid") { if(temp.AnsiPos("final") == 1) { value = true; } else { player->Append(temp.c_str()); //Hinzufügen zu Player String Liste temp = ""; } } } } } //------------------------------------------------------- if(value == true) //Wenn die Liste fertig empfangen wurde { ListView1->Clear(); //säubern aller alten Einträge for (e = 0; e < player->Count; e++) //Durch Stringliste iterieren { if(player->Strings[e].AnsiPos("deaths_") == 1) //Neuen Spieler in Liste erkennen und ID berechnen { rownumber++; ListView1->Items->Add(); ListView1->Items->Item[rownumber]->Caption = rownumber + 1; ListView1->Items->Item[rownumber]->SubItems->Add(""); ListView1->Items->Item[rownumber]->SubItems->Add(""); ListView1->Items->Item[rownumber]->SubItems->Add(""); ListView1->Items->Item[rownumber]->SubItems->Add(""); ListView1->Items->Item[rownumber]->SubItems->Add(""); ListView1->Items->Item[rownumber]->SubItems->Add(""); ListView1->Items->Item[rownumber]->SubItems->Add(""); ListView1->Items->Item[rownumber]->SubItems->Strings[3] = player->Strings[e + 1]; //Death } if(player->Strings[e].AnsiPos("playername_") == 1 && ListView1->Items->Item[rownumber]->SubItems->Count <= 7) ListView1->Items->Item[rownumber]->SubItems->Strings[0] = player->Strings[e + 1]; //Name if(player->Strings[e].AnsiPos("score_") == 1 && ListView1->Items->Item[rownumber]->SubItems->Count <= 7) ListView1->Items->Item[rownumber]->SubItems->Strings[1] = player->Strings[e + 1]; //Score if(player->Strings[e].AnsiPos("kills_") == 1 && ListView1->Items->Item[rownumber]->SubItems->Count <= 7) ListView1->Items->Item[rownumber]->SubItems->Strings[2] = player->Strings[e + 1]; //Kills if (player->Strings[e].AnsiPos("ping_") == 1 && ListView1->Items->Item[rownumber]->SubItems->Count <= 7) ListView1->Items->Item[rownumber]->SubItems->Strings[4] = player->Strings[e + 1]; //Ping if (player->Strings[e].AnsiPos("team_") == 1 && ListView1->Items->Item[rownumber]->SubItems->Count <= 7) ListView1->Items->Item[rownumber]->SubItems->Strings[5] = player->Strings[e + 1]; //Team if(player->Strings[e].AnsiPos("keyhash_") == 1 && ListView1->Items->Item[rownumber]->SubItems->Count <= 7) ListView1->Items->Item[rownumber]->SubItems->Strings[6] = player->Strings[e + 1]; //Hashkey } //------------------------------------------------------ value = false; Form1->Memo1->Clear(); Form1->Memo1->Lines->AddStrings(player); } } }Wie gesagt klappt es bei einer Reihe von Server und bei manchen nicht.
Der Server sendet im folgendem Format:\deaths_0\3\keyhash_0\ca2b68e180ce9d4e49910ca92a674626\kills_0\12\ping_0\43......ich hab echt keine Ahnung warum es Access Fehler gibt. Bitte helft mir damit ich Nachts wieder schlafen kann

-
Joe_M. schrieb:
Von was wird die AccessViolation den geworfen?
Hi,
ich schätze mal, Joe_M. meinte damit: In welcher Zeile tritt die AccessViolation auf? (Auf welcher Zeile steht der Debugger nach dem Stoppen?)MfG
Alexander Sulfrian
-
Ab folgender Zeile:
if(player->Strings[e].AnsiPos("kills_") == 1 && ListView1->Items->Item[rownumber]->SubItems->Count <= 7) ListView1->Items->Item[rownumber]->SubItems->Strings[2] = player->Strings[e + 1];Was ich merkwürdig finde ist, wenn ich player->Clear() im OnClick Ereignis weglasse das dann alles fehlerfrei läuft. Nur die Stringliste wird dann gigantisch groß. hab echt keinen Plan was das alles soll, wenn der Code so daneben wäre würde er mir doch nicht 100 Server fehlerfrei auswerten. Sporatisch steigt er bei dem ein oder anderen Server mit einer Access violation aus

-
Mal ganz blöd gefragt:
if(player->Strings[e].AnsiPos("playername_") == 1 && ListView1->Items->Item[rownumber]->SubItems->Count <= 7) ListView1->Items->Item[rownumber]->SubItems->Strings[0] = player->Strings[e + 1]; //NameWie kannst du dir sicher sein, dass in der letzten Zeile e+1 in player Existiert? Schließlich leerst du ja vorher (oder sonst wann). (Wahrscheinlich Blödsinn. Aber vielleicht habe ich ja Glück und Recht. ;))
-
sobald AnsiPos("playername_") in der Stringliste vorkommt müsste logischerweiße ja auch der Name folgen,also [e + 1]
-
"sollte". Egal. Tut es das auch?! (Sorry, bei dem Chaos finde ich die richtige Exceptionmeldung nicht mehr...)
Wenn die letzte Zeile von player playername_, score_, kill_, etc. enthält, kracht es auf jeden Fall.
-
Du hast auf jeden Fall recht, aber warum bekomme ich dann keinen Index out of bound Error ? oder hab ich da was falsch verstanden ?
-
if(player->Strings[e].AnsiPos("playername_") == 1 && e + 1 <= player->Count) ListView1->Items->Item[rownumber]->SubItems->Strings[0] = player->Strings[e + 1]; //Namehilft da auch nicht

-
Ich glaube, (e+1) muss KLEINER als Count() sein...
Ich dachte, dein Problem WAR ein OutOfBoundsError...
War aber wohl eine AV...Ausserdem fängst du nicht ab: Wenn warum auch immer "_deaths" einmal ausfällt, greifst du auf SubItems zu, die es nicht gibt, oder? //Edit: Ach so, fängst du ja ab. //Edit2: Nö, doch nicht. "<=7"?! Was soll das denn? Hast du Angst, du hast mehr als 7 Subitems?
-
Das stimmt schon -hatte mich mit dem Index geirrt, bringt aber auch nichts. Erst hatte ich nur "out of bound" errors.Sie treten jetzt nicht mehr auf, nur noch Access violation errors. Das death ausfallen kann habe ich soeben auch gemerkt. entweder ist bei der Serverprogrammierung bei Battlefield 1942 was schief gelaufen oder es liegt am UDP Protokoll das manchmal nicht alles ankommt. Aber das UDP so dermassen anfällig ist kann ich irgendwie nicht glauben weil ich schon so viel mit udp sockets gemacht habe und nie mit einer Fehlerhaften übertragung zu kämpfen hatte. Bei dem Battlefield servern sieht das irgendwie anders aus, die senden stellenweiße so einen müll wie z.b 3 mal den gleichen user oder hier und da fehlt was. Habe mir sogar schon ein dummy Programm gebastelt was einfach stur die Daten mit Append in ne MemoBox schreibt um wirklich zu überprüfen ob die fehlenden Daten nicht wegen meiner Programmierung aufgetreten sind, aber auch das ergab das der BF Server stellenweiße totaler mist sendet. Aber wie machen das die Profis von All Seeing Eye oder Gamespy ? Ich verwende ja auch das Gamespy Protokoll für die Kommunikation mit den Gameservern und dem GameSpyMaster Server um aktuelle Serverlisten abzurufen. Die müssen ja auch mit dem Arbeiten was der Server übermittelt.
Echt mal Bahnhof
