Files
FSI.BT.IR.Tools/Notification-Popup-Window/Tulpep.NotificationWindow/PopupNotifierForm.cs
Stephan Maier 647f938eee v1.2
2024-08-27 08:10:27 +02:00

398 lines
16 KiB
C#

/*
* 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
{
/// <summary>
/// This is the form of the actual notification window.
/// </summary>
internal class PopupNotifierForm : System.Windows.Forms.Form
{
/// <summary>
/// Event that is raised when the text is clicked.
/// </summary>
public event EventHandler LinkClick;
/// <summary>
/// Event that is raised when the notification window is manually closed.
/// </summary>
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
/// <summary>
/// Create a new instance.
/// </summary>
/// <param name="parent">PopupNotifier</param>
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);
}
/// <summary>
/// The form is shown/hidden.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PopupNotifierForm_VisibleChanged(object sender, EventArgs e)
{
if (this.Visible)
{
mouseOnClose = false;
mouseOnLink = false;
mouseOnOptions = false;
}
}
/// <summary>
/// Used in design mode.
/// </summary>
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);
}
/// <summary>
/// Gets or sets the parent control.
/// </summary>
public new PopupNotifier Parent { get; set; }
/// <summary>
/// Add two values but do not return a value greater than 255.
/// </summary>
/// <param name="input">first value</param>
/// <param name="add">value to add</param>
/// <returns>sum of both values</returns>
private int AddValueMax255(int input, int add)
{
return (input + add < 256) ? input + add : 255;
}
/// <summary>
/// Subtract two values but do not returns a value below 0.
/// </summary>
/// <param name="input">first value</param>
/// <param name="ded">value to subtract</param>
/// <returns>first value minus second value</returns>
private int DedValueMin0(int input, int ded)
{
return (input - ded > 0) ? input - ded : 0;
}
/// <summary>
/// Returns a color which is darker than the given color.
/// </summary>
/// <param name="color">Color</param>
/// <returns>darker color</returns>
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));
}
/// <summary>
/// Returns a color which is lighter than the given color.
/// </summary>
/// <param name="color">Color</param>
/// <returns>lighter color</returns>
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));
}
/// <summary>
/// Gets the rectangle of the content text.
/// </summary>
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);
}
}
}
/// <summary>
/// gets the rectangle of the close button.
/// </summary>
private Rectangle RectClose
{
get { return new Rectangle(this.Width - 5 - 16, Parent.HeaderHeight + 3, 16, 16); }
}
/// <summary>
/// Gets the rectangle of the options button.
/// </summary>
private Rectangle RectOptions
{
get { return new Rectangle(this.Width - 5 - 16, Parent.HeaderHeight + 3 + 16 + 5, 16, 16); }
}
/// <summary>
/// Update form to display hover styles when the mouse moves over the notification form.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
/// <summary>
/// A mouse button has been released, check if something has been clicked.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
}
/// <summary>
/// The options popup menu has been closed.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OptionsMenu_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
Parent.OptionsMenu.Closed -= new ToolStripDropDownClosedEventHandler(OptionsMenu_Closed);
if (ContextMenuClosed != null)
{
ContextMenuClosed(this, EventArgs.Empty);
}
}
/// <summary>
/// Create all GDI objects used to paint the form.
/// </summary>
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;
}
/// <summary>
/// Free all GDI objects.
/// </summary>
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();
}
}
/// <summary>
/// Draw the notification form.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
/// <summary>
/// Dispose GDI objects.
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
if (disposing)
{
DisposeGDIObjects();
}
base.Dispose(disposing);
}
}
}