Mniej siłowni, więcej Delphi to ogarniesz taki prosty w sumie temat ;) Ja rozwiązałem
tworzenie okienek rozmowy w swoim programie tak, jak Tobie pokazuje tutaj poniżej.
Najważniejsze stałe i zmienne - oczywiście wszystkie potrzebne obiekty są tworzone
w zdarzeniu OnCreate formatki głownej, a przy jej zamykaniu są one już zwalniane,
a i dodam, że wszystkie niestandardowe komponenty, są tu tworzone dynamicznie:
// ...
public
EGG : TEasyGG;
GGL : TGGList;
APass : String;
AUID : Cardinal;
AppPath : String;
WhichIcon : Byte;
UsersList : TList;
TrayIcon : TTrayIcon;
AllowClose : boolean;
NewMessageIcon : TIcon;
ContactsLV : TListView;
ChatWindowsList : TList;
CurrentUserName : String;
// ...
const
ChatForm_Name = 'ChatForm_';
// ..
Używam osobnej formatki TChatForm z okienkami do rozmowy.
Dwukrotne kliknięcie na nazwę użytkownika na TGGList 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;
Nadejście nowej 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;
Dwukrotne kliknięcie na ikonke w trayu przy nadejściu wiadomości:
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;</delphi>
Miganie ikonką na przemian koperta z ikoną statusu po nadejściu wiadomości:
procedure TMainForm.AppTimerTimer(Sender : TObject);
begin
if WhichIcon = 1 then
begin
WhichIcon := 2;
end
else
begin
WhichIcon := 1;
end;
case WhichIcon of
1 : UpdateAppControls(MainForm);
2 : TrayIcon.Icon := NewMessageIcon;
end;
TrayIcon.ToolTip := 'Wiadomość od: ' + TChatForm(ChatWindowsList[0]).Caption;
end;
Dla formalności procedura UpdateAppControls - StatusIL to TImageList
z ikonkami statusu, z którego korzysta TGGList, a dane userów pobiera
z ListView o nazwie ContactsLV. Źródła TGGList znajdziesz turaj na 4p:
procedure TMainForm.UpdateAppControls(Sender : TObject);
const
ConnectBtn_CaptionArray : array[boolean] of string = ('Połącz', 'Rozłącz');
var
CurrentIcon : TIcon;
begin
CurrentIcon := TIcon.Create;
StatusIL.GetIcon(StateID(EGG.Status), CurrentIcon);
TrayIcon.Icon := CurrentIcon;
CurrentIcon.Free;
Masowewysylaniewiadomosci.Enabled := EGG.Loggedin;
ConnectBtn.Caption := StringReplace(ConnectBtn_CaptionArray[EGG.LoggedIn], '&', '', [rfReplaceAll]);
end;
Mam nadzieję, że teraz wszystko będzie jasne. Można to pewnie rozwiązać i inaczej,
ale ja to rozwiązałem tak i jest ok. FlashTimer to Timer w oknie rozmowy, którego
zadaniem jest miganie belką okna kiedy przyjdzie nowa wiadomośc, a to okno nie
jest przywrócone na pierwszy plan. I wybaczcie ten przydługi post - nawet jak na
"moje standardy", ale skoro pytający nie ogarniał w miarę prostego tematu okien
dla swojego komunikatora to napisałem przykład żeby wszystko było jasne. No i
ja póki co zarzuciłem tworzenie tego komunikatora, korzystam z AQQ, bo jak tu
pewnie wszyscy wiemy - rozwijanie TEasyGG niestety póki co "się zatrzymało".