// C# TaskbarNotifier Class v1.0 // by John O'Byrne - 02 december 2002 // 01 april 2003 : Small fix in the OnMouseUp handler // 11 january 2003 : Patrick Vanden Driessche added a few enhancements // Small Enhancements/Bugfix // Small bugfix: When Content text measures larger than the corresponding ContentRectangle // the focus rectangle was not correctly drawn. This has been solved. // Added KeepVisibleOnMouseOver // Added ReShowOnMouseOver // Added If the Title or Content are too long to fit in the corresponding Rectangles, // the text is truncateed and the ellipses are appended (StringTrimming). using System; using System.Drawing; using System.Drawing.Imaging; using System.Drawing.Drawing2D; using System.Windows.Forms; using System.Runtime.InteropServices; namespace CustomUIControls { /// /// TaskbarNotifier allows to display MSN style/Skinned instant messaging popups /// public class TaskbarNotifier : System.Windows.Forms.Form { #region TaskbarNotifier Protected Members protected Bitmap BackgroundBitmap = null; protected Bitmap CloseBitmap = null; protected Point CloseBitmapLocation; protected Size CloseBitmapSize; protected Rectangle RealTitleRectangle; protected Rectangle RealContentRectangle; protected Rectangle WorkAreaRectangle; protected Timer timer = new Timer(); protected TaskbarStates taskbarState = TaskbarStates.hidden; protected string titleText; protected string contentText; protected Color normalTitleColor = Color.FromArgb(255,0,0); protected Color hoverTitleColor = Color.FromArgb(255,0,0); protected Color normalContentColor = Color.FromArgb(0,0,0); protected Color hoverContentColor = Color.FromArgb(0,0,0x66); protected Font normalTitleFont = new Font("Arial",12,FontStyle.Regular,GraphicsUnit.Pixel); protected Font hoverTitleFont = new Font("Arial",12,FontStyle.Bold,GraphicsUnit.Pixel); protected Font normalContentFont = new Font("Arial",11,FontStyle.Regular,GraphicsUnit.Pixel); protected Font hoverContentFont = new Font("Arial",11,FontStyle.Regular,GraphicsUnit.Pixel); protected int nShowEvents; protected int nHideEvents; protected int nVisibleEvents; protected int nIncrementShow; protected int nIncrementHide; protected bool bIsMouseOverPopup = false; protected bool bIsMouseOverClose = false; protected bool bIsMouseOverContent = false; protected bool bIsMouseOverTitle = false; protected bool bIsMouseDown = false; protected bool bKeepVisibleOnMouseOver = true; // Added Rev 002 protected bool bReShowOnMouseOver = false; // Added Rev 002 #endregion #region TaskbarNotifier Public Members public Rectangle TitleRectangle; public Rectangle ContentRectangle; public bool TitleClickable = false; public bool ContentClickable = true; public bool CloseClickable = true; public bool EnableSelectionRectangle = true; public event EventHandler CloseClick = null; public event EventHandler TitleClick = null; public event EventHandler ContentClick = null; #endregion #region TaskbarNotifier Enums /// /// List of the different popup animation status /// public enum TaskbarStates { hidden = 0, appearing = 1, visible = 2, disappearing = 3 } #endregion #region TaskbarNotifier Constructor /// /// The Constructor for TaskbarNotifier /// public TaskbarNotifier() { // Window Style FormBorderStyle = FormBorderStyle.None; WindowState = FormWindowState.Minimized; base.Show(); base.Hide(); WindowState = FormWindowState.Normal; ShowInTaskbar = false; TopMost = true; MaximizeBox = false; MinimizeBox = false; ControlBox = false; timer.Enabled = true; timer.Tick += new EventHandler(OnTimer); } #endregion #region TaskbarNotifier Properties /// /// Get the current TaskbarState (hidden, showing, visible, hiding) /// public TaskbarStates TaskbarState { get { return taskbarState; } } /// /// Get/Set the popup Title Text /// public string TitleText { get { return titleText; } set { titleText=value; Refresh(); } } /// /// Get/Set the popup Content Text /// public string ContentText { get { return contentText; } set { contentText=value; Refresh(); } } /// /// Get/Set the Normal Title Color /// public Color NormalTitleColor { get { return normalTitleColor; } set { normalTitleColor = value; Refresh(); } } /// /// Get/Set the Hover Title Color /// public Color HoverTitleColor { get { return hoverTitleColor; } set { hoverTitleColor = value; Refresh(); } } /// /// Get/Set the Normal Content Color /// public Color NormalContentColor { get { return normalContentColor; } set { normalContentColor = value; Refresh(); } } /// /// Get/Set the Hover Content Color /// public Color HoverContentColor { get { return hoverContentColor; } set { hoverContentColor = value; Refresh(); } } /// /// Get/Set the Normal Title Font /// public Font NormalTitleFont { get { return normalTitleFont; } set { normalTitleFont = value; Refresh(); } } /// /// Get/Set the Hover Title Font /// public Font HoverTitleFont { get { return hoverTitleFont; } set { hoverTitleFont = value; Refresh(); } } /// /// Get/Set the Normal Content Font /// public Font NormalContentFont { get { return normalContentFont; } set { normalContentFont = value; Refresh(); } } /// /// Get/Set the Hover Content Font /// public Font HoverContentFont { get { return hoverContentFont; } set { hoverContentFont = value; Refresh(); } } /// /// Indicates if the popup should remain visible when the mouse pointer is over it. /// Added Rev 002 /// public bool KeepVisibleOnMousOver { get { return bKeepVisibleOnMouseOver; } set { bKeepVisibleOnMouseOver=value; } } /// /// Indicates if the popup should appear again when mouse moves over it while it's disappearing. /// Added Rev 002 /// public bool ReShowOnMouseOver { get { return bReShowOnMouseOver; } set { bReShowOnMouseOver=value; } } #endregion #region TaskbarNotifier Public Methods //[DllImport("user32.dll")] //private static extern Boolean ShowWindow(IntPtr hWnd,Int32 nCmdShow); /// /// Displays the popup for a certain amount of time /// /// The string which will be shown as the title of the popup /// The string which will be shown as the content of the popup /// Duration of the showing animation (in milliseconds) /// Duration of the visible state before collapsing (in milliseconds) /// Duration of the hiding animation (in milliseconds) /// Nothing public void Show(string strTitle, string strContent, int nTimeToShow, int nTimeToStay, int nTimeToHide) { WorkAreaRectangle = Screen.GetWorkingArea(WorkAreaRectangle); titleText = strTitle; contentText = strContent; nVisibleEvents = nTimeToStay; CalculateMouseRectangles(); // We calculate the pixel increment and the timer value for the showing animation int nEvents; if (nTimeToShow > 10) { nEvents = Math.Min((nTimeToShow / 10), BackgroundBitmap.Height); nShowEvents = nTimeToShow / nEvents; nIncrementShow = BackgroundBitmap.Height / nEvents; } else { nShowEvents = 10; nIncrementShow = BackgroundBitmap.Height; } // We calculate the pixel increment and the timer value for the hiding animation if( nTimeToHide > 10) { nEvents = Math.Min((nTimeToHide / 10), BackgroundBitmap.Height); nHideEvents = nTimeToHide / nEvents; nIncrementHide = BackgroundBitmap.Height / nEvents; } else { nHideEvents = 10; nIncrementHide = BackgroundBitmap.Height; } switch (taskbarState) { case TaskbarStates.hidden: taskbarState = TaskbarStates.appearing; SetBounds(WorkAreaRectangle.Right-BackgroundBitmap.Width-17, WorkAreaRectangle.Bottom-1, BackgroundBitmap.Width, 0); timer.Interval = nShowEvents; timer.Start(); // We Show the popup without stealing focus //ShowWindow(this.Handle, 4); Show(); //2014.04.13. break; case TaskbarStates.appearing: Refresh(); break; case TaskbarStates.visible: timer.Stop(); timer.Interval = nVisibleEvents; timer.Start(); Refresh(); break; case TaskbarStates.disappearing: timer.Stop(); taskbarState = TaskbarStates.visible; SetBounds(WorkAreaRectangle.Right-BackgroundBitmap.Width-17, WorkAreaRectangle.Bottom-BackgroundBitmap.Height-1, BackgroundBitmap.Width, BackgroundBitmap.Height); timer.Interval = nVisibleEvents; timer.Start(); Refresh(); break; } } /// /// Hides the popup /// /// Nothing public new void Hide() { if (taskbarState != TaskbarStates.hidden) { timer.Stop(); taskbarState = TaskbarStates.hidden; base.Hide(); } } /// /// Sets the background bitmap and its transparency color /// /// Path of the Background Bitmap on the disk /// Color of the Bitmap which won't be visible /// Nothing public void SetBackgroundBitmap(string strFilename, Color transparencyColor) { BackgroundBitmap = new Bitmap(strFilename); Width = BackgroundBitmap.Width; Height = BackgroundBitmap.Height; Region = BitmapToRegion(BackgroundBitmap, transparencyColor); } /// /// Sets the background bitmap and its transparency color /// /// Image/Bitmap object which represents the Background Bitmap /// Color of the Bitmap which won't be visible /// Nothing public void SetBackgroundBitmap(Image image, Color transparencyColor) { BackgroundBitmap = new Bitmap(image); Width = BackgroundBitmap.Width; Height = BackgroundBitmap.Height; Region = BitmapToRegion(BackgroundBitmap, transparencyColor); } /// /// Sets the 3-State Close Button bitmap, its transparency color and its coordinates /// /// Path of the 3-state Close button Bitmap on the disk (width must a multiple of 3) /// Color of the Bitmap which won't be visible /// Location of the close button on the popup /// Nothing public void SetCloseBitmap(string strFilename, Color transparencyColor, Point position) { CloseBitmap = new Bitmap(strFilename); CloseBitmap.MakeTransparent(transparencyColor); CloseBitmapSize = new Size(CloseBitmap.Width/3, CloseBitmap.Height); CloseBitmapLocation = position; } /// /// Sets the 3-State Close Button bitmap, its transparency color and its coordinates /// /// Image/Bitmap object which represents the 3-state Close button Bitmap (width must be a multiple of 3) /// Color of the Bitmap which won't be visible /// /// Location of the close button on the popup /// Nothing public void SetCloseBitmap(Image image, Color transparencyColor, Point position) { CloseBitmap = new Bitmap(image); CloseBitmap.MakeTransparent(transparencyColor); CloseBitmapSize = new Size(CloseBitmap.Width/3, CloseBitmap.Height); CloseBitmapLocation = position; } #endregion #region TaskbarNotifier Protected Methods protected void DrawCloseButton(Graphics grfx) { if (CloseBitmap != null) { Rectangle rectDest = new Rectangle(CloseBitmapLocation, CloseBitmapSize); Rectangle rectSrc; if (bIsMouseOverClose) { if (bIsMouseDown) rectSrc = new Rectangle(new Point(CloseBitmapSize.Width*2, 0), CloseBitmapSize); else rectSrc = new Rectangle(new Point(CloseBitmapSize.Width, 0), CloseBitmapSize); } else rectSrc = new Rectangle(new Point(0, 0), CloseBitmapSize); grfx.DrawImage(CloseBitmap, rectDest, rectSrc, GraphicsUnit.Pixel); } } protected void DrawText(Graphics grfx) { if (titleText != null && titleText.Length != 0) { StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Near; sf.LineAlignment = StringAlignment.Center; sf.FormatFlags = StringFormatFlags.NoWrap; sf.Trimming = StringTrimming.EllipsisCharacter; // Added Rev 002 if (bIsMouseOverTitle) grfx.DrawString(titleText, hoverTitleFont, new SolidBrush(hoverTitleColor), TitleRectangle, sf); else grfx.DrawString(titleText, normalTitleFont, new SolidBrush(normalTitleColor), TitleRectangle, sf); } if (contentText != null && contentText.Length != 0) { StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Center; sf.FormatFlags = StringFormatFlags.MeasureTrailingSpaces; sf.Trimming = StringTrimming.Word; // Added Rev 002 if (bIsMouseOverContent) { grfx.DrawString(contentText, hoverContentFont, new SolidBrush(hoverContentColor), ContentRectangle, sf); if (EnableSelectionRectangle) ControlPaint.DrawBorder3D(grfx, RealContentRectangle, Border3DStyle.Etched, Border3DSide.Top | Border3DSide.Bottom | Border3DSide.Left | Border3DSide.Right); } else grfx.DrawString(contentText, normalContentFont, new SolidBrush(normalContentColor), ContentRectangle, sf); } } protected void CalculateMouseRectangles() { Graphics grfx = CreateGraphics(); StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Center; sf.FormatFlags = StringFormatFlags.MeasureTrailingSpaces; SizeF sizefTitle = grfx.MeasureString(titleText, hoverTitleFont, TitleRectangle.Width, sf); SizeF sizefContent = grfx.MeasureString(contentText, hoverContentFont, ContentRectangle.Width, sf); grfx.Dispose(); // Added Rev 002 //We should check if the title size really fits inside the pre-defined title rectangle if (sizefTitle.Height > TitleRectangle.Height) { RealTitleRectangle = new Rectangle(TitleRectangle.Left, TitleRectangle.Top, TitleRectangle.Width , TitleRectangle.Height ); } else { RealTitleRectangle = new Rectangle(TitleRectangle.Left, TitleRectangle.Top, (int)sizefTitle.Width, (int)sizefTitle.Height); } RealTitleRectangle.Inflate(0,2); // Added Rev 002 //We should check if the Content size really fits inside the pre-defined Content rectangle if (sizefContent.Height > ContentRectangle.Height) { RealContentRectangle = new Rectangle((ContentRectangle.Width-(int)sizefContent.Width)/2+ContentRectangle.Left, ContentRectangle.Top, (int)sizefContent.Width, ContentRectangle.Height ); } else { RealContentRectangle = new Rectangle((ContentRectangle.Width-(int)sizefContent.Width)/2+ContentRectangle.Left, (ContentRectangle.Height-(int)sizefContent.Height)/2+ContentRectangle.Top, (int)sizefContent.Width, (int)sizefContent.Height); } RealContentRectangle.Inflate(0,2); } protected Region BitmapToRegion(Bitmap bitmap, Color transparencyColor) { if (bitmap == null) throw new ArgumentNullException("Bitmap", "Bitmap cannot be null!"); int height = bitmap.Height; int width = bitmap.Width; GraphicsPath path = new GraphicsPath(); for (int j=0; j CloseBitmapLocation.X) && (mea.X < CloseBitmapLocation.X + CloseBitmapSize.Width) && (mea.Y > CloseBitmapLocation.Y) && (mea.Y < CloseBitmapLocation.Y + CloseBitmapSize.Height) && CloseClickable ) { if (!bIsMouseOverClose) { bIsMouseOverClose = true; bIsMouseOverTitle = false; bIsMouseOverContent = false; Cursor = Cursors.Hand; bContentModified = true; } } else if (RealContentRectangle.Contains(new Point(mea.X, mea.Y)) && ContentClickable) { if (!bIsMouseOverContent) { bIsMouseOverClose = false; bIsMouseOverTitle = false; bIsMouseOverContent = true; Cursor = Cursors.Hand; bContentModified = true; } } else if (RealTitleRectangle.Contains(new Point(mea.X, mea.Y)) && TitleClickable) { if (!bIsMouseOverTitle) { bIsMouseOverClose = false; bIsMouseOverTitle = true; bIsMouseOverContent = false; Cursor = Cursors.Hand; bContentModified = true; } } else { if (bIsMouseOverClose || bIsMouseOverTitle || bIsMouseOverContent) bContentModified = true; bIsMouseOverClose = false; bIsMouseOverTitle = false; bIsMouseOverContent = false; Cursor = Cursors.Default; } if (bContentModified) Refresh(); } protected override void OnMouseDown(MouseEventArgs mea) { base.OnMouseDown(mea); bIsMouseDown = true; if (bIsMouseOverClose) Refresh(); } protected override void OnMouseUp(MouseEventArgs mea) { base.OnMouseUp(mea); bIsMouseDown = false; if (bIsMouseOverClose) { Hide(); if (CloseClick != null) CloseClick(this, new EventArgs()); } else if (bIsMouseOverTitle) { if (TitleClick != null) TitleClick(this, new EventArgs()); } else if (bIsMouseOverContent) { if (ContentClick != null) ContentClick(this, new EventArgs()); } } protected override void OnPaintBackground(PaintEventArgs pea) { Graphics grfx = pea.Graphics; grfx.PageUnit = GraphicsUnit.Pixel; Graphics offScreenGraphics; Bitmap offscreenBitmap; offscreenBitmap = new Bitmap(BackgroundBitmap.Width, BackgroundBitmap.Height); offScreenGraphics = Graphics.FromImage(offscreenBitmap); if (BackgroundBitmap != null) { offScreenGraphics.DrawImage(BackgroundBitmap, 0, 0, BackgroundBitmap.Width, BackgroundBitmap.Height); } DrawCloseButton(offScreenGraphics); DrawText(offScreenGraphics); grfx.DrawImage(offscreenBitmap, 0, 0); } #endregion //Talált javítások protected override bool ShowWithoutActivation { get { return true; } } } }