GG na TEasyGG, aplikacja wielookienkowa i kosmetyka-problem

0

Witam! Moja zabawa z delphi trwa +/- rok, tworze gg na podstawie komponentu TEasyGG, wszystko szlo w miare sprawnie tylko moim najwiekszym problemem sa okna rozmowy... Nie chce zeby wygladalo to tak ze w glownym oknie gg pisze sie z ludzmi tylko zeby bylo jak w prawdziwym komunikatorze ze kazdy ma swoje okno rozmowy tworzone dynamicznie. Wszystko fajnie dziala do pewnego momentu...

Tworzac 1 okno glowne typie fsNormal i drugie dostepne tez fsNormal dziala, tylko jak mam identyfikowac okna jak bedzie ich wiecej niz 1? jak mam wykonywac operacje na wyspecjalizowanym oknie przez np. tytul?
Szukalem odpowiedzi na to pytanie bardzo dlugo i przeszlem do opcji łatwiejszej czyli mdiForm i dostepna forma mdiChild... Tu juz wiem co i jak ale z drugiej strony nie chce zeby mi okienka rozmow miescily sie w oknie glownym aplikacji ;/. To jest moj glowny problem ktory nie pozwala mi isc dalej w projekcie teraz czas na mniej wazny jednak znaczacy problem:

Lista kontaktow jest oparta na komponencie TTreeView, opisy sa wyswietlane jako podkatalog tzn
-aras
|----Tu opis
No i zle to wyglada bo nie moge ani podswietlic nazwy uzytkownika, ani zmienic czcionki dla podkatalogow, wyglada to bynajmniej dziwnie jak nazwa kontaktu i opis sa ta sama czcionka... pomijajac to ze opis w takim wypadku nie zmiesci sie na 100% w 1linijce.

Licze na jakies sugestie, podpowiedzi, albo w ogole na propozycje innych mozliwosci przechowywania kontaktow, apeluje jednak ze wazniejszy dla mnie jest problem nr 1 :). Dzieki z gory

0

co do listy userow to byl juz taki temat na tym forum i pamietam ze padlo wiele podpowiedzi. poszukaj.
jesli chodzi o dynamiczne okienka... tworzysz dynamicznie i trzymasz forme w jakiejs tablicy czy liscie. potem jesli przychodzi jakas wiadomosc to sprawdzasz ktora forma jest danemu uzytkownikowi przyporzadkowana i odwolujesz sie do niej "normalnie".

//P.S.

arasso12 napisał(a)

ani zmienic czcionki dla podkatalogow, wyglada to bynajmniej dziwnie jak nazwa kontaktu i opis sa ta sama czcionka...

http://sjp.pwn.pl/haslo.php?id=6119
:P

0

Poza tym formy (jak i wiekszosc obiektow) maja wlasciwosc Tag, ktora mozna dowolnie wykorzystywac. Mozesz tam przechowywac np jakies wlasne ID okna i go uzywac do identyfikacji okien.

0

Hmm no ok, ale jak to ma wygladac, zalozmy ze forma ktora tworze jest zadeklarowana jako Frm, to jak mam sprawdzac kolejno formy jak nie mam nawet mozliwosci sprawdzenia ile form jest stworzonych? Bo chyba nie ma czegos takiego w formach o typie normal
if Frm[nr okna albo jakikolwiek identyfikator].Caption='franek' then
blablabla

na pewno przyjrze sie temu blizej ale tymczasem spadam na silownie, dzieki za zainteresowanie :)

0

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

0

Trzymaj formy w dynamicznej tablicy

var
    Formy : array of TForm;
.........


    setlength( Formy, 10 );

    Formy[0] := TForm.Create(self);

    Formy[0].Parent := Form1;
    Formy[0].FormStyle := fsnormal;
   // Formy[0].Show;

    Formy[1] := TForm.Create(self);
    .... itd.

// Przy usuwaniu formy
    Formy[0].Free;
0

Można i w dynamicznej tablicy, ale do tego celu lepsza będzie TList
trzymająca wskaźniki albo TObjectList, lecz wteyd trzeba dodać do
sekcji uses dodatkowy moduł - z tego co się orientuję - to contnrs.

0

Jak teraz sie zablokuje na czyms to zaniecham, bedzie to znak ze jeszcze za maly jestem. Dzieki za wielka pomoc! Pozdro

0

