Dynamiczne okienka

0

Cześć piszę sobie prostego klienta GG i mam problem z dynamicznymi okienkami to znaczy mam taki kod:

var
Nr: integer;
begin
if GGlist1.Selected[GGlist1.ItemIndex]=false then Exit;

if EGG.Loggedin=false then Exit;

SetLength(F,20);

for Nr := 0 to Screen.FormCount -1 do
begin
if F[Nr].Caption='Rozmowa z ' + ListView1.Items.Item[Gglist1.ItemIndex].SubItems.Strings[0] then
begin
if F[Nr].Showing=true then begin
F[Nr].BringToFront;
exit;
end else begin
F[Nr].Show;
F[Nr].BringToFront;
exit;
end;
end;
end;

NrOkna:=NrOkna+1;
F[NrOkna] := Trozmowa.Create(Self);
F[NrOkna].Caption:='Rozmowa z ' +  ListView1.Items.Item[Gglist1.ItemIndex].SubItems.Strings[0];
F[NrOkna].numer:=Strtoint(ListView1.Items.Item[Gglist1.ItemIndex].Caption);
F[NrOkna].nazwa:=ListView1.Items.Item[Gglist1.ItemIndex].SubItems.Strings[0];
F[NrOkna].Show;

end;

I teraz gdy dostaję wiadomość od użytkownika to jak wstawić ją do odpowiedniego okna?
próbowałem tak:

F[NrOkna].memo1.lines.add();

Ale to nie jest dobry pomysł bo wtedy wstawia tą wiadomość nie w to okno co trzeba.
próbowałem też tak:

for Nr := 0 to Screen.FormCount -1 do
begin
if F[Nr].Caption='Rozmowa z ' + Egg.Users.Items[Egg.Users.IndexOfUID(UID)].Name then
begin
F[Nr].memo1.lines.add();

Ale wtedy gdy przychodzi wiadomośc wyskakuje Access violation... Czy ktoś mi pomoże i powie jak to zrobić żeby wiadomość była wstawiana w dobrym oknie?

0

Tez napisałem sobie prostego klienta GG przy użyciu TEasyGG i tworzenie osobnych okien
rozmowy rozwiązałem tak jak poniżej. Kontakty przechowuje w ListView, który jest ukryty,
bo korzysta z niego komponent typu TGGList, którego źródło nieco przerobiłem, a którego
kod w oryginale można znaleźć na tym forum. Kontakty do ListView dodaję w taki sposób,
jak pokazałem poniżej na przykładzie procedury do importowania listy kontaktów, zaś też
użyta UsersList typu TList i typ obiektowy UsrObj możesz zignorować wykorzystałem je w
celu zapisywania do - spakowanego ZLibem, pliku kontaktów z litsy czyli Name oraz UID:

procedure TMainForm.EGGImportList(Sender : TObject);
var
  S : String;
  I : Integer;
  User : TUser;
  ListItem : TListItem;
begin
  UsersList.Clear;
  ContactsLV.Items.Clear;
  for I := 0 to EGG.Users.Count - 1 do
  begin
    User := EGG.Users.Items[I];
    UsrObj := TUserObject.Create;
    UsrObj.Name := User.Name;
    UsrObj.UID := User.UID;
    UsrObj.Group := [0];
    UsersList.Add(UsrObj);
    S := IntToStr(StateID(User.Status));
    ContactsLV.AddItem(User.Name, User);
    ListItem := ContactsLV.Items[ContactsLV.Items.Count - 1];
    ListItem.Caption := User.Name;
    ListItem.SubItems.Add(IntToStr(User.UID));
    ListItem.SubItems.Add(User.Description);
    ListItem.SubItems.Add(S);
  end;
  ContactsLV.AlphaSort;
  GGL.RefreshItems;
end;

Zaś tworzenie nowych okien rozmowy po podwójnym kliknięciu na osobę, a także sposób
dynamicznego tworzenia formatki w przypadku gdy przyjdzie wiadomość od jakiejś osoby,
z która nie mam otwartego jeszcze okna rozmowy - pokazany został poniżej. Jeżeli już z
danym numerem istnieje okno rozmowy to jest do niego wpisywana treść wiadomość. A i
na TChatForm znajduje się komponent MsgRecvMemo, do którego przychodzi wiadomość,
natomiast FlashTimer ktory na niej się znajduje służy do migania belką paska zadań danej
formatki. Jest w jej kodzie także własnośc ActiveUID w sekcji public, którą ustaiwam, po
odebraniu wiadomości lub przy klikaniu na kontakt. Zmienna ta umożliwia mi wysyłanie z
formatki do tego numeru wiadomości wpisanym w dolnym Memo. Natomiast użyty też w
kodzie ChatWindowsList to obiekt typu TList, tworzony raz w OnCreate formatki głownej
i niszczony w OnCloseQuery, zaś AppTimer jest użyty w celu migania ikoną obok zegara i
jak widzisz całość nie jest specjalnie skomplikowana, powinno się Tobie coś w tym rodzaju
zastosować u siebie. Obiekt typu TList przechowuje wskaźniki do innych obiektów, ale jak
potrzeba to przez rzututowanie można przechowywać booleany lub liczby dowolnego typu.

