using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Windows.Forms; using WatchdogLib.Thread; using System.Timers; namespace WatchdogLib.WinForms { /// /// Wrapper Class around .Net NotifyIcon, to make it easier to work with an System Tray Icon. /// Instantiate the object and set ContextMenu or ContextMenuStrip in order to have a right click menu. /// Subscripe to the MouseLeftClick, and MouseLeftDoubleClick event to get accurate events to handle, /// Call Show()/Hide() to show/hide the System Tray Icon, respectively. /// public class SysTray { #region Public Properties public NotifyIcon trayNotify { get; private set; } public Icon Icon { get { return trayNotify.Icon; } set { trayNotify.Icon = value; } } public ContextMenu trayMenu { get { return trayNotify.ContextMenu; } set { trayNotify.ContextMenu = value; } } public ContextMenuStrip trayMenuStrip { get { return trayNotify.ContextMenuStrip; } set { trayNotify.ContextMenuStrip = value; } } public string toolTip { get { return trayNotify.Text; } set { trayNotify.Text = value; } } public bool Visible { get { return trayNotify.Visible; } } #endregion #region Public Events public delegate void SingleLeftMouseClick(MouseEventArgs e); /// /// Subscribe to get the Left Mouse Single Click Event /// public event SingleLeftMouseClick LeftMouseClick; public delegate void DoubleLeftMouseClick(MouseEventArgs e); /// /// Subscribe to get the Left Mouse Double Click Event /// public event DoubleLeftMouseClick LeftMouseDoubleClick; public delegate void RightMouseClick(MouseEventArgs e); /// /// Subscribe to get any Right Mouse Fired Event, use to redo context menu, if needed /// public event RightMouseClick RightMouseFired; #endregion #region Private Members private TTimer SingleClickDetectTimer = null; private TimeSpan _LastFiredEvent = new TimeSpan(DateTime.Now.Ticks); private const int _MILISECONDS_FOR_SINGLEMOUSE_CLICKEVENT_TOCOUNT = 500; private const int _N_SECONDS_TOIGNORE_NEXT_SIGNLEMOUSE_CLICKEVENT = 2; // to avoid tripple clicks, etc... (only sends one double click) /// /// Returns true if enough time since _LastFiredEvent has passed /// private bool EnoughTimeSinceLastEventHasElapsed { get { // 1 second is 10 Million ticks, one Milisecond is 10K return (DateTime.Now.Ticks - _LastFiredEvent.Ticks) >= (_N_SECONDS_TOIGNORE_NEXT_SIGNLEMOUSE_CLICKEVENT * 1000 * 10000); } } #endregion #region Construction /// /// Construct a System Tray Icon (use public properties like ContextMenu,Icon,toolTip to customize further) /// /// pass in an initial ToolTip to display, defaults to "" /// if null, defaults to systemIcons.Application //public SysTray(string toolTip = "", Icon icon = null) public SysTray(string toolTip, Icon icon) { // Create internal objects this.trayNotify = new NotifyIcon(); this.SingleClickDetectTimer = new TTimer(new ElapsedEventHandler(RealSingleClickDetectTimer_ElapsedEventHandler), _MILISECONDS_FOR_SINGLEMOUSE_CLICKEVENT_TOCOUNT, false, true); // Add Single / Double-Click Event Handlers trayNotify.Click += new EventHandler(trayNotify_Click); trayNotify.DoubleClick += new EventHandler(trayNotify_DoubleClick); trayNotify.MouseDown += new MouseEventHandler(trayNotify_MouseDown); // Set ToolTip if (!String.IsNullOrEmpty(toolTip)) this.toolTip = toolTip; // Set Icon if (icon == null) this.Icon = new Icon(SystemIcons.Application, 40, 40); else this.Icon = icon; } #endregion #region Click Event Handlers /// /// Called by NotifyIcon DoubleClick Event, We filter for only the left mouse double-click, /// event and fire event when neccessary /// /// /// private void trayNotify_DoubleClick(object sender, EventArgs e) { MouseEventArgs args = (MouseEventArgs)e; if (args.Button == MouseButtons.Left) { SingleClickDetectTimer.Stop(); if (LeftMouseDoubleClick != null && EnoughTimeSinceLastEventHasElapsed) { _LastFiredEvent = new TimeSpan(DateTime.Now.Ticks); LeftMouseDoubleClick(new MouseEventArgs(MouseButtons.Left, 2, 0, 0, 0)); } } } /// // Called by NotifyIcon Click Event, We filter for only the left mouse click, /// event and fire event when neccessary /// /// /// private void trayNotify_Click(object sender, EventArgs e) { MouseEventArgs args = (MouseEventArgs) e; if (args.Button == MouseButtons.Left && EnoughTimeSinceLastEventHasElapsed) SingleClickDetectTimer.Start(); // Start Single Click Detect Timer } /// /// In order to accurately re-do a context menu, we handle MouseDown for the /// Right-Mouse click. Mouse Down comes in before the click event, which gives /// the caller an opportunity to handle/recreate the context menu dynamically, if needed /// /// /// void trayNotify_MouseDown(object sender, MouseEventArgs e) { MouseEventArgs args = (MouseEventArgs)e; if (args.Button == MouseButtons.Right && (RightMouseFired != null)) RightMouseFired(args); } /// /// Used to detect ONLY Single Clicks, since a single-click and then a double-click fires, /// we want to ignore the first click,and first see if a double-click comes in, if so, ignore /// the single click, otherwise send it. (this is done by trayNotify_Click & transNotify_DoubleClick) /// /// /// private void RealSingleClickDetectTimer_ElapsedEventHandler(object sender, ElapsedEventArgs e) { SingleClickDetectTimer.Stop(); if (LeftMouseClick != null) { _LastFiredEvent = new TimeSpan(DateTime.Now.Ticks); LeftMouseClick(new MouseEventArgs(MouseButtons.Left, 1, 0, 0, 0)); } } #endregion #region Show N' Hide /// /// Show the System Tray Icon /// public void Show() { trayNotify.Visible = true; } /// /// Hide the System Tray Icon /// public void Hide() { trayNotify.Visible = false; } #endregion #region Public ShowBallon /// /// Pops up a Ballon over the System Tray Icon /// /// Specify the Timeout in Seconds //public void ShowBallon_Default(string BallonTipTitle, string BallonTipText, int nTimeoutInSeconds = 10) public void ShowBallon_Default(string BallonTipTitle, string BallonTipText, int nTimeoutInSeconds) { trayNotify.ShowBalloonTip((nTimeoutInSeconds * 1000), BallonTipTitle, BallonTipText, ToolTipIcon.None); } /// /// Pops up a Error Ballon over the System Tray Icon /// /// Specify the Timeout in Seconds //public void ShowBallon_Error(string BallonTipTitle, string BallonTipText, int nTimeoutInSeconds = 10) public void ShowBallon_Error(string BallonTipTitle, string BallonTipText, int nTimeoutInSeconds) { trayNotify.ShowBalloonTip((nTimeoutInSeconds * 1000), BallonTipTitle, BallonTipText, ToolTipIcon.Error); } /// /// Pops up a Warning Ballon over the System Tray Icon /// /// Specify the Timeout in Seconds //public void ShowBallon_Warning(string BallonTipTitle, string BallonTipText, int nTimeoutInSeconds = 10) public void ShowBallon_Warning(string BallonTipTitle, string BallonTipText, int nTimeoutInSeconds) { trayNotify.ShowBalloonTip((nTimeoutInSeconds * 1000), BallonTipTitle, BallonTipText, ToolTipIcon.Warning); } /// /// Pops up a Info Ballon over the System Tray Icon /// /// Specify the Timeout in Seconds //public void ShowBallon_Info(string BallonTipTitle, string BallonTipText, int nTimeoutInSeconds = 10) public void ShowBallon_Info(string BallonTipTitle, string BallonTipText, int nTimeoutInSeconds) { trayNotify.ShowBalloonTip((nTimeoutInSeconds * 1000), BallonTipTitle, BallonTipText, ToolTipIcon.Info); } #endregion } }