Felder in ListView Komponente



  • Meinst du folgendes:

    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->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
    

    Kann man das so vertreten ? Bin mir wirklich unsicher da ich noch nie zuvor mit einer ListView gearbeitet habe. Da ich auf der Arbeit bin und nur über http 8080
    rauskomme kann ich es leider noch nicht Testen. Zuvor hatte ich immer ein Index Out of bound gehabt und danach woch ich das im Griff hatte ne direkte Zugriffsschutzverletzung. Ich hoffe das ihr mir die Sache mit der ListView näher bringen könnt

    Das Programm könnt ihr hier als jpeg sehen:
    http://www.fragthe.net/download.php?id=17327

    Die Liste die mir der Server sendet hat folgendes Format:

    ------------------------------------Player 1
    deaths_0
    3
    keyhash_0
    ca2b68e180ce9d4e49910ca92a674626
    kills_0
    12
    ping_0
    43
    playername_0
    [CNB]rokko
    score_0
    16
    team_0
    1
    ------------------------------------Player 2
    deaths_1
    16
    keyhash_1
    aa85154aa3ed0f8b97d61416c1963477
    kills_1
    7
    ping_1
    38
    playername_1
    Hoze
    score_1
    5
    team_1
    2
    ------------------------

    Gruß David



  • Habe gerade rausgefunden das es nur Funktioniert wenn ich im Objekt Inspektor unter Items->TListItems items + eine Anzahl von Substrings statisch anlege. Das bedeutet ich kann nur in Substrings schreiben die auch vorher definiert wurden. Wie kann ich 7 Substrings pro ListViewEintrag zur laufzeit allokieren ??
    Sobald eine neue Zeile beginnt reserviere ich schon mal 7 Substrings- ungefähr nach dem Prinzip

    Ich hoffe der Rest meines oben beschriebenen Codes ist richtig. Ich tappe momentan noch voll im Dunkeln wie ich mit der ListView Komponente am besten umgehe.
    Ich bitte höflichst um eure Hilfe weil ich momentan keinen Plan habe wo ich am besten weitermachen soll. Vielen Dank !!!



  • 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]);  //Name
    

    Das 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 aufgeschmissen

    Was 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]; //Score
    

    EDIT: 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];  //Name
    

    Wie 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];  //Name
    

    hilft da auch nicht 😞


Anmelden zum Antworten