Witam ponownie, odkopuje temat zeby nie zakladac nowego. Mam problem z lista kontaktow.... Mam scrollboxa do ktorego dodaje dynamicznie tworzone panele z obrazkiem i 2 labelami - 1 to nick a drugi to opis jezeli jest. Wszystko ładnie pieknie tylko jak mam odnalezc panel ktory wywolal procedure ondblclick? Chce zrobic ze po 2x kliku otworzy sie okno rozmowy no ale potrzebuje jakiegos identyfikatora z kim ta rozmowa bedzie, w nazwach penali to sie zawiera ale nijak nie dojde jak odnalezc nacisniety panel... Prosze o odp :) Pozdro!

0

Chodzi Tobie o coś takiego jak poniżej?

procedure TForm1.Panel1DblClick(Sender: TObject);
begin
  ShowMessage(TPanel(Sender).Name);
end;

Bo rozumiem, że do dynamicznie tworzonych paneli masz przypisane
zdarzenie OnDblClick. Także Obiekt który wywołał kliknięcie będzie w
zmiennej Sender. Można później na nią rzutować tak, jak pokazałem.
Ewentualnie jak potrzeba na zwroconą nazwę rzutuj FindComponent.

0

Oj glupi jestem glupi... dzieki wielkie :>. Tak przy okacji ma ktos jakis pomysl jak sortowac ta liste kontaktu? Aktualnie robie to tak:
Sortuje alfabetycznie nazwy znajomych
sprawdzam kolejno czy ktorys ma status dostepny albo zw jak tak to przenosze go na gore(sortowanie w memo)
pobieram kolejne linijki memo i dodaje panele do scrollboxa z nazwa kontaktu

