Click here to Skip to main content
15,892,674 members
Articles / Web Development / ASP.NET

Chat Application using Web services in C#

Rate me:
Please Sign up or sign in to vote.
4.85/5 (38 votes)
15 May 2008CPOL5 min read 384.8K   41.8K   139  
This is a cool chat application created in DotNet using web services having all the functionalities.
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Reflection;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace ChatClient
{
    /// <summary>
    /// Display An MSN-Messenger-Style NotifyWindow.
    /// </summary>
    public partial class NotifyWindow : Form
    {
        #region Public Variables
        /// <summary>
        /// Gets or sets the title text to be displayed in the NotifyWindow.
        /// </summary>
        public string Title;
        /// <summary>
        /// Gets or sets the Font used for the title text.
        /// </summary>
        public System.Drawing.Font TitleFont;
        /// <summary>
        /// Gets or sets the Font used when the mouse hovers over the main body of text.
        /// </summary>
        public System.Drawing.Font HoverFont;
        /// <summary>
        /// Gets or sets the Font used when the mouse hovers over the title text.
        /// </summary>
        public System.Drawing.Font TitleHoverFont;
        /// <summary>
        /// Gets or sets the style used when drawing the background of the NotifyWindow.
        /// </summary>
        public BackgroundStyles BackgroundStyle;
        /// <summary>
        /// Gets or sets the Blend used when drawing a gradient background for the NotifyWindow.
        /// </summary>
        public System.Drawing.Drawing2D.Blend Blend;
        /// <summary>
        /// Gets or sets the StringFormat used when drawing text in the NotifyWindow.
        /// </summary>
        public System.Drawing.StringFormat StringFormat;
        /// <summary>
        /// Gets or sets a value specifiying whether or not the window should continue to be displayed if the mouse cursor is inside the bounds
        /// of the NotifyWindow.
        /// </summary>
        public bool WaitOnMouseOver;
        /// <summary>
        /// An EventHandler called when the NotifyWindow main text is clicked.
        /// </summary>
        public event System.EventHandler TextClicked;
        /// <summary>
        /// An EventHandler called when the NotifyWindow title text is clicked.
        /// </summary>
        public event System.EventHandler TitleClicked;
        /// <summary>
        /// Gets or sets the color of the title text.
        /// </summary>
        public System.Drawing.Color TitleColor;
        /// <summary>
        /// Gets or sets the color of the NotifyWindow main text.
        /// </summary>
        public System.Drawing.Color TextColor;
        /// <summary>
        /// Gets or sets the gradient color which will be blended in drawing the background.
        /// </summary>
        public System.Drawing.Color GradientColor;
        /// <summary>
        /// Gets or sets the color of text when the user clicks on it.
        /// </summary>
        public System.Drawing.Color PressedColor;
        /// <summary>
        /// Gets or sets the amount of milliseconds to display the NotifyWindow for.
        /// </summary>
        public int WaitTime;
        /// <summary>
        /// Gets or sets the full height of the NotifyWindow, used after the opening animation has been completed.
        /// </summary>
        public int ActualHeight;
        /// <summary>
        /// Gets or sets the full width of the NotifyWindow.
        /// </summary>
        public int ActualWidth;

        public enum BackgroundStyles { BackwardDiagonalGradient, ForwardDiagonalGradient, HorizontalGradient, VerticalGradient, Solid };
        public enum ClockStates { Opening, Closing, Showing, None };
        public ClockStates ClockState;
        #endregion

        #region Protected Variables
        protected bool closePressed = false, textPressed = false, titlePressed = false, closeHot = false, textHot = false, titleHot = false;
        protected Rectangle rClose, rText, rTitle, rDisplay, rScreen, rGlobClose, rGlobText, rGlobTitle, rGlobDisplay;
        protected System.Windows.Forms.Timer viewClock;
        #endregion

        #region Constructor
        /// <param name="title">Title text displayed in the NotifyWindow</param>
        /// <param name="text">Main text displayedin the NotifyWindow</param>
        public NotifyWindow(string title, string text) : this() { Title = title; Text = text; }
        /// <param name="text">Text displayed in the NotifyWindow</param>
        public NotifyWindow(string text) : this() { Text = text; }
        public NotifyWindow()
        {
            SetStyle(ControlStyles.UserMouse, true);
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);		// WmPaint calls OnPaint and OnPaintBackground
            SetStyle(ControlStyles.DoubleBuffer, true);

            ShowInTaskbar = false;
            FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            StartPosition = System.Windows.Forms.FormStartPosition.Manual;

            // Default values
            BackgroundStyle = BackgroundStyles.VerticalGradient;
            ClockState = ClockStates.None;
            BackColor = Color.SteelBlue;
            GradientColor = Color.WhiteSmoke;
            PressedColor = Color.Gray;
            TitleColor = SystemColors.ControlText;
            TextColor = SystemColors.ControlText;
            WaitOnMouseOver = true;
            ActualWidth = 130;
            ActualHeight = 110;
            WaitTime = 11000;
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Sets the width and height of the NotifyWindow.
        /// </summary>
        public void SetDimensions(int width, int height)
        {
            ActualWidth = width;
            ActualHeight = height;
        }

        /// <summary>
        /// Displays the NotifyWindow.
        /// </summary>
        public void Notify()
        {
            if (Text == null || Text.Length < 1)
                throw new System.Exception("You must set NotifyWindow.Text before calling Notify()");

            Width = ActualWidth;
            rScreen = Screen.GetWorkingArea(Screen.PrimaryScreen.Bounds);
            Height = 0;
            Top = rScreen.Bottom;
            Left = rScreen.Width - Width - 11;

            if (HoverFont == null)
                HoverFont = new Font(Font, Font.Style | FontStyle.Underline);
            if (TitleFont == null)
                TitleFont = Font;
            if (TitleHoverFont == null)
                TitleHoverFont = new Font(TitleFont, TitleFont.Style | FontStyle.Underline);
            if (this.StringFormat == null)
            {
                this.StringFormat = new StringFormat();
                this.StringFormat.Alignment = StringAlignment.Center;
                this.StringFormat.LineAlignment = StringAlignment.Center;
                this.StringFormat.Trimming = StringTrimming.EllipsisWord;
            }

            rDisplay = new Rectangle(0, 0, Width, ActualHeight);
            rClose = new Rectangle(Width - 21, 10, 13, 13);

            int offset;
            if (Title != null)
            {
                using (Graphics fx = CreateGraphics())
                {
                    SizeF sz = fx.MeasureString(Title, TitleFont, ActualWidth - rClose.Width - 22, this.StringFormat);
                    rTitle = new Rectangle(11, 12, (int)Math.Ceiling(sz.Width), (int)Math.Ceiling(sz.Height));
                    offset = (int)Math.Max(Math.Ceiling(sz.Height + rTitle.Top + 2), rClose.Bottom + 5);
                }
            }
            else
            {
                offset = rClose.Bottom + 1;
                rTitle = new Rectangle(-1, -1, 1, 1);
            }

            rText = new Rectangle(11, offset, ActualWidth - 22, ActualHeight - (int)(offset * 1.5));
            // rGlob* are Rectangle's Offset'ed to their actual position on the screen, for use with Cursor.Position.
            rGlobClose = rClose;
            rGlobClose.Offset(Left, rScreen.Bottom - ActualHeight);
            rGlobText = rText;
            rGlobText.Offset(Left, rScreen.Bottom - ActualHeight);
            rGlobTitle = rTitle;
            if (Title != null)
                rGlobTitle.Offset(Left, rScreen.Bottom - ActualHeight);
            rGlobDisplay = rDisplay;
            rGlobDisplay.Offset(Left, rScreen.Bottom - ActualHeight);
            rGlobClose = rClose;
            rGlobClose.Offset(Left, rScreen.Bottom - ActualHeight);
            rGlobDisplay = rDisplay;
            rGlobDisplay.Offset(Left, rScreen.Bottom - ActualHeight);

            // Use unmanaged ShowWindow() and SetWindowPos() instead of the managed Show() to display the window - this method will display
            // the window TopMost, but without stealing focus (namely the SW_SHOWNOACTIVATE and SWP_NOACTIVATE flags)
            ShowWindow(Handle, SW_SHOWNOACTIVATE);
            SetWindowPos(Handle, HWND_TOPMOST, rScreen.Width - ActualWidth - 11, rScreen.Bottom, ActualWidth, 0, SWP_NOACTIVATE);

            viewClock = new System.Windows.Forms.Timer();
            viewClock.Tick += new System.EventHandler(viewTimer);
            viewClock.Interval = 1;
            viewClock.Start();

            ClockState = ClockStates.Opening;
        }
        #endregion

        #region Drawing
        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
            // Draw the close button and text.
            drawCloseButton(e.Graphics);

            Font useFont; Color useColor;
            if (Title != null)
            {
                if (titleHot)
                    useFont = TitleHoverFont;
                else
                    useFont = TitleFont;
                if (titlePressed)
                    useColor = PressedColor;
                else
                    useColor = TitleColor;
                using (SolidBrush sb = new SolidBrush(useColor))
                    e.Graphics.DrawString(Title, useFont, sb, rTitle, this.StringFormat);
            }

            if (textHot)
                useFont = HoverFont;
            else
                useFont = Font;
            if (textPressed)
                useColor = PressedColor;
            else
                useColor = TextColor;
            using (SolidBrush sb = new SolidBrush(useColor))
                e.Graphics.DrawString(Text, useFont, sb, rText, this.StringFormat);
        }

        protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs e)
        {
            // First paint the background
            if (BackgroundStyle == BackgroundStyles.Solid)
            {
                using (SolidBrush sb = new SolidBrush(BackColor))
                    e.Graphics.FillRectangle(sb, rDisplay);
            }
            else
            {
                LinearGradientMode lgm;
                switch (BackgroundStyle)
                {
                    case BackgroundStyles.BackwardDiagonalGradient:
                        lgm = LinearGradientMode.BackwardDiagonal;
                        break;
                    case BackgroundStyles.ForwardDiagonalGradient:
                        lgm = LinearGradientMode.ForwardDiagonal;
                        break;
                    case BackgroundStyles.HorizontalGradient:
                        lgm = LinearGradientMode.Horizontal;
                        break;
                    default:
                    case BackgroundStyles.VerticalGradient:
                        lgm = LinearGradientMode.Vertical;
                        break;
                }
                using (LinearGradientBrush lgb = new LinearGradientBrush(rDisplay, GradientColor, BackColor, lgm))
                {
                    if (this.Blend != null)
                        lgb.Blend = this.Blend;
                    e.Graphics.FillRectangle(lgb, rDisplay);
                }
            }

            // Next draw borders...
            drawBorder(e.Graphics);
        }

        protected virtual void drawBorder(Graphics fx)
        {
            fx.DrawRectangle(Pens.Silver, 2, 2, Width - 4, ActualHeight - 4);

            // Top border
            fx.DrawLine(Pens.Silver, 0, 0, Width, 0);
            fx.DrawLine(Pens.White, 0, 1, Width, 1);
            fx.DrawLine(Pens.DarkGray, 3, 3, Width - 4, 3);
            fx.DrawLine(Pens.DimGray, 4, 4, Width - 5, 4);

            // Left border
            fx.DrawLine(Pens.Silver, 0, 0, 0, ActualHeight);
            fx.DrawLine(Pens.White, 1, 1, 1, ActualHeight);
            fx.DrawLine(Pens.DarkGray, 3, 3, 3, ActualHeight - 4);
            fx.DrawLine(Pens.DimGray, 4, 4, 4, ActualHeight - 5);

            // Bottom border
            fx.DrawLine(Pens.DarkGray, 1, ActualHeight - 1, Width - 1, ActualHeight - 1);
            fx.DrawLine(Pens.White, 3, ActualHeight - 3, Width - 3, ActualHeight - 3);
            fx.DrawLine(Pens.Silver, 4, ActualHeight - 4, Width - 4, ActualHeight - 4);

            // Right border
            fx.DrawLine(Pens.DarkGray, Width - 1, 1, Width - 1, ActualHeight - 1);
            fx.DrawLine(Pens.White, Width - 3, 3, Width - 3, ActualHeight - 3);
            fx.DrawLine(Pens.Silver, Width - 4, 4, Width - 4, ActualHeight - 4);
        }

        protected virtual void drawCloseButton(Graphics fx)
        {
            if (visualStylesEnabled())
                drawThemeCloseButton(fx);
            else
                drawLegacyCloseButton(fx);
        }

        /// <summary>
        /// Draw a Windows XP style close button.
        /// </summary>
        protected void drawThemeCloseButton(Graphics fx)
        {
            IntPtr hTheme = OpenThemeData(Handle, "Window");
            if (hTheme == IntPtr.Zero)
            {
                drawLegacyCloseButton(fx);
                return;
            }
            int stateId;
            if (closePressed)
                stateId = CBS_PUSHED;
            else if (closeHot)
                stateId = CBS_HOT;
            else
                stateId = CBS_NORMAL;
            RECT reClose = new RECT(rClose);
            RECT reClip = reClose; // should fx.VisibleClipBounds be used here?
            IntPtr hDC = fx.GetHdc();
            DrawThemeBackground(hTheme, hDC, WP_CLOSEBUTTON, stateId, ref reClose, ref reClip);
            fx.ReleaseHdc(hDC);
            CloseThemeData(hTheme);
        }

        /// <summary>
        /// Draw a Windows 95 style close button.
        /// </summary>
        protected void drawLegacyCloseButton(Graphics fx)
        {
            ButtonState bState;
            if (closePressed)
                bState = ButtonState.Pushed;
            else // the Windows 95 theme doesn't have a "hot" button
                bState = ButtonState.Normal;
            ControlPaint.DrawCaptionButton(fx, rClose, CaptionButton.Close, bState);
        }

        /// <summary>
        /// Determine whether or not XP Visual Styles are active.  Compatible with pre-UxTheme.dll versions of Windows.
        /// </summary>
        protected bool visualStylesEnabled()
        {
            try
            {
                if (IsThemeActive() == 1)
                    return true;
                else
                    return false;
            }
            catch (System.DllNotFoundException)  // pre-XP systems which don't have UxTheme.dll
            {
                return false;
            }
        }
        #endregion

        #region Timers and EventHandlers
        protected void viewTimer(object sender, System.EventArgs e)
        {
            switch (ClockState)
            {
                case ClockStates.Opening:
                    if (Top - 2 <= rScreen.Height - ActualHeight)
                    {
                        Top = rScreen.Height - ActualHeight;
                        Height = ActualHeight;
                        ClockState = ClockStates.Showing;
                        viewClock.Interval = WaitTime;
                    }
                    else
                    {
                        Top -= 2;
                        Height += 2;
                    }
                    break;

                case ClockStates.Showing:
                    if (!WaitOnMouseOver || !rGlobDisplay.Contains(Cursor.Position))
                    {
                        viewClock.Interval = 1;
                        ClockState = ClockStates.Closing;
                    }
                    break;

                case ClockStates.Closing:
                    Top += 2;
                    Height -= 2;
                    if (Top >= rScreen.Height)
                    {
                        ClockState = ClockStates.None;
                        viewClock.Stop();
                        viewClock.Dispose();
                        Close();
                    }
                    break;
            }
        }

        protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e)
        {
            if (Title != null && rGlobTitle.Contains(Cursor.Position) && !textPressed && !closePressed)
            {
                Cursor = Cursors.Hand;
                titleHot = true;
                textHot = false; closeHot = false;
                Invalidate();
            }
            else if (rGlobText.Contains(Cursor.Position) && !titlePressed && !closePressed)
            {
                Cursor = Cursors.Hand;
                textHot = true;
                titleHot = false; closeHot = false;
                Invalidate();
            }
            else if (rGlobClose.Contains(Cursor.Position) && !titlePressed && !textPressed)
            {
                Cursor = Cursors.Hand;
                closeHot = true;
                titleHot = false; textHot = false;
                Invalidate();
            }
            else if ((textHot || titleHot || closeHot) && (!titlePressed && !textPressed && !closePressed))
            {
                Cursor = Cursors.Default;
                titleHot = false; textHot = false; closeHot = false;
                Invalidate();
            }
            base.OnMouseMove(e);
        }

        protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (rGlobClose.Contains(Cursor.Position))
                {
                    closePressed = true;
                    closeHot = false;
                    Invalidate();
                }
                else if (rGlobText.Contains(Cursor.Position))
                {
                    textPressed = true;
                    Invalidate();
                }
                else if (Title != null && rGlobTitle.Contains(Cursor.Position))
                {
                    titlePressed = true;
                    Invalidate();
                }
            }
            base.OnMouseDown(e);
        }

        protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (closePressed)
                {
                    Cursor = Cursors.Default;
                    closePressed = false;
                    closeHot = false;
                    Invalidate();
                    if (rGlobClose.Contains(Cursor.Position))
                        Close();
                }
                else if (textPressed)
                {
                    Cursor = Cursors.Default;
                    textPressed = false;
                    textHot = false;
                    Invalidate();
                    if (rGlobText.Contains(Cursor.Position))
                    {
                        Close();
                        if (TextClicked != null)
                            TextClicked(this, new System.EventArgs());
                    }
                }
                else if (titlePressed)
                {
                    Cursor = Cursors.Default;
                    titlePressed = false;
                    titleHot = false;
                    Invalidate();
                    if (rGlobTitle.Contains(Cursor.Position))
                    {
                        Close();
                        if (TitleClicked != null)
                            TitleClicked(this, new System.EventArgs());
                    }
                }
            }
            base.OnMouseUp(e);
        }
        #endregion

        #region P/Invoke
        // DrawThemeBackground()
        protected const Int32 WP_CLOSEBUTTON = 18;
        protected const Int32 CBS_NORMAL = 1;
        protected const Int32 CBS_HOT = 2;
        protected const Int32 CBS_PUSHED = 3;
        [StructLayout(LayoutKind.Explicit)]
        protected struct RECT
        {
            [FieldOffset(0)]
            public Int32 Left;
            [FieldOffset(4)]
            public Int32 Top;
            [FieldOffset(8)]
            public Int32 Right;
            [FieldOffset(12)]
            public Int32 Bottom;

            public RECT(System.Drawing.Rectangle bounds)
            {
                Left = bounds.Left;
                Top = bounds.Top;
                Right = bounds.Right;
                Bottom = bounds.Bottom;
            }
        }

        // SetWindowPos()
        protected const Int32 HWND_TOPMOST = -1;
        protected const Int32 SWP_NOACTIVATE = 0x0010;

        // ShowWindow()
        protected const Int32 SW_SHOWNOACTIVATE = 4;

        // UxTheme.dll
        [DllImport("UxTheme.dll")]
        protected static extern Int32 IsThemeActive();
        [DllImport("UxTheme.dll")]
        protected static extern IntPtr OpenThemeData(IntPtr hWnd, [MarshalAs(UnmanagedType.LPTStr)] string classList);
        [DllImport("UxTheme.dll")]
        protected static extern void CloseThemeData(IntPtr hTheme);
        [DllImport("UxTheme.dll")]
        protected static extern void DrawThemeBackground(IntPtr hTheme, IntPtr hDC, Int32 partId, Int32 stateId, ref RECT rect, ref RECT clipRect);

        // user32.dll
        [DllImport("user32.dll")]
        protected static extern bool ShowWindow(IntPtr hWnd, Int32 flags);
        [DllImport("user32.dll")]
        protected static extern bool SetWindowPos(IntPtr hWnd, Int32 hWndInsertAfter, Int32 X, Int32 Y, Int32 cx, Int32 cy, uint uFlags);
        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader
United States United States
He has a total experience of more than 6 years in programming on different technologies. Currently working as a Systems Analyst.

Comments and Discussions