5. díl - Přístup k okýnkům, Mutex, fce messengeru - ISIM

C# .NET Pro pokročilé Instant Messenger Přístup k okýnkům, Mutex, fce messengeru - ISIM

Global.cs

Tady to bude trošku rozsáhlejší, budou zde vnořené třídy, proměnné a tak dál. Možná doporučuji si to pak roztřídit do více souborů.

Enum dostupnosti může být následující. Přiřazením hodnoty čísla, pak lze jednoduše přetypovat na integer a tuto hodnotu získat. Zde to využívám jako určení priority při řazení.

public enum Availability { Online = 1, Away = 2, DND = 3, Invisible = 4, Blocked = 5, Offline = 6 };

První vnořená třída obsahující instance okýnek:

public static class OpenForms
{
        public static MainForm mainForm;
        public static ChatForm chatForm;
}

Další vnořená třída je pro Mutex - odesílání signálu. Popsáno zde: http://www.itnetwork.cz/…gle-instance

public static class SingleInstance
{
        public const int HWND_BROADCAST = 0xffff;
        public static int WM_SHOWME;
        [DllImport("user32")]
        public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
        [DllImport("user32")]
        public static extern int RegisterWindowMessage(string message);

        static SingleInstance()
        {
                WM_SHOWME = RegisterWindowMessage("ISIM_SHOW_FORM");
        }

        public static void ShowForm()
        {
                SingleInstance.PostMessage(
                        (IntPtr)SingleInstance.HWND_BROADCAST,
                        SingleInstance.WM_SHOWME,
                        IntPtr.Zero,
                        IntPtr.Zero);
        }
}

Teď bude velká vnořená třída s funkcemi messengeru.

public static class ISIMFunctions
{

Invoke -> zajímavá a užitečná metůdka, využívající se při multi threadingu -> zásahu do jiného threadu (okýnka) z jinýho threadu (okýnka). Přivlastním si ho a pracuji s ním. Zde je proto, abych zajistil spuštění okýnka chatu na hlavním vlákně. Jinak by se mohlo stát, že se metoda OpenChatForm zavolá z jiného threadu a okýnko by jen probliklo - jakmile by thread skončil, okýnko by se zavřelo. Existuje také asynchronní metoda BeginInvoke - což zjednodušeně znamená, že se požadavek pošle a jede se dál, on se časem vykoná na dalším vlákně, takže se na nic nečeká.

/// <summary>
/// Přidání tabu případné otevření chat okýnka
/// </summary>
/// <param name="contact"></param>
/// <param name="selectTab"></param>
public static void OpenChatForm(ISIMContact contact, bool selectTab = false)
{
        if (Global.OpenForms.chatForm == null)
        {
                // Abych zajistil otevření na hlavním threadu
                Global.OpenForms.mainForm.Invoke(new MethodInvoker(() =>
                {
                        Global.OpenForms.chatForm = new ChatForm(contact);
                        Global.OpenForms.chatForm.Show();
                        Global.OpenForms.chatForm.Activate();
                }));
        }
        else
        {
                Global.OpenForms.chatForm.BeginInvoke(new MethodInvoker(() =>
                {
                        Global.OpenForms.chatForm.chatTabs.AddTab(contact, selectTab);
                }));
        }
}

() -> je tzv. lambda znak, používá se pro definici jednořádkové metody, kterou lze použít vnořeně v metodě. Používá se místo delegátu delegate() kdůli kratšímu zápisu.

object as MůjObject je způsob takového C# like přetypování objektu. Vlastně se zeptá, zda je objekt toho typu -> object is MůjObject ? (MůjObject)object : (MůjObject)null. Ovšem nelze to použít například ve switch, tuším že u enum a nějakých dalších případech.

/// <summary>
/// Přidání zprávy do chat okýnka dané konverzace a případné otevření okýnka
/// </summary>
/// <param name="contact"></param>
/// <param name="message"></param>
/// <param name="time"></param>
public static void AddChatMessage(ISIMContact contact, string message, DateTime time, string from)
{
        OpenChatForm(contact);

        Global.OpenForms.chatForm.BeginInvoke(new MethodInvoker(() =>
        {
                (Global.OpenForms.chatForm.chatTabs.TabPages[contact.id] as ChatTabPage).AddChatMessage(contact, message, time, from);

                if (Global.OpenForms.chatForm.chatTabs.TabPages[contact.id] != Global.OpenForms.chatForm.chatTabs.SelectedTab)
                {
                        contact.unreadedMessage = true;

                        Global.OpenForms.chatForm.Invoke(new MethodInvoker(() => { Global.OpenForms.chatForm.Refresh(); }));
                        Global.OpenForms.mainForm.Invoke(new MethodInvoker(() => { Global.OpenForms.mainForm.Refresh(); }));
                }
        }));
}

Pro odesílání zpráv se udělá jedna univerzální metoda, která rozpozná, ze kterého protokolu jde požadavek a podle toho se zařídí.

/// <summary>
/// Odeslání zprávy kontaktu
/// </summary>
/// <param name="contact"></param>
/// <param name="conversation"></param>
/// <param name="message"></param>
public static void SendChatMessage(ISIMContact contact, object conversation, string message)
{
        if (conversation is SkypeContact.ContactObject)
        {
                try
                {
                        (conversation as SkypeContact.ContactObject).conversation.PostText(message);
                }
                catch (Exception ex)
                {
                        AddChatMessage(contact, "Nepodařilo se odeslat zprávu", DateTime.Now, "ISIM");
                        Console.WriteLine("msg send failed" + ex.Message);
                }
        }

        // nejprve se zkontroluje dle nějakého identifikátoru které knihovně daný objekt náleží
        if (conversation is XmppContact.ContactObject)
        {
                Global.OpenForms.mainForm.Invoke(new MethodInvoker(() =>
                {
                        // nastala chyba - odpojeno od serveru
                        if (((conversation as XmppContact.ContactObject).xmppClient == null) || ((conversation as XmppContact.ContactObject).xmppClient.XmppConnectionState != agsXMPP.XmppConnectionState.SessionStarted))
                                Global.ISIMFunctions.AddChatMessage(contact, "Chyba při odesílání zprávy", DateTime.Now, "ISIM");

                        // lze odeslat jen asi 1000 znaků dlouho zprávu, pokud je delší splitne se na části
                        foreach (string msg in message.SplitString(900))
                                (conversation as XmppContact.ContactObject).xmppClient.Send(new agsXMPP.protocol.client.Message(new agsXMPP.Jid(contact.id), MessageType.chat, msg));
                }));
        }

        if (conversation is IcqContact.ContactObject)
        {
                // blbě kódování v ICQ
                message = message.RemoveDiacritics();
                (conversation as IcqContact.ContactObject).session.Messaging.Send(new IcqSharp.Base.Message(new IcqSharp.Base.Contact(contact.id), IcqSharp.Base.MessageType.Outgoing, message));
        }

        Global.ISIMFunctions.AddChatMessage(contact, message, DateTime.Now, myNick);
}

Při přidání kontaktu nebo editaci jeho dostupnosti se zavolá metoda Sort sesortí kontakty dle našeho komparátoru a i překreslí ListView což mě celkem štvalo, bže to problikává. Proto je dobré používat BeginUpdate() a EndUpdate() pokud děláme více operací, jako například při hromadném přidávání kontaktů, zablokuje to překreslování udělám si co chci a pak to překreslím naráz.