Operacja trwa dluuuugo bo z 5s przy okolo 100 kontaktach... Do tego dojdzie jeszcze sprawdzanie co jakies 3s czy nikt nie zmienil opisu, statusu, to robie w ten sposob ze sortuje od nowa uzytkownikow jak wyzej, zwalniam wszystkie panele i dodaje je od nowa. Jest to nieciekawe rozwiazanie bo stanowczo za dlugo trwa ;(

0

Przechowuj dane o kontaktach w postaci klasy - typu TObject.
Później dodawaj je do wyczyszczonej listy typu TList no i to tę
listę dopiero sortuj. Przykłady jak sortować TList są w gogole.

0

Ja aż stu kontaktow nie mam, ale sortowanie odbywa się raczej płynnie.
Bez sensu jest jakieś kombinacje z Memo. Używanie ukrytego Memo do
przechowywania tekstu zamiast TStringList to mega nieporozumienie co
zdarzać się może tylko totalnym amatorom. Sam taki błąd kiedyś jak w
programowaniu zaczynałem, używałem ukrytych Listboxów, ale teraz to
jak mogę każdego przed tym przestrzegam. A co do sorotowania to ja w
swoim programie użyłem ListView, podczepionego do TGGList i sortuje z
użyciem AlphaSort tylko tego ListView, ktory ma dodane kontakty. Jest
to jeden możliwy sposób. Inny to przechowywać kontakty jako klasę co
jesr typu TObject i dodawać do obiektu typu TList. Następnie dopiero w
odpowiedni sposób posortować tę TList. I przykłady znajdziesz w google.

procedure TMainForm.ContactsLVCompare(Sender : TObject; Item1,
  Item2 : TListItem; Data : Integer; var Compare : Integer);
const
  StatusCol = 2;
var
  StatusNum1, StatusNum2 : integer;
begin
  StatusNum1 := StrToInt(Item1.SubItems[StatusCol]);
  StatusNum2 := StrToInt(Item2.SubItems[StatusCol]);
  if StatusNum1 > StatusNum2 then
    Compare := 1
  else if StatusNum1 < StatusNum2 then
    Compare := -1
  else
    Compare := CompareText(Item1.Caption, Item2.Caption);
end;
0

Nie zauwazylem ze jest druga strona, sortowanie juz zmienilem. Po imporcie kontaktow sa one sortowane alfabetycznie przez quick sort i dodawane do tablicy, pozniej elementy tablicy sa przepisane do drugiej logalnej tablicy w procedurze ktora sortuje pod wzgledem statusu. Czyli sortowanie alfabetyczne robie tylko raz, a sortowania kontaktow pod wzgledem statusu chyba nie da sie zrobic inaczej jak sortowaniem babelkowym, teraz operacja trwa 1s +/-. Problem mam ze scrollboxem oto kod

panel:=Tpanel(ScrollBOx1.FindComponent('Panel'+inttostr(numergiegie)));
panel.Free;
panel:=Tpanel.Create(ScrollBox1);
//panel.Left:=10;
//Panel.Top:=5;
Panel.Align:=alTop;
panel.AutoSize:=true;
panel.Parent:=ScrollBox1;
Panel.Visible:=true;
Panel.Name:='Panel'+inttostr(numergiegie);
Panel.Tag:=numergiegie;
Panel.Caption:='';
panel.OnDblClick:=panelclick;

W ten sposob dodaje panele na scrollboxa, tablica z ktorej dodawane sa panele ma na poczatku nazwy dostepnych uzytkownikow czyli zeby byli na poczatku listy teoretycznie wystarczy ustawic align na alTop ale... tylko pierwszy kontakt z dostepnych jest na samej gorze a pod spodem niedostepni i na samym dole dostepni... To 1 problem, teraz pytanie. Czy zwalnianie wszystkich paneli i tworzenie ich od nowa to jedyny sposob na aktualizacje listy kontaktow? Kminilem spory czas jak aktualizowac juz istniejace ale jak ktos z niedostepnych zmieni status na dostepny to bede musial go przerzucic na poczatek i posortowac alfabetycznie panele co stanowi jednak problem dla mnie. Dzieki za zainteresowanie, pozdro!!

EDIT: Problem ze zlym ustawieniem paneli rozwiazalem, mało elegancko ale rozwiazalem. Posortowalem tablice odwrotnie alfabetycznie czyli do z do a, pozniej przesunalem kontakty dostepne na sam dol, ustawilem align na alBottom i dziala jak nalezy.

0

Najprościej będzie użyć komponentu TGGList dostępnego w downloadzie na 4p,
a do niego podczepiasz LV, który sortujesz wedlug statusu, w razie jakby Tobie
nie odpowiadala ta wersja dostępna na 4p, możesz sprawdzić tę wersję, którą
lekko poprawiłem żeby ładniej wyświetlała kontakty. Link poniżej do tego mały
fragment kodu jak dodawać elementy do ListView'a. A ja TGGList oraz ListView
tworzyłem dynamicznie http://www.speedyshare.com/files/25016527/gglist.rar

// ...
function StateID(Status : TUserStatus) : Byte;
begin
  case Status of
    usAvailable : Result := 0; // Dostępny
    usBusy : Result := 1; // Zaraz wracam
    usNotAvailable : Result := 2; // Niedostępny
    usInvisible : Result := 3; //Niewidoczny
    usBlocked : Result := 4; //Zablokowany
  else
    Result := 1; // Niedostępny
  end;
end;

// dodawanie elementów do ListView...
          S := IntToStr(StateID(User.Status));
          UsrObj := TUserObject.Create;
          UsrObj.Name := User.Name;
          UsrObj.UID := User.UID;
          UsrObj.Group := [0];
          UsersList.Add(UsrObj);
          ContactsLV.AddItem(User.Name, User);
          ListItem := ContactsLV.Items[ContactsLV.Items.Count - 1];
          ListItem.SubItems.Add(IntToStr(User.UID));
          ListItem.SubItems.Add(User.Description);
          ListItem.SubItems.Add(S);
//...

Mam nadzieję, że coś to Tobie pomoże, bo jak się uprzesz przy jakiś tam
panelach zrobionych po swojemu, to je również możesz sortować w TList.

0

Zobacze jak to bedzie wygladalo, bo te panele jak na moje oko b. ladnie wygladaja. Tak czy siak dzieki za rady :)

0

Musze jeszcze raz zwrocic sie do Was o pomoc... GG dziala i wyglada ale nurtuje mnie ten scrollbox... dlaczego jak dodaje w petli panele z align altop to i tak zostaja na dole? Problem rozwiazalem jak pisalem wyzej, ale jak dodam pojedynczy kontakt to zostaje on na samej gorze bez wzgledu na status przez te kombinacje z sortowaniem odwrotnym itd... Wyglada na to ze jak dodaje w petli panele to nie ustawiaja sie jak nalezy a jak pojedynczo np buttonem to jest ok ;/. Licze na pomoc. Z gory dzieki :))

EDIT
Rozwiazalem to, ponownie dziwnym sposobem ale dziala :)

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