Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

5. diel - Prístup k okýnkům, mutex, fce messengera - isim

Global.cs

Tu to bude trošku rozsiahlejší, budú tu vnorené triedy, premenné a tak ďalej. Možno odporúčam si to potom roztriediť do viacerých súborov.

Enum dostupnosti môže byť nasledovné. Priradením hodnoty čísla, potom možno jednoducho pretypovať na integer a túto hodnotu získať. Tu to využívam ako určenie priority pri radení.

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

Prvý vnorená trieda obsahujúca inštancie okienok:

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

Ďalšia vnorená trieda je pre mutex - odosielanie signálu. Popísané tu: 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);
    }
}

Teraz bude veľká vnorená trieda s funkciami messengera.

public static class ISIMFunctions
{

Invoke -> zaujímavá a užitočná metůdka, využívajúce sa pri multi threading -> zásahu do iného threadu (okienka) z jinýho threadu (okienka). Vzdám si ho a pracujem s ním. Tu je preto, aby som zaistil spustenie okienka chatu na hlavnom vlákne. Inak by sa mohlo stať, že sa metóda OpenChatForm zavolá z iného threadu a okienko by len probliklo - akonáhle by thread skončil, okienko by sa zavrelo. Existuje aj asynchrónne metóda BeginInvoke - čo zjednodušene znamená, že sa požiadavka pošle a ide sa ďalej, on sa časom vykoná na ďalšom vlákne, takže sa na nič nečaká.

/// <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žíva sa pre definíciu jednoriadkové metódy, ktorú možno použiť vnorené v metóde. Používa sa namiesto delegátovi delegate() kdůli kratšiemu zápisu.

object as MůjObject je spôsob takéhoto C# like pretypovanie objektu. Vlastne sa spýta, či je objekt toho typu -> object is MůjObject ? (MůjObject)object : (MůjObject)null. Ovšem nemožno to použiť napríklad vo switch, tuším že u enum a nejakých ďalších prípadoch.

/// <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(); }));
        }
    }));
}

Pre odosielanie správ sa urobí jedna univerzálna metóda, ktorá rozpozná, z ktorého protokolu ide požiadavku a podľa toho sa zariadi.

/// <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);
}

Pri pridanie kontaktu alebo editáciu jeho dostupnosti sa zavolá metóda Sort sesortí kontakty podľa nášho komparátora ai prekreslí ListView čo ma celkom štvalo, BZE to preblikáva. Preto je dobré používať BeginUpdate() a EndUpdate() ak robíme viac operácií, ako napríklad pri hromadnom pridávaní kontaktov, zablokuje to prekresľovanie urobím si čo chcem a potom to prekreslíme naraz.

    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);
        }));
    }
}

 

Predchádzajúci článok
Interface pre kontakt, Adaptee Wrapper a komparátor - isim
Všetky články v sekcii
Programujeme vlastné Instant Messenger :: isim ::
Preskočiť článok
(neodporúčame)
Konverter, práca s textom - isim
Článok pre vás napísal David Jančík
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor je vášnivý programátor. Nezná slovo "nelze", nebojí se zkoušet nepoznané a pronikat do nových technologií.
Aktivity