// ...
const
  ChatForm_Name = 'ChatForm_';
  Format_TimeStamp = '[HH:NN:SS]';
// ...
// Kliknięcie na utworzony dynamicznie ListBox z kontaktami:
procedure TMainForm.GGL_DblClick(Sender : TObject);
var
  AnUser : String;
  AnUID : Cardinal;
  ChatWindow : TChatForm;
begin
  if ContactsLV.SelCount = 1 then
  begin
    AnUser := TUser(ContactsLV.Items.Item[ContactsLV.ItemIndex].Data).Name;
    AnUID := TUser(ContactsLV.Items.Item[ContactsLV.ItemIndex].Data).UID;
    if AnUID = EGG.UID then
    begin
      Exit;
    end;
    if EGG.Loggedin = False then
    begin
      MessageBox(Application.Handle, 'Nie jesteś zalogowany na GG!',
        PChar(Application.Title), MB_OK + MB_ICONWARNING);
      Exit;
    end;
    ChatWindow := TChatForm(Self.FindComponent(ChatForm_Name + IntToStr(AnUID)));
    if ChatWindow = nil then
    begin
      ChatWindow := TChatForm.Create(Self);
      ChatWindow.ActiveUID := AnUID;
      ChatWindow.Name := ChatForm_Name + IntToStr(AnUID);
    end;
    ChatWindow.Caption := AnUser;
    ChatWindow.Show;
    ShowWindow(ChatWindow.Handle, SW_RESTORE);
  end;
end;
// ...
// Obsluga przychodzących wiadomości:
procedure TMainForm.ReceiveMsg(Sender : TObject; UID : Cardinal; HTMLMessage,
  PlainMessage, Attributes : String; Time : TDateTime;
  Conference : array of Cardinal);
var
  I : Integer;
  ChatWindow : TChatForm;
  S, TheTime, FromWho : String;
begin
  FromWho := '';
  Thetime := FormatDateTime(Format_TimeStamp, Now);
  for I := 0 to ContactsLV.Items.Count - 1 do
  begin
    if UID = TUser(ContactsLV.Items.Item[I].Data).UID then
    begin
      FromWho := TUser(ContactsLV.Items.Item[I].Data).Name;
      Break;
    end;
  end;
  if FromWho = '' then
  begin
    FromWho := IntToStr(UID);
  end;
  S := Format('%s <%s> %s', [TheTime, FromWho, PlainMessage]);
  ChatWindow := TChatForm(Self.FindComponent(ChatForm_Name + IntToStr(UID)));
  if ChatWindow <> nil then
  begin
    if GetForeGroundWIndow <> ChatWindow.Handle then
    begin
      ChatWindow.WindowState := wsMinimized;
    end;
  end
  else
  begin
    ChatWindow := TChatForm.Create(Self);
    ChatWindow.ActiveUID := UID;
    ChatWindow.Name := ChatForm_Name + IntToStr(UID);
    ChatWindow.WindowState := wsMinimized;
  end;
  if GetForeGroundWIndow <> ChatWindow.Handle then
  begin
    ChatWindow.FlashTimer.Enabled := True;
  end;
  ChatWindow.Caption := FromWho;
  if ChatWindowsList.IndexOf(ChatWindow) = -1 then
  begin
    ChatWindowsList.Add(ChatWindow);
    AppTimer.Enabled := not ChatWindow.Showing;
  end;
  TMemo(ChatWindow.FindComponent(ChatForm.MsgRecvMemo.Name)).Lines.Add(S);
end;
// ...
// Obsluga podwójnego kliknięcia na ikonę obok zegarka:
procedure TMainForm.TrayIconDblClick(Sender : TObject);
begin
  MainForm.Visible := True;
  if AppTimer.Enabled = True then
  begin
    TChatForm(ChatWindowsList[0]).Show;
    ShowWindow(TChatForm(ChatWindowsList[0]).Handle, SW_RESTORE);
    ChatWindowsList.Delete(0);
    MainForm.Visible := True;
    if ChatWindowsList.Count = 0 then
    begin
      AppTimer.Enabled := False;
      TrayIcon.Icon := Application.Icon;
      SetTrayIconToolTip;
    end;
  end
  else
  begin
    SetForeGroundWindow(MainForm.Handle);
  end;
end;

1 użytkowników online, w tym zalogowanych: 0, gości: 1