        public static void AddContact(ISIMContact contact)
        {
                Global.OpenForms.mainForm.BeginInvoke(new MethodInvoker(() =>
                {
                        if (!Global.OpenForms.mainForm.contactListView.Items.ContainsKey(contact.id))
                        {
                                Global.OpenForms.mainForm.contactListView.Items.Add(new ContactListViewItem(contact));

                                if (contact.availability == Availability.Offline)
                                        Global.OpenForms.mainForm.contactListView.Items[contact.id].Group = Global.OpenForms.mainForm.contactListView.Groups["offlineListViewGroup"];
                                else
                                        Global.OpenForms.mainForm.contactListView.Items[contact.id].Group = Global.OpenForms.mainForm.contactListView.Groups["onlineListViewGroup"];

                                Global.OpenForms.mainForm.contactListView.Sort();
                        }
                }));
        }

        public static void EditContactAvailability(string id, Availability availability)
        {
                Global.OpenForms.mainForm.BeginInvoke(new MethodInvoker(() =>
                {
                        if (Global.OpenForms.mainForm.contactListView.Items.ContainsKey(id))
                        {
                                (Global.OpenForms.mainForm.contactListView.Items[id] as ContactListViewItem).contact.availability = availability;
                                if (availability == Availability.Offline)
                                        Global.OpenForms.mainForm.contactListView.Items[id].Group = Global.OpenForms.mainForm.contactListView.Groups["offlineListViewGroup"];
                                else
                                        Global.OpenForms.mainForm.contactListView.Items[id].Group = Global.OpenForms.mainForm.contactListView.Groups["onlineListViewGroup"];

                                Global.OpenForms.mainForm.contactListView.Sort();
                        }
                }));
        }

        public static void RemoveContact(string id)
        {
                Global.OpenForms.mainForm.Invoke(new MethodInvoker(() =>
                {
                        Global.OpenForms.mainForm.contactListView.Items.RemoveByKey(id);
                }));
        }
}

 

  Aktivity (1)

Článek pro vás napsal David Jančík [sczdavos]
Avatar
Autor je vášnivý programátor v .NET C# a PHP. Nezná slovo "nelze", nebojí se zkoušet nepoznané a pronikat do nových technologií.

Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!


 



 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!