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;