Kontaktliste á la ICQ: Dynamische Arrays bei Formen (Gesprächsfenstern) & ListItem (Kontakte)
-
Hallo zusammen!
Da ich einen Messenger programmiere, versuche ich seit Stunden eine Kontaktliste mit TListView hinzubekommen.Voraussetzungen sind:
- Anzahl der Kontakte unbekannt (varriert natürlich)
- Indexe der Kontakte ändern sich (durch Sortieren der Kontakte per Alphabet)
- Für jeden Kontakt darf sich nur 1 Gesprächsfenster öffnenIm Moment bin ich so weit:
Ich habe eine TListView und eine TEdit, mit der ich die Anzahl der Kontakte bestimme.Momentan bin ich so weit gekommen, aber das funktioniert noch nicht so, wie ich das möchte.
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key) { if(Key == VK_RETURN) { zahl = Edit1->Text.ToInt(); ILArray.Length = zahl; FormArray.Length = zahl; for(int i = 0; i < ILArray.Length; i++) { ILArray[i] = ListView1->Items->Add(); ILArray[i]->Caption = String("Kontakt") + i; } Edit1->Enabled = false; } }
DynamicArray<TForm*>FormArray; DynamicArray<TListItem*>ILArray; int zahl, formzaehler=0; ... void __fastcall TForm1::ListView1DblClick(TObject *Sender) { if(Form1->ListView1->Selected) { int index = Form1->ListView1->Selected->Index; String caption = Form1->ListView1->Items->Item[index]->Caption; formzaehler++; for(int z=0; z<formzaehler; z++) { if(FormArray[index]->Caption != caption) { FormArray[index] = new TForm(Form1); FormArray[index]->Caption = "Form: " + Form1->ListView1->Items->Item[index]->Caption; FormArray[index]->Name = caption; FormArray[index]->Show(); } else formzaehler--; } } }
Mit der for-Schleife und dem Integer "formzaehler" versuche ich, ähnlich wie bei einem Lotto-Programm, dass die erstellte Form als Namen den Namen des Kontakts (ListItem->Caption) annimmt und diesen dann mit neu hinzukommenden Formen zu vergleichen, damit für jeden Kontakt auch wirklich nur 1 Gesprächsfenster geöffnet werden kann.
Ich weiß einfach nicht, wie das zu machen ist..
Viele Grüße
Peter
-
du könntest einen umweg über ne Datenbank gehen oder mit files arbeiten, wo du reinschreibst welcher Kontakt bereits ein offenes Fenster hat.
Das müsstest du dann bei jedem Doppelklick auf einen Kontakt abfragen.Wäre eine Möglichkeit, die andere die mir einfällt, ist ein simples Array, wo du die Namen oder Kontakt-IDs reinschreibst sobald ein Fenster für einen Kontakt geöffnet wird.
Beim Schließen müsstest du natürlich das Array oder den Vector reorganisieren, damit da keine Lücken entstehen und das Array überläuft.
Die Größe des Arrays würde ich auf die Anzahl der Kontakte setzen.Hoffe, konnte dir damit helfen
-
Hi,
ich würde mir eine Klasse bauen Kontakt, die als Member das zugeordnete Form (das Gesprächsfenster) besitzt. Die Objekte dieser Klasse kannst Du dann meinetwegen in DynamicArray hosten. Im Konstruktor des Kontaktes dann diesen Member mit 0 initialisieren, wenn der Kontakt gewählt wird brauchst Du nur zu prüfen, ob der Member 0 ist. Dann entweder das Form konstruieren und dort verweisen oder das bestehende Form ( != 0) in den Vordergrund. Du kannst dann nach Herzenslust sortieren und brauchst nicht nach offenen Gesprächsfenstern suchen.
-
Hallo,
wie wäre es denn mit FindWindow die Existenz eines Fensters zu üerprüfen? Da jeder Kontakt nur einmal vorhanden sein wird und Kontaktnamen nicht doppelt vergeben werden können, sollte das Resultat von FindWindow eindeutig sein.
if (FindWindow(NULL, "Form1")) ShowMessage("existiert"); else ShowMessage("existiert nicht");
mfg, Micha
-
damit bekommste aber Probleme, wenn du doch doppelte Namen erlaubst.
Geht in ICQ ja auch. Ist halt immer die Frage, wie robust man das gegenüber Modifikationen machen möchte.
-
Hallo
Besser ist ein vollständige Trennung von GUI und internen Daten.
Das heißt du legst die ganzen Kontaktdaten erstmal in ein ein dynamisches Array von Elementen einer Kontaktklasse. Das erlaubt dir auch eine sinnvolle Datenkapselung.class Contact { Contact(AnsiString name) : m_name(name), m_chat(0) { } AnsiString m_name; TForm* m_chat; ... }; std::vector<Contact> contacts;
Diese Liste beinhaltet nun auch Zeiger zu den Chatfenstern, und zwar für jeden Benutzer auch nur maximal eins, egal ob doppelte Namen oder nicht.
Wenn kein Fenster da ist, ist der Zeiger 0. Dort wird also ein neues Fenster erstellt und dem Zeiger zugewiesen. Wenn der Zeiger nicht 0 ist, muß nur das vorhandene Fenster in den Vordergrund geholt werden. Wird ein Fenster geschlossen, muß es gelöscht werden und der Zeiger auf 0 gesetzt werden.Deine GUI-Ansicht der Kontakte kannst du nun ganz leicht anzeigen : Für jede Aktualisierung must du nur noch alle alten Einträge im ListView löschen, und danach durch die interne Liste gehen und in der gewünschten Reihenfolge alle Einträge in das ListView eintragen.
bis bald
akari
-
Erstmal danke für eure Antworten.
Mit Datenbanken habe ich noch nie gearbeitet, obwohl's langsam mal Zeit wird, sich da ran zu machen..Puh, dann versuch ich mal, wie ich akaris Vorschlag umsetzen kann...
Danke nochmal und bis später!Viele Grüße
Peter
-
akaris Vorschlag scheint mir der bisher robusteste zu sein.
Musst halt da immer nur aufpassen, was du für einen zeiger übergisbt, nicht dass du dir deine main-Form aus versehen zerschießt, dann wäre alles weg
Und Datenbanken sind generell ein interessantes Thema, aber auch nicht ganz einfach beim ersten Mal
Wenn man mal durchgestiegen ist gehts ganz einfach weiter