/* * Created/modified in 2011 by Simon Baer * * Based on the Code Project article by Nicolas Wälti: * http://www.codeproject.com/KB/cpp/PopupNotifier.aspx * * Licensed under the Code Project Open License (CPOL). */ using System; using System.Windows.Forms; using System.Drawing; using System.Drawing.Drawing2D; namespace Tulpep.NotificationWindow { /// /// This is the form of the actual notification window. /// internal class PopupNotifierForm : System.Windows.Forms.Form { /// /// Event that is raised when the text is clicked. /// public event EventHandler LinkClick; /// /// Event that is raised when the notification window is manually closed. /// public event EventHandler CloseClick; internal event EventHandler ContextMenuOpened; internal event EventHandler ContextMenuClosed; private bool mouseOnClose = false; private bool mouseOnLink = false; private bool mouseOnOptions = false; private int heightOfTitle; #region GDI objects private bool gdiInitialized = false; private Rectangle rcBody; private Rectangle rcHeader; private Rectangle rcForm; private LinearGradientBrush brushBody; private LinearGradientBrush brushHeader; private Brush brushButtonHover; private Pen penButtonBorder; private Pen penContent; private Pen penBorder; private Brush brushForeColor; private Brush brushLinkHover; private Brush brushContent; private Brush brushTitle; #endregion /// /// Create a new instance. /// /// PopupNotifier public PopupNotifierForm(PopupNotifier parent) { Parent = parent; this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.SetStyle(ControlStyles.ResizeRedraw, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.ShowInTaskbar = false; this.VisibleChanged += new EventHandler(PopupNotifierForm_VisibleChanged); this.MouseMove += new MouseEventHandler(PopupNotifierForm_MouseMove); this.MouseUp += new MouseEventHandler(PopupNotifierForm_MouseUp); this.Paint += new PaintEventHandler(PopupNotifierForm_Paint); } /// /// The form is shown/hidden. /// /// /// private void PopupNotifierForm_VisibleChanged(object sender, EventArgs e) { if (this.Visible) { mouseOnClose = false; mouseOnLink = false; mouseOnOptions = false; } } /// /// Used in design mode. /// private void InitializeComponent() { this.SuspendLayout(); // // PopupNotifierForm // this.ClientSize = new System.Drawing.Size(392, 66); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.Name = "PopupNotifierForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; this.ResumeLayout(false); } /// /// Gets or sets the parent control. /// public new PopupNotifier Parent { get; set; } /// /// Add two values but do not return a value greater than 255. /// /// first value /// value to add /// sum of both values private int AddValueMax255(int input, int add) { return (input + add < 256) ? input + add : 255; } /// /// Subtract two values but do not returns a value below 0. /// /// first value /// value to subtract /// first value minus second value private int DedValueMin0(int input, int ded) { return (input - ded > 0) ? input - ded : 0; } /// /// Returns a color which is darker than the given color. /// /// Color /// darker color private Color GetDarkerColor(Color color) { return System.Drawing.Color.FromArgb(255, DedValueMin0((int)color.R, Parent.GradientPower), DedValueMin0((int)color.G, Parent.GradientPower), DedValueMin0((int)color.B, Parent.GradientPower)); } /// /// Returns a color which is lighter than the given color. /// /// Color /// lighter color private Color GetLighterColor(Color color) { return System.Drawing.Color.FromArgb(255, AddValueMax255((int)color.R, Parent.GradientPower), AddValueMax255((int)color.G, Parent.GradientPower), AddValueMax255((int)color.B, Parent.GradientPower)); } /// /// Gets the rectangle of the content text. /// private RectangleF RectContentText { get { if (Parent.Image != null) { return new RectangleF( Parent.ImagePadding.Left + Parent.ImageSize.Width + Parent.ImagePadding.Right + Parent.ContentPadding.Left, Parent.HeaderHeight + Parent.TitlePadding.Top + heightOfTitle + Parent.TitlePadding.Bottom + Parent.ContentPadding.Top, this.Width - Parent.ImagePadding.Left - Parent.ImageSize.Width - Parent.ImagePadding.Right - Parent.ContentPadding.Left - Parent.ContentPadding.Right - 16 - 5, this.Height - Parent.HeaderHeight - Parent.TitlePadding.Top - heightOfTitle - Parent.TitlePadding.Bottom - Parent.ContentPadding.Top - Parent.ContentPadding.Bottom - 1); } else { return new RectangleF( Parent.ContentPadding.Left, Parent.HeaderHeight + Parent.TitlePadding.Top + heightOfTitle + Parent.TitlePadding.Bottom + Parent.ContentPadding.Top, this.Width - Parent.ContentPadding.Left - Parent.ContentPadding.Right - 16 - 5, this.Height - Parent.HeaderHeight - Parent.TitlePadding.Top - heightOfTitle - Parent.TitlePadding.Bottom - Parent.ContentPadding.Top - Parent.ContentPadding.Bottom - 1); } } } /// /// gets the rectangle of the close button. /// private Rectangle RectClose { get { return new Rectangle(this.Width - 5 - 16, Parent.HeaderHeight + 3, 16, 16); } } /// /// Gets the rectangle of the options button. /// private Rectangle RectOptions { get { return new Rectangle(this.Width - 5 - 16, Parent.HeaderHeight + 3 + 16 + 5, 16, 16); } } /// /// Update form to display hover styles when the mouse moves over the notification form. /// /// /// private void PopupNotifierForm_MouseMove(object sender, MouseEventArgs e) { if (Parent.ShowCloseButton) { mouseOnClose = RectClose.Contains(e.X, e.Y); } if (Parent.ShowOptionsButton) { mouseOnOptions = RectOptions.Contains(e.X, e.Y); } mouseOnLink = RectContentText.Contains(e.X, e.Y); Invalidate(); } /// /// A mouse button has been released, check if something has been clicked. /// /// /// private void PopupNotifierForm_MouseUp(object sender, MouseEventArgs e) { if (e.Button == System.Windows.Forms.MouseButtons.Left) { if (RectClose.Contains(e.X, e.Y) && (CloseClick != null)) { CloseClick(this, EventArgs.Empty); } if (RectContentText.Contains(e.X, e.Y) && (LinkClick != null)) { LinkClick(this, EventArgs.Empty); } if (RectOptions.Contains(e.X, e.Y) && (Parent.OptionsMenu != null)) { if (ContextMenuOpened != null) { ContextMenuOpened(this, EventArgs.Empty); } Parent.OptionsMenu.Show(this, new Point(RectOptions.Right - Parent.OptionsMenu.Width, RectOptions.Bottom)); Parent.OptionsMenu.Closed += new ToolStripDropDownClosedEventHandler(OptionsMenu_Closed); } } } /// /// The options popup menu has been closed. /// /// /// private void OptionsMenu_Closed(object sender, ToolStripDropDownClosedEventArgs e) { Parent.OptionsMenu.Closed -= new ToolStripDropDownClosedEventHandler(OptionsMenu_Closed); if (ContextMenuClosed != null) { ContextMenuClosed(this, EventArgs.Empty); } } /// /// Create all GDI objects used to paint the form. /// private void AllocateGDIObjects() { rcBody = new Rectangle(0, 0, this.Width, this.Height); rcHeader = new Rectangle(0, 0, this.Width, Parent.HeaderHeight); rcForm = new Rectangle(0, 0, this.Width - 1, this.Height - 1); brushBody = new LinearGradientBrush(rcBody, Parent.BodyColor, GetLighterColor(Parent.BodyColor), LinearGradientMode.Vertical); brushHeader = new LinearGradientBrush(rcHeader, Parent.HeaderColor, GetDarkerColor(Parent.HeaderColor), LinearGradientMode.Vertical); brushButtonHover = new SolidBrush(Parent.ButtonHoverColor); penButtonBorder = new Pen(Parent.ButtonBorderColor); penContent = new Pen(Parent.ContentColor, 2); penBorder = new Pen(Parent.BorderColor); brushForeColor = new SolidBrush(ForeColor); brushLinkHover = new SolidBrush(Parent.ContentHoverColor); brushContent = new SolidBrush(Parent.ContentColor); brushTitle = new SolidBrush(Parent.TitleColor); gdiInitialized = true; } /// /// Free all GDI objects. /// private void DisposeGDIObjects() { if (gdiInitialized) { brushBody.Dispose(); brushHeader.Dispose(); brushButtonHover.Dispose(); penButtonBorder.Dispose(); penContent.Dispose(); penBorder.Dispose(); brushForeColor.Dispose(); brushLinkHover.Dispose(); brushContent.Dispose(); brushTitle.Dispose(); } } /// /// Draw the notification form. /// /// /// private void PopupNotifierForm_Paint(object sender, PaintEventArgs e) { if (!gdiInitialized) { AllocateGDIObjects(); } // draw window e.Graphics.FillRectangle(brushBody, rcBody); e.Graphics.FillRectangle(brushHeader, rcHeader); e.Graphics.DrawRectangle(penBorder, rcForm); if (Parent.ShowGrip) { e.Graphics.DrawImage(Properties.Resources.Grip, (int)((this.Width - Properties.Resources.Grip.Width) / 2), (int)((Parent.HeaderHeight - 3) / 2)); } if (Parent.ShowCloseButton) { if (mouseOnClose) { e.Graphics.FillRectangle(brushButtonHover, RectClose); e.Graphics.DrawRectangle(penButtonBorder, RectClose); } e.Graphics.DrawLine(penContent, RectClose.Left + 4, RectClose.Top + 4, RectClose.Right - 4, RectClose.Bottom - 4); e.Graphics.DrawLine(penContent, RectClose.Left + 4, RectClose.Bottom - 4, RectClose.Right - 4, RectClose.Top + 4); } if (Parent.ShowOptionsButton) { if (mouseOnOptions) { e.Graphics.FillRectangle(brushButtonHover, RectOptions); e.Graphics.DrawRectangle(penButtonBorder, RectOptions); } e.Graphics.FillPolygon(brushForeColor, new Point[] { new Point(RectOptions.Left + 4, RectOptions.Top + 6), new Point(RectOptions.Left + 12, RectOptions.Top + 6), new Point(RectOptions.Left + 8, RectOptions.Top + 4 + 6) }); } // draw icon if (Parent.Image != null) { e.Graphics.DrawImage(Parent.Image, Parent.ImagePadding.Left, Parent.HeaderHeight + Parent.ImagePadding.Top, Parent.ImageSize.Width, Parent.ImageSize.Height); } if (Parent.IsRightToLeft) { heightOfTitle = (int)e.Graphics.MeasureString("A", Parent.TitleFont).Height; // the value 30 is because of x close icon int titleX2 = this.Width - 30;// Parent.TitlePadding.Right; // draw title right to left StringFormat headerFormat = new StringFormat(StringFormatFlags.DirectionRightToLeft); e.Graphics.DrawString(Parent.TitleText, Parent.TitleFont, brushTitle, titleX2, Parent.HeaderHeight + Parent.TitlePadding.Top, headerFormat); // draw content text, optionally with a bold part this.Cursor = mouseOnLink ? Cursors.Hand : Cursors.Default; Brush brushText = mouseOnLink ? brushLinkHover : brushContent; // draw content right to left StringFormat contentFormat = new StringFormat(StringFormatFlags.DirectionRightToLeft); e.Graphics.DrawString(Parent.ContentText, Parent.ContentFont, brushText, RectContentText, contentFormat); } else { // calculate height of title heightOfTitle = (int)e.Graphics.MeasureString("A", Parent.TitleFont).Height; int titleX = Parent.TitlePadding.Left; if (Parent.Image != null) titleX += Parent.ImagePadding.Left + Parent.ImageSize.Width + Parent.ImagePadding.Right; e.Graphics.DrawString(Parent.TitleText, Parent.TitleFont, brushTitle, titleX, Parent.HeaderHeight + Parent.TitlePadding.Top); // draw content text, optionally with a bold part this.Cursor = mouseOnLink ? Cursors.Hand : Cursors.Default; Brush brushText = mouseOnLink ? brushLinkHover : brushContent; e.Graphics.DrawString(Parent.ContentText, Parent.ContentFont, brushText, RectContentText); } } /// /// Dispose GDI objects. /// /// protected override void Dispose(bool disposing) { if (disposing) { DisposeGDIObjects(); } base.Dispose(disposing); } } }