initial checkin of yaulw (locally)
This commit is contained in:
185
WinForms/ControlClickHelper.cs
Normal file
185
WinForms/ControlClickHelper.cs
Normal file
@@ -0,0 +1,185 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using Yaulw.Thread;
|
||||
using System.Timers;
|
||||
|
||||
namespace Yaulw.WinForms
|
||||
{
|
||||
/// <remarks>
|
||||
/// Initiate ControlClickHelper with a Control that you want to implement a Single/Double Mouse Click
|
||||
/// This Class helps you get accurate Single/Double Mouse Click Events
|
||||
/// </remarks>
|
||||
public class ControlClickHelper
|
||||
{
|
||||
#region Public Events
|
||||
|
||||
/// <summary>
|
||||
/// Single Mouse Click Delegate for subscribing to SingleMouseClick Events
|
||||
/// </summary>
|
||||
/// <param name="e">MouseEventArgs</param>
|
||||
public delegate void SingleMouseClick(MouseEventArgs e);
|
||||
|
||||
/// <summary>
|
||||
/// Double Mouse Click Delegate for subscribing to DoubleMouseClick Events
|
||||
/// </summary>
|
||||
/// <param name="e">MouseEventArgs</param>
|
||||
public delegate void DoubleMouseClick(MouseEventArgs e);
|
||||
|
||||
/// <summary>
|
||||
/// Left Mouse Click Event
|
||||
/// </summary>
|
||||
public event SingleMouseClick LeftMouseClick;
|
||||
|
||||
/// <summary>
|
||||
/// Right Mouse Click Event
|
||||
/// </summary>
|
||||
public event SingleMouseClick RightMouseClick;
|
||||
|
||||
/// <summary>
|
||||
/// Left Mouse Double Click Event
|
||||
/// </summary>
|
||||
public event DoubleMouseClick LeftMouseDoubleClick;
|
||||
|
||||
/// <summary>
|
||||
/// Right Mouse Double Click Event
|
||||
/// </summary>
|
||||
public event DoubleMouseClick RightMouseDoubleClick;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Members
|
||||
|
||||
private Control _Control = null;
|
||||
private TTimerDisp SingleLeftClickDetectTimer = null;
|
||||
private TTimerDisp SingleRightClickDetectTimer = null;
|
||||
private TimeSpan _LastFiredEvent = new TimeSpan(DateTime.Now.Ticks);
|
||||
private const int _MILISECONDS_FOR_SINGLEMOUSE_CLICKEVENT_TOCOUNT = 350;
|
||||
private const int _N_SECONDS_TOIGNORE_NEXT_SIGNLEMOUSE_CLICKEVENT = 2; // to avoid tripple clicks, etc... (only sends one double click)
|
||||
private MouseEventArgs _LeftClickEventArgs;
|
||||
private MouseEventArgs _RightClickEventArgs;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if enough time since _LastFiredEvent has passed
|
||||
/// </summary>
|
||||
private bool EnoughTimeSinceLastEventHasElapsed
|
||||
{
|
||||
get
|
||||
{
|
||||
return (DateTime.Now.Ticks - _LastFiredEvent.Ticks) >= (TimeSpan.FromSeconds(_N_SECONDS_TOIGNORE_NEXT_SIGNLEMOUSE_CLICKEVENT).Ticks);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
/// Initiate ControlClickHelper with a Control that you want to implement a Single/Double Mouse Click
|
||||
/// This Class helps you get accurate Single/Double Mouse Click Events
|
||||
/// </summary>
|
||||
/// <param name="control">a control for which you want to implement Single/Double Mouse Click</param>
|
||||
public ControlClickHelper(Control control)
|
||||
{
|
||||
this._Control = control;
|
||||
this.SingleLeftClickDetectTimer = new TTimerDisp(new ElapsedEventHandler(RealSingleLeftClickDetectTimer_ElapsedEventHandler), _MILISECONDS_FOR_SINGLEMOUSE_CLICKEVENT_TOCOUNT);
|
||||
this.SingleRightClickDetectTimer = new TTimerDisp(new ElapsedEventHandler(RealSingleRightClickDetectTimer_ElapsedEventHandler), _MILISECONDS_FOR_SINGLEMOUSE_CLICKEVENT_TOCOUNT);
|
||||
|
||||
// Add Event Handlers
|
||||
control.MouseClick += new MouseEventHandler(control_MouseClick);
|
||||
control.MouseDoubleClick += new MouseEventHandler(control_MouseDoubleClick);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Click Event Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Called by Control DoubleClick Event, We filter for only the left/right mouse double-click,
|
||||
/// event and fire event when neccessary
|
||||
/// </summary>
|
||||
/// <param name="sender">control</param>
|
||||
/// <param name="e">MouseEventArgs</param>
|
||||
private void control_MouseDoubleClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
MouseEventArgs args = (MouseEventArgs)e;
|
||||
if (args.Button == MouseButtons.Left)
|
||||
{
|
||||
SingleLeftClickDetectTimer.Stop();
|
||||
if (LeftMouseDoubleClick != null && EnoughTimeSinceLastEventHasElapsed)
|
||||
{
|
||||
_LastFiredEvent = new TimeSpan(DateTime.Now.Ticks);
|
||||
LeftMouseDoubleClick(new MouseEventArgs(MouseButtons.Left, 2, args.X, args.Y, args.Delta));
|
||||
}
|
||||
}
|
||||
else if (args.Button == MouseButtons.Right)
|
||||
{
|
||||
SingleRightClickDetectTimer.Stop();
|
||||
if (RightMouseDoubleClick != null && EnoughTimeSinceLastEventHasElapsed)
|
||||
{
|
||||
_LastFiredEvent = new TimeSpan(DateTime.Now.Ticks);
|
||||
RightMouseDoubleClick(new MouseEventArgs(MouseButtons.Right, 2, args.X, args.Y, args.Delta));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
// Called by NotifyIcon Click Event, We filter for only the left mouse click,
|
||||
/// event and fire event when neccessary
|
||||
/// </summary>
|
||||
/// <param name="sender">control</param>
|
||||
/// <param name="e">MouseEventArgs</param>
|
||||
private void control_MouseClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
MouseEventArgs args = (MouseEventArgs)e;
|
||||
if (args.Button == MouseButtons.Left && EnoughTimeSinceLastEventHasElapsed)
|
||||
{
|
||||
SingleLeftClickDetectTimer.Start(); // Start Single Click Detect Timer
|
||||
_LeftClickEventArgs = e;
|
||||
}
|
||||
else if (args.Button == MouseButtons.Right && EnoughTimeSinceLastEventHasElapsed)
|
||||
{
|
||||
SingleRightClickDetectTimer.Start(); // Start Single Click Detect Timer
|
||||
_RightClickEventArgs = e;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to detect ONLY Single Left 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.
|
||||
/// </summary>
|
||||
/// <param name="sender">control</param>
|
||||
/// <param name="e">MouseEventArgs</param>
|
||||
private void RealSingleLeftClickDetectTimer_ElapsedEventHandler(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
SingleLeftClickDetectTimer.Stop();
|
||||
if (LeftMouseClick != null)
|
||||
{
|
||||
_LastFiredEvent = new TimeSpan(DateTime.Now.Ticks);
|
||||
LeftMouseClick(new MouseEventArgs(MouseButtons.Right, 1, _LeftClickEventArgs.X, _LeftClickEventArgs.Y, _LeftClickEventArgs.Delta));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to detect ONLY Single Right 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.
|
||||
/// </summary>
|
||||
/// <param name="sender">control</param>
|
||||
/// <param name="e">MouseEventArgs</param>
|
||||
private void RealSingleRightClickDetectTimer_ElapsedEventHandler(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
SingleRightClickDetectTimer.Stop();
|
||||
if (RightMouseClick != null)
|
||||
{
|
||||
_LastFiredEvent = new TimeSpan(DateTime.Now.Ticks);
|
||||
RightMouseClick(new MouseEventArgs(MouseButtons.Right, 1, _RightClickEventArgs.X, _RightClickEventArgs.Y, _RightClickEventArgs.Delta));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
187
WinForms/MDIHelper.cs
Normal file
187
WinForms/MDIHelper.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Yaulw.WinForms
|
||||
{
|
||||
/// <remarks>
|
||||
/// Helper functions for WinForms MDI Layout
|
||||
/// </remarks>
|
||||
public static class MDIHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Use this function to retrive the actual MDIClient Object from
|
||||
/// an MDIContainer Form
|
||||
/// </summary>
|
||||
/// <param name="mdiFormContainer">Window form that is a valid MDIContainter</param>
|
||||
/// <returns>Valid MdiClient object if found, null otherwise</returns>
|
||||
public static MdiClient GetMDIClientObj(Form mdiFormContainer)
|
||||
{
|
||||
if (mdiFormContainer.IsMdiContainer)
|
||||
{
|
||||
for (int i = 0; i < mdiFormContainer.Controls.Count; ++i)
|
||||
{
|
||||
MdiClient mdiClient = mdiFormContainer.Controls[i] as MdiClient;
|
||||
if (mdiClient != null)
|
||||
return mdiClient;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes all MDI Children for the specified MDI Form Container
|
||||
/// </summary>
|
||||
/// <param name="mdiFormContainer">Window form that is a valid MDIContainter</param>
|
||||
public static void CloseAllChildWindows(Form mdiFormContainer)
|
||||
{
|
||||
if (mdiFormContainer.IsMdiContainer)
|
||||
{
|
||||
if (mdiFormContainer.MdiChildren.Length > 0)
|
||||
{
|
||||
Form[] form = mdiFormContainer.MdiChildren;
|
||||
foreach (Form f in form)
|
||||
{
|
||||
f.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the Child MDI Window Layout for the specified MDI Form Containter
|
||||
/// </summary>
|
||||
/// <param name="mdiFormContainter">Window form that is a valid MDIContainter</param>
|
||||
/// <param name="pLayout">Specify the MdiLaoyt to use</param>
|
||||
public static void HandleChildWindowsLayout(Form mdiFormContainer, MdiLayout pLayout)
|
||||
{
|
||||
if (!mdiFormContainer.IsMdiContainer)
|
||||
throw new InvalidOperationException("mdiFormContainter not and MDI Container");
|
||||
|
||||
// We don't handle Vertical * we are done *
|
||||
if (pLayout == MdiLayout.TileVertical)
|
||||
return;
|
||||
|
||||
// Arrange Icon works fine with MDI
|
||||
if (pLayout == MdiLayout.ArrangeIcons)
|
||||
{
|
||||
mdiFormContainer.LayoutMdi(pLayout);
|
||||
return;
|
||||
}
|
||||
|
||||
////
|
||||
// For Some Reason *YTBD* Cascade and Horizontal MDI Layout stopped working,
|
||||
// So now we just do the same logic manually and don't use the build in functions
|
||||
// provided by the MDI
|
||||
////
|
||||
if (pLayout == MdiLayout.Cascade)
|
||||
{
|
||||
// Incr. Consts
|
||||
const int N_INCR_TOP = 30;
|
||||
const int N_INCR_LEFT = 18;
|
||||
|
||||
Form ActiveMDI = mdiFormContainer.ActiveMdiChild;
|
||||
if (ActiveMDI != null)
|
||||
{
|
||||
int nTop = -1 * N_INCR_TOP;
|
||||
int nLeft = -1 * N_INCR_LEFT;
|
||||
|
||||
// By Default, Cascade windows increases the size of the Form
|
||||
// to a percentage of available with on the screen. any screen size > 800
|
||||
// width we'll use the calculated width
|
||||
MdiClient client = GetMDIClientObj(mdiFormContainer);
|
||||
int nCalculatedWidth = (client.Width / 100) * 80;
|
||||
int nCalculatedHeight = (client.Height / 100) * 60;
|
||||
|
||||
foreach (Form child in mdiFormContainer.MdiChildren)
|
||||
{
|
||||
if (child != ActiveMDI)
|
||||
{
|
||||
// Incr. nTop N' nLeft
|
||||
nTop = nTop + N_INCR_TOP;
|
||||
nLeft = nLeft + N_INCR_LEFT;
|
||||
|
||||
// Position Childe
|
||||
child.Top = nTop;
|
||||
child.Left = nLeft;
|
||||
child.Height = (nCalculatedHeight > child.MinimumSize.Height) ? nCalculatedHeight : child.MinimumSize.Height;
|
||||
child.Width = (nCalculatedWidth > child.MinimumSize.Width) ? nCalculatedWidth : child.MinimumSize.Width;
|
||||
child.Activate();
|
||||
}
|
||||
}
|
||||
|
||||
// Position Active MDI
|
||||
ActiveMDI.Top = nTop + N_INCR_TOP;
|
||||
ActiveMDI.Left = nLeft + N_INCR_LEFT;
|
||||
ActiveMDI.Height = (nCalculatedHeight > ActiveMDI.MinimumSize.Height) ? nCalculatedHeight : ActiveMDI.MinimumSize.Height;
|
||||
ActiveMDI.Width = (nCalculatedWidth > ActiveMDI.MinimumSize.Width) ? nCalculatedWidth : ActiveMDI.MinimumSize.Width;
|
||||
ActiveMDI.Activate();
|
||||
}
|
||||
}
|
||||
else if (pLayout == MdiLayout.TileHorizontal)
|
||||
{
|
||||
Form ActiveMDI = mdiFormContainer.ActiveMdiChild;
|
||||
if (ActiveMDI != null && mdiFormContainer.MdiChildren.Length > 1)
|
||||
{
|
||||
MdiClient client = GetMDIClientObj(mdiFormContainer);
|
||||
int nMaxHeight = client.Height;
|
||||
int nMaxWidth = client.Width;
|
||||
|
||||
// MDI Window Counts
|
||||
int nCount = mdiFormContainer.MdiChildren.Length;
|
||||
int nHalf = (nCount / 2);
|
||||
|
||||
// Position the first half of the Windows
|
||||
int nTop = 0;
|
||||
int nCalculatedHeight = nMaxHeight / nHalf;
|
||||
int nCalculatedWidth = (nMaxWidth / 2);
|
||||
for (int i = 0; i < nHalf; ++i)
|
||||
{
|
||||
Form child = mdiFormContainer.MdiChildren[i];
|
||||
|
||||
// Title the Window
|
||||
child.Top = nTop;
|
||||
child.Left = 0;
|
||||
|
||||
// Always set to Mins
|
||||
child.Height = (child.MinimumSize.Height < nCalculatedHeight) ? nCalculatedHeight : child.MinimumSize.Height;
|
||||
child.Width = (child.MinimumSize.Width < nCalculatedWidth) ? nCalculatedWidth : child.MinimumSize.Width;
|
||||
|
||||
// incr. nTop
|
||||
nTop = nTop + nCalculatedHeight;
|
||||
}
|
||||
|
||||
// Position the remaining half of the Windows
|
||||
nTop = 0;
|
||||
nCalculatedHeight = (nMaxHeight / (nCount - nHalf));
|
||||
for (int i = nHalf; i < nCount; ++i)
|
||||
{
|
||||
Form child = mdiFormContainer.MdiChildren[i];
|
||||
|
||||
// Title the Window
|
||||
child.Top = nTop;
|
||||
child.Left = nCalculatedWidth;
|
||||
|
||||
// Always set to Mins
|
||||
child.Height = (child.MinimumSize.Height < nCalculatedHeight) ? nCalculatedHeight : child.MinimumSize.Height;
|
||||
child.Width = (child.MinimumSize.Width < (nCalculatedWidth - 20)) ? (nCalculatedWidth - 20) : child.MinimumSize.Width;
|
||||
|
||||
// incr. nTop
|
||||
nTop = nTop + nCalculatedHeight;
|
||||
}
|
||||
}
|
||||
else if (ActiveMDI != null && mdiFormContainer.MdiChildren.Length == 1)
|
||||
{
|
||||
ActiveMDI.Top = 0;
|
||||
ActiveMDI.Left = 0;
|
||||
ActiveMDI.Height = ActiveMDI.MinimumSize.Height;
|
||||
ActiveMDI.Width = ActiveMDI.MinimumSize.Width;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
731
WinForms/MsgBox.cs
Normal file
731
WinForms/MsgBox.cs
Normal file
@@ -0,0 +1,731 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using Yaulw.Win32;
|
||||
using System.Drawing;
|
||||
using System.ComponentModel;
|
||||
using WPFWin = System.Windows;
|
||||
using WPFWinInterop = System.Windows.Interop;
|
||||
using Yaulw.Tools;
|
||||
|
||||
namespace Yaulw.WinForms
|
||||
{
|
||||
/// <remarks>
|
||||
/// MsgBox is a WindowsForms MessageBox that can be centered to the Parent
|
||||
/// </summary>
|
||||
public static class MsgBox
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Message Box Icon to use
|
||||
/// </summary>
|
||||
public static Icon DefaultTitleBarIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the max number of characters to show on each line
|
||||
/// </summary>
|
||||
public static uint MaxNumberOfCharactersPerLine { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// the default max number of characters on each line
|
||||
/// </summary>
|
||||
public const uint DefaultNumberOfCharactersPerLine = 62;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Header Properties
|
||||
|
||||
/// <summary>
|
||||
/// Get / Set to show a header in the Message Box
|
||||
/// </summary>
|
||||
public static bool ShowHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get / Set the Error Header
|
||||
/// </summary>
|
||||
public static string MsgBox_ErrorHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get / Set the Fatal Error Header
|
||||
/// </summary>
|
||||
public static string MsgBox_FatalErrorHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get / Set the Warning Header
|
||||
/// </summary>
|
||||
public static string MsgBox_WarningHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get / Set the Information Header
|
||||
/// </summary>
|
||||
public static string MsgBox_InfoHeader { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Footer Properties
|
||||
|
||||
/// <summary>
|
||||
/// Get / Set to show a footer in the Message Box
|
||||
/// </summary>
|
||||
public static bool ShowFooter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get / Set the Error Footer
|
||||
/// </summary>
|
||||
public static string MsgBox_ErrorFooter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get / Set the Fatal Error Footer
|
||||
/// </summary>
|
||||
public static string MsgBox_FatalErrorFooter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get / Set the Warning Footer
|
||||
/// </summary>
|
||||
public static string MsgBox_WarningFooter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get / Set the Information Footer
|
||||
/// </summary>
|
||||
public static string MsgBox_InfoFooter { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Title Header Properties
|
||||
|
||||
/// <summary>
|
||||
/// Get / Set to show a header in the Message Box Title
|
||||
/// </summary>
|
||||
public static bool ShowTitleHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get / Set the Error Title Header
|
||||
/// </summary>
|
||||
public static string MsgBox_ErrorTitleHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get / Set the Fatal Error Title Header
|
||||
/// </summary>
|
||||
public static string MsgBox_FatalErrorTitleHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get / Set the Warning Title Header
|
||||
/// </summary>
|
||||
public static string MsgBox_WarningTitleHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get / Set the Information Title Header
|
||||
/// </summary>
|
||||
public static string MsgBox_InfoTitleHeader { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
/// MsgBox Construction, ShowHeader, ShowFooter, ShowTitleHeader defaulted to true
|
||||
/// </summary>
|
||||
static MsgBox()
|
||||
{
|
||||
DefaultTitleBarIcon = null;
|
||||
MaxNumberOfCharactersPerLine = DefaultNumberOfCharactersPerLine;
|
||||
|
||||
// Header Init
|
||||
ShowHeader = true;
|
||||
ShowFooter = true;
|
||||
ShowTitleHeader = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Static Methods
|
||||
|
||||
/// <summary>
|
||||
/// Shows a custom Message Box (centered to parent), with the DefaultTitleBarIcon
|
||||
/// </summary>
|
||||
/// <param name="parent">Window To center Message Box Against</param>
|
||||
/// <param name="Title">Title to show</param>
|
||||
/// <param name="Text">Text to show</param>
|
||||
/// <param name="MsgBoxButtons">buttons to show</param>
|
||||
/// <param name="MsgBoxIcon">icon to show</param>
|
||||
/// <returns>the result of the Message Box</returns>
|
||||
public static DialogResult Show(WPFWin.Window parent, String Title, String Text, MessageBoxButtons MsgBoxButtons, MessageBoxIcon MsgBoxIcon)
|
||||
{
|
||||
if (parent != null)
|
||||
{
|
||||
WPFWinInterop.WindowInteropHelper interop = new WPFWinInterop.WindowInteropHelper(parent);
|
||||
if(interop.Handle != IntPtr.Zero)
|
||||
return Show(Yaulw.Win32.Convert.ConverthWndToIWin32Window(interop.Handle), Title, Text, MsgBoxButtons, MsgBoxIcon, DefaultTitleBarIcon);
|
||||
}
|
||||
return Show(Functions.GetDestopWindow(), Title, Text, MsgBoxButtons, MsgBoxIcon, DefaultTitleBarIcon);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows a custom Message Box (centered to parent), with the DefaultTitleBarIcon
|
||||
/// </summary>
|
||||
/// <param name="parent">Window To center Message Box Against</param>
|
||||
/// <param name="Title">Title to show</param>
|
||||
/// <param name="Text">Text to show</param>
|
||||
/// <param name="MsgBoxButtons">buttons to show</param>
|
||||
/// <param name="MsgBoxIcon">icon to show</param>
|
||||
/// <returns>the result of the Message Box</returns>
|
||||
public static DialogResult Show(IWin32Window parent, String Title, String Text, MessageBoxButtons MsgBoxButtons, MessageBoxIcon MsgBoxIcon)
|
||||
{
|
||||
return Show(parent, Title, Text, MsgBoxButtons, MsgBoxIcon, DefaultTitleBarIcon);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows a custom Message Box (centered to Desktop), with the DefaultTitleBarIcon
|
||||
/// </summary>
|
||||
/// <param name="Title">Title to show</param>
|
||||
/// <param name="Text">Text to show</param>
|
||||
/// <param name="MsgBoxButtons">buttons to show</param>
|
||||
/// <param name="MsgBoxIcon">icon to show</param>
|
||||
/// <returns>the result of the Message Box</returns>
|
||||
public static DialogResult Show(String Title, String Text, MessageBoxButtons MsgBoxButtons, MessageBoxIcon MsgBoxIcon)
|
||||
{
|
||||
return Show(Functions.GetDestopWindow(), Title, Text, MsgBoxButtons, MsgBoxIcon, DefaultTitleBarIcon);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Static Methods Extended
|
||||
|
||||
/// <summary>
|
||||
/// Shows Warning MessageBox (WPF)
|
||||
/// </summary>
|
||||
/// <param name="parent">Window To center Message Box Against</param>
|
||||
/// <param name="Title">Title to show</param>
|
||||
/// <param name="Text">Text to show</param>
|
||||
/// <param name="MsgBoxButtons">buttons to show</param>
|
||||
/// <param name="MsgBoxIcon">icon to show</param>
|
||||
/// <returns>the result of the Message Box</returns>
|
||||
public static DialogResult ShowWarning(WPFWin.Window parent, String Title, String Text, MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
{
|
||||
return Show(parent, Title, Text, MsgBoxButtons, MessageBoxIcon.Exclamation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Warning MessageBox (WinForms)
|
||||
/// </summary>
|
||||
/// <param name="parent">Window To center Message Box Against</param>
|
||||
/// <param name="Title">Title to show</param>
|
||||
/// <param name="Text">Text to show</param>
|
||||
/// <param name="MsgBoxButtons">buttons to show</param>
|
||||
/// <param name="MsgBoxIcon">icon to show</param>
|
||||
/// <returns>the result of the Message Box</returns>
|
||||
public static DialogResult ShowWarning(IWin32Window parent, String Title, String Text, MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
{
|
||||
return Show(parent, Title, Text, MsgBoxButtons, MessageBoxIcon.Exclamation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Warning MessageBox (Desktop)
|
||||
/// </summary>
|
||||
/// <param name="Title">Title to show</param>
|
||||
/// <param name="Text">Text to show</param>
|
||||
/// <param name="MsgBoxButtons">buttons to show</param>
|
||||
/// <param name="MsgBoxIcon">icon to show</param>
|
||||
/// <returns>the result of the Message Box</returns>
|
||||
public static DialogResult ShowWarning(String Title, String Text, MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
{
|
||||
return Show(Title, Text, MsgBoxButtons, MessageBoxIcon.Exclamation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Fatal Error MessageBox (WPF)
|
||||
/// </summary>
|
||||
/// <param name="parent">Window To center Message Box Against</param>
|
||||
/// <param name="Title">Title to show</param>
|
||||
/// <param name="Text">Text to show</param>
|
||||
/// <param name="MsgBoxButtons">buttons to show</param>
|
||||
/// <param name="MsgBoxIcon">icon to show</param>
|
||||
/// <returns>the result of the Message Box</returns>
|
||||
public static DialogResult ShowFatalError(WPFWin.Window parent, String Title, String Text, MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
{
|
||||
_ShowFatal = true;
|
||||
DialogResult dr = Show(parent, Title, Text, MsgBoxButtons, MessageBoxIcon.Error);
|
||||
_ShowFatal = false;
|
||||
return dr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Fatal Error MessageBox (WinForms)
|
||||
/// </summary>
|
||||
/// <param name="parent">Window To center Message Box Against</param>
|
||||
/// <param name="Title">Title to show</param>
|
||||
/// <param name="Text">Text to show</param>
|
||||
/// <param name="MsgBoxButtons">buttons to show</param>
|
||||
/// <param name="MsgBoxIcon">icon to show</param>
|
||||
/// <returns>the result of the Message Box</returns>
|
||||
public static DialogResult ShowFatalError(IWin32Window parent, String Title, String Text, MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
{
|
||||
_ShowFatal = true;
|
||||
DialogResult dr = Show(parent, Title, Text, MsgBoxButtons, MessageBoxIcon.Error);
|
||||
_ShowFatal = false;
|
||||
return dr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Fatal Error MessageBox (Desktop)
|
||||
/// </summary>
|
||||
/// <param name="Title">Title to show</param>
|
||||
/// <param name="Text">Text to show</param>
|
||||
/// <param name="MsgBoxButtons">buttons to show</param>
|
||||
/// <param name="MsgBoxIcon">icon to show</param>
|
||||
/// <returns>the result of the Message Box</returns>
|
||||
public static DialogResult ShowFatalError(String Title, String Text, MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
{
|
||||
_ShowFatal = true;
|
||||
DialogResult dr = Show(Title, Text, MsgBoxButtons, MessageBoxIcon.Error);
|
||||
_ShowFatal = false;
|
||||
return dr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Error MessageBox (WPF)
|
||||
/// </summary>
|
||||
/// <param name="parent">Window To center Message Box Against</param>
|
||||
/// <param name="Title">Title to show</param>
|
||||
/// <param name="Text">Text to show</param>
|
||||
/// <param name="MsgBoxButtons">buttons to show</param>
|
||||
/// <param name="MsgBoxIcon">icon to show</param>
|
||||
/// <returns>the result of the Message Box</returns>
|
||||
public static DialogResult ShowError(WPFWin.Window parent, String Title, String Text, MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
{
|
||||
return Show(parent, Title, Text, MsgBoxButtons, MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Error MessageBox (WinForms)
|
||||
/// </summary>
|
||||
/// <param name="parent">Window To center Message Box Against</param>
|
||||
/// <param name="Title">Title to show</param>
|
||||
/// <param name="Text">Text to show</param>
|
||||
/// <param name="MsgBoxButtons">buttons to show</param>
|
||||
/// <param name="MsgBoxIcon">icon to show</param>
|
||||
/// <returns>the result of the Message Box</returns>
|
||||
public static DialogResult ShowError(IWin32Window parent, String Title, String Text, MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
{
|
||||
return Show(parent, Title, Text, MsgBoxButtons, MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Error MessageBox (Desktop)
|
||||
/// </summary>
|
||||
/// <param name="Title">Title to show</param>
|
||||
/// <param name="Text">Text to show</param>
|
||||
/// <param name="MsgBoxButtons">buttons to show</param>
|
||||
/// <param name="MsgBoxIcon">icon to show</param>
|
||||
/// <returns>the result of the Message Box</returns>
|
||||
public static DialogResult ShowError(String Title, String Text, MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
{
|
||||
return Show(Title, Text, MsgBoxButtons, MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Information MessageBox (WPF)
|
||||
/// </summary>
|
||||
/// <param name="parent">Window To center Message Box Against</param>
|
||||
/// <param name="Title">Title to show</param>
|
||||
/// <param name="Text">Text to show</param>
|
||||
/// <param name="MsgBoxButtons">buttons to show</param>
|
||||
/// <param name="MsgBoxIcon">icon to show</param>
|
||||
/// <returns>the result of the Message Box</returns>
|
||||
public static DialogResult ShowInfo(WPFWin.Window parent, String Title, String Text, MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
{
|
||||
return Show(parent, Title, Text, MsgBoxButtons, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Information MessageBox (WinForms)
|
||||
/// </summary>
|
||||
/// <param name="parent">Window To center Message Box Against</param>
|
||||
/// <param name="Title">Title to show</param>
|
||||
/// <param name="Text">Text to show</param>
|
||||
/// <param name="MsgBoxButtons">buttons to show</param>
|
||||
/// <param name="MsgBoxIcon">icon to show</param>
|
||||
/// <returns>the result of the Message Box</returns>
|
||||
public static DialogResult ShowInfo(IWin32Window parent, String Title, String Text, MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
{
|
||||
return Show(parent, Title, Text, MsgBoxButtons, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows Information MessageBox (Desktop)
|
||||
/// </summary>
|
||||
/// <param name="Title">Title to show</param>
|
||||
/// <param name="Text">Text to show</param>
|
||||
/// <param name="MsgBoxButtons">buttons to show</param>
|
||||
/// <param name="MsgBoxIcon">icon to show</param>
|
||||
/// <returns>the result of the Message Box</returns>
|
||||
public static DialogResult ShowInfo(String Title, String Text, MessageBoxButtons MsgBoxButtons = MessageBoxButtons.OK)
|
||||
{
|
||||
return Show(Title, Text, MsgBoxButtons, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Static Members
|
||||
|
||||
private static User32.WindowsHookProc _hookProcDelegate = null;
|
||||
private static int _hHook = 0;
|
||||
private static string _title = null;
|
||||
private static string _msg = null;
|
||||
private static IntPtr _hIcon = IntPtr.Zero;
|
||||
private static bool _IsDesktopOwner = false;
|
||||
private static bool _ShowFatal = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Delegate to make All Message Boxes Thread-Safe
|
||||
/// </summary>
|
||||
private delegate DialogResult ShowMsgBoxDelegate(IWin32Window parent, String Title, String Text, MessageBoxButtons MsgBoxButtons, MessageBoxIcon MsgBoxIcon, Icon TitleBarIcon);
|
||||
|
||||
/// <summary>
|
||||
/// *Main MessageBox Show Function* allows you to center the Message Box to the Parent * Dispatcher Safe *
|
||||
/// </summary>
|
||||
/// <returns>Result of Dialog </returns>
|
||||
private static DialogResult Show(IWin32Window parent, String Title, String Text, MessageBoxButtons MsgBoxButtons, MessageBoxIcon MsgBoxIcon, Icon TitleBarIcon)
|
||||
{
|
||||
ISynchronizeInvoke InvokeObject = null;
|
||||
if (parent != null && parent is ISynchronizeInvoke)
|
||||
InvokeObject = (ISynchronizeInvoke)parent;
|
||||
|
||||
// Invoke if we need to * Make MessageBoxes generally Thread-safe *
|
||||
if ((InvokeObject != null) && InvokeObject.InvokeRequired)
|
||||
{
|
||||
DialogResult result = (DialogResult)InvokeObject.Invoke(new ShowMsgBoxDelegate(MsgBox.Show), new object[] { parent, Title, Text, MsgBoxButtons, MsgBoxIcon, TitleBarIcon });
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MsgBox.ShowInternal(parent, Text, Title, MsgBoxButtons, MsgBoxIcon, TitleBarIcon);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal Message Box Showing Function, responsible for showing the message box, setting the hook, etc
|
||||
/// </summary>
|
||||
/// <param name="owner">any IWin32Window</param>
|
||||
/// <param name="msg">message to show</param>
|
||||
/// <param name="title">title to show</param>
|
||||
/// <param name="btns">buttons to show</param>
|
||||
/// <param name="icon">messageboxicon</param>
|
||||
/// <param name="TitleBarIcon">Title bar Icon</param>
|
||||
/// <returns></returns>
|
||||
private static DialogResult ShowInternal(IWin32Window owner, string msg, string title, MessageBoxButtons btns, MessageBoxIcon icon, Icon TitleBarIcon)
|
||||
{
|
||||
// Create a callback delegate
|
||||
_hookProcDelegate = new User32.WindowsHookProc(HookCallback);
|
||||
|
||||
// Perform header/footer/title actions
|
||||
HeaderFooterTitleAction(ref msg, ref title, icon);
|
||||
|
||||
// Properly Format and Pad the Message
|
||||
MsgTextPaddingAndFormatting(ref msg);
|
||||
|
||||
// Remember the title & message that we'll look for.
|
||||
// The hook sees *all* windows, so we need to make sure we operate on the right one.
|
||||
_msg = msg;
|
||||
_title = title;
|
||||
|
||||
// if Owner is the Desktop Window
|
||||
_IsDesktopOwner = (owner.Handle == Functions.GetDestopWindow().Handle);
|
||||
|
||||
// Icon could not be present
|
||||
if (TitleBarIcon != null)
|
||||
_hIcon = TitleBarIcon.ToBitmap().GetHicon();
|
||||
else
|
||||
_hIcon = IntPtr.Zero;
|
||||
|
||||
// Set the hook.
|
||||
// Suppress "GetCurrentThreadId() is deprecated" warning.
|
||||
// It's documented that Thread.ManagedThreadId doesn't work with SetWindowsHookEx()
|
||||
#pragma warning disable 0618
|
||||
_hHook = User32.SetWindowsHookEx(Definitions.WH_CBT, _hookProcDelegate, IntPtr.Zero, AppDomain.GetCurrentThreadId());
|
||||
#pragma warning restore 0618
|
||||
|
||||
// Pop a standard MessageBox. The hook will center it.
|
||||
DialogResult rslt = DialogResult.None;
|
||||
if (_IsDesktopOwner)
|
||||
rslt = MessageBox.Show(_msg, _title, btns, icon);
|
||||
else
|
||||
rslt = MessageBox.Show(owner, _msg, _title, btns, icon);
|
||||
|
||||
// Release hook, clean up (may have already occurred)
|
||||
Unhook();
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Responsible for adding Header / Footer / Title Information
|
||||
/// </summary>
|
||||
/// <param name="msg">text to add header/footer for, if set</param>
|
||||
/// <param name="title">text to add title header for, if set</param>
|
||||
/// <param name="icon">Message Icon used in MessageBox</param>
|
||||
private static void HeaderFooterTitleAction(ref string msg, ref string title, MessageBoxIcon icon)
|
||||
{
|
||||
#region Header Action
|
||||
if (ShowHeader)
|
||||
{
|
||||
if (icon == MessageBoxIcon.Error && !String.IsNullOrEmpty(MsgBox_FatalErrorHeader) && _ShowFatal)
|
||||
msg = MsgBox_FatalErrorHeader + "\n\n" + msg;
|
||||
else if (icon == MessageBoxIcon.Error && !String.IsNullOrEmpty(MsgBox_ErrorHeader) && !_ShowFatal)
|
||||
msg = MsgBox_ErrorHeader + "\n\n" + msg;
|
||||
else if (icon == MessageBoxIcon.Exclamation && !String.IsNullOrEmpty(MsgBox_WarningHeader))
|
||||
msg = MsgBox_WarningHeader + "\n\n" + msg;
|
||||
else if (icon == MessageBoxIcon.Information && !String.IsNullOrEmpty(MsgBox_InfoHeader))
|
||||
msg = MsgBox_InfoHeader + "\n\n" + msg;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Footer Action
|
||||
if (ShowFooter)
|
||||
{
|
||||
if (icon == MessageBoxIcon.Error && !String.IsNullOrEmpty(MsgBox_FatalErrorFooter) && _ShowFatal)
|
||||
msg = msg + "\n\n" + MsgBox_FatalErrorFooter;
|
||||
else if (icon == MessageBoxIcon.Error && !String.IsNullOrEmpty(MsgBox_ErrorFooter) && !_ShowFatal)
|
||||
msg = msg + "\n\n" + MsgBox_ErrorFooter;
|
||||
else if (icon == MessageBoxIcon.Exclamation && !String.IsNullOrEmpty(MsgBox_WarningFooter))
|
||||
msg = msg + "\n\n" + MsgBox_WarningFooter;
|
||||
else if (icon == MessageBoxIcon.Information && !String.IsNullOrEmpty(MsgBox_InfoFooter))
|
||||
msg = msg + "\n\n" + MsgBox_InfoFooter;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Title Header
|
||||
if (ShowTitleHeader)
|
||||
{
|
||||
if (icon == MessageBoxIcon.Error && !String.IsNullOrEmpty(MsgBox_FatalErrorTitleHeader) && _ShowFatal)
|
||||
title = MsgBox_FatalErrorTitleHeader + ((!String.IsNullOrEmpty(title)) ? (" (" + title + ")") : "");
|
||||
else if (icon == MessageBoxIcon.Error && !String.IsNullOrEmpty(MsgBox_ErrorTitleHeader) && !_ShowFatal)
|
||||
title = MsgBox_ErrorTitleHeader + ((!String.IsNullOrEmpty(title)) ? (" (" + title + ")") : "");
|
||||
else if (icon == MessageBoxIcon.Exclamation && !String.IsNullOrEmpty(MsgBox_WarningTitleHeader))
|
||||
title = MsgBox_WarningTitleHeader + ((!String.IsNullOrEmpty(title)) ? (" (" + title + ")") : "");
|
||||
else if (icon == MessageBoxIcon.Information && !String.IsNullOrEmpty(MsgBox_InfoTitleHeader))
|
||||
title = MsgBox_InfoTitleHeader + ((!String.IsNullOrEmpty(title)) ? (" (" + title + ")") : "");
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform Message Text padding and Text Wrapping
|
||||
/// </summary>
|
||||
/// <param name="msg">the Padded and Text Wrapped Message</param>
|
||||
private static void MsgTextPaddingAndFormatting(ref string msg)
|
||||
{
|
||||
// Stripe last \n, if exists
|
||||
if (!String.IsNullOrEmpty(msg) && (msg.Length > 0) && (msg[msg.Length - 1] == '\n'))
|
||||
msg = msg.Remove(msg.Length - 1);
|
||||
|
||||
// Make sure the text looks good, by using padding
|
||||
if (!String.IsNullOrEmpty(msg) && (msg.Length > 0) && (msg.Length < MaxNumberOfCharactersPerLine))
|
||||
{
|
||||
string[] lines = msg.Split('\n');
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (string line in lines)
|
||||
{
|
||||
sb.Append(line.PadRight((int)MaxNumberOfCharactersPerLine));
|
||||
sb.Append("\n");
|
||||
}
|
||||
msg = sb.ToString();
|
||||
}
|
||||
else if (!String.IsNullOrEmpty(msg) && (msg.Length > 0) && (msg.Length > MaxNumberOfCharactersPerLine))
|
||||
{
|
||||
// Incredible and amazing Padding code
|
||||
string[] lines = msg.Split('\n');
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < lines.Length; ++i)
|
||||
{
|
||||
if (lines[i].Length < MaxNumberOfCharactersPerLine)
|
||||
{
|
||||
sb.Append(lines[i].PadRight((int)MaxNumberOfCharactersPerLine));
|
||||
sb.Append("\n");
|
||||
}
|
||||
else if (lines[i].Length == MaxNumberOfCharactersPerLine)
|
||||
{
|
||||
sb.Append(lines[i]);
|
||||
sb.Append("\n");
|
||||
}
|
||||
else if (lines[i].Length > MaxNumberOfCharactersPerLine)
|
||||
{
|
||||
// Split up all the SubLines into a List
|
||||
List<string> nSubLinesList = new List<string>();
|
||||
for (int j = 0; j < lines[i].Length; j = j + (int)MaxNumberOfCharactersPerLine)
|
||||
{
|
||||
string line = lines[i].Substring(j, ((lines[i].Length - j) > (int)MaxNumberOfCharactersPerLine) ? (int)MaxNumberOfCharactersPerLine : (lines[i].Length - j));
|
||||
nSubLinesList.Add(line);
|
||||
}
|
||||
|
||||
// Perform proper Text Wrapping on all Sub Lines
|
||||
for (int j = 0; j < nSubLinesList.Count; ++j)
|
||||
{
|
||||
string line1 = nSubLinesList[j];
|
||||
string line2 = (j + 1 < nSubLinesList.Count) ? nSubLinesList[j + 1] : String.Empty;
|
||||
if (!String.IsNullOrEmpty(line2))
|
||||
{
|
||||
if (StringTool.StringEndsWithLetter(line1) && StringTool.StringStartsWithLetter(line2))
|
||||
{
|
||||
string word1 = StringTool.StringFetchLastWord(line1);
|
||||
string word2 = StringTool.StringFetchFirstWord(line2);
|
||||
string word = word1 + word2;
|
||||
|
||||
// Use Text Wrapping to make sure word is wrapped correctly
|
||||
if (word.Length < (int)MaxNumberOfCharactersPerLine)
|
||||
{
|
||||
StringTool.StringStripeLastWord(ref line1);
|
||||
StringTool.StringStripeFirstWord(ref line2);
|
||||
|
||||
// Now perform the proper corrections to the actual list
|
||||
nSubLinesList[j] = line1.PadRight((int)MaxNumberOfCharactersPerLine);
|
||||
nSubLinesList[j + 1] = word + line2;
|
||||
|
||||
// Adjust lines
|
||||
string toMoveDown = "";
|
||||
for (int z = j + 1; z < nSubLinesList.Count; ++z)
|
||||
{
|
||||
// First Append the Move down
|
||||
if (!String.IsNullOrEmpty(toMoveDown))
|
||||
{
|
||||
nSubLinesList[z] = toMoveDown + nSubLinesList[z];
|
||||
toMoveDown = "";
|
||||
}
|
||||
|
||||
// Check Char Limit * make adjustment as needed *
|
||||
if (nSubLinesList[z].Length > MaxNumberOfCharactersPerLine)
|
||||
{
|
||||
toMoveDown = nSubLinesList[z].Substring((int)MaxNumberOfCharactersPerLine);
|
||||
nSubLinesList[z] = nSubLinesList[z].Substring(0, (int)MaxNumberOfCharactersPerLine);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the dangling Move Down as a new Line(s)
|
||||
if (!String.IsNullOrEmpty(toMoveDown))
|
||||
{
|
||||
for (int z = 0; z < toMoveDown.Length; z = z + (int)MaxNumberOfCharactersPerLine)
|
||||
{
|
||||
string line = toMoveDown.Substring(z, ((toMoveDown.Length - z) > (int)MaxNumberOfCharactersPerLine) ? (int)MaxNumberOfCharactersPerLine : (toMoveDown.Length - z));
|
||||
nSubLinesList.Add(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate all subLines and add them to the main list * Padded *
|
||||
foreach (string line in nSubLinesList)
|
||||
{
|
||||
if (line.Length == (int)MaxNumberOfCharactersPerLine)
|
||||
{
|
||||
sb.Append(line);
|
||||
sb.Append("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(line.PadRight((int)MaxNumberOfCharactersPerLine));
|
||||
sb.Append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write nicely formatted Message out
|
||||
msg = sb.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing, string is miracioulsy exactly correct
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unhook the User Window Hook
|
||||
/// </summary>
|
||||
private static void Unhook()
|
||||
{
|
||||
User32.UnhookWindowsHookEx(_hHook);
|
||||
_hHook = 0;
|
||||
_hookProcDelegate = null;
|
||||
_msg = null;
|
||||
_title = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback for the User Window Hook
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <param name="wParam">wParam Passed in</param>
|
||||
/// <param name="lParam">lParam Passed in</param>
|
||||
/// <returns>the result of the next hook in the chain</returns>
|
||||
private static int HookCallback(int code, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
int hHook = _hHook; // Local copy for CallNextHookEx() JIC we release _hHook
|
||||
|
||||
// Look for HCBT_ACTIVATE, *not* HCBT_CREATEWND:
|
||||
// child controls haven't yet been created upon HCBT_CREATEWND.
|
||||
if (code == Definitions.HCBT_ACTIVATE)
|
||||
{
|
||||
string cls = Functions.GetWindowClassName(wParam);
|
||||
if (cls == "#32770") // MessageBoxes are Dialog boxes
|
||||
{
|
||||
string title = Functions.GetWindowText(wParam);
|
||||
string msg = Functions.GetDlgItemText(wParam, 0xFFFF); // -1 aka IDC_STATIC
|
||||
if ((title == _title) && (msg == _msg))
|
||||
{
|
||||
// Only Center the Window, if the Owner is NOT the Desktop
|
||||
if (!_IsDesktopOwner)
|
||||
CenterWindowOnParent(wParam);
|
||||
|
||||
Unhook(); // Release hook - we've done what we needed
|
||||
|
||||
// Now we also want to set the Icon on the Dialog
|
||||
if (_hIcon != IntPtr.Zero)
|
||||
{
|
||||
User32.SendMessage(wParam, (int)Definitions.WM.WM_SETICON, (IntPtr)1, _hIcon);
|
||||
User32.SendMessage(wParam, (int)Definitions.WM.WM_SETICON, (IntPtr)0, _hIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return User32.CallNextHookEx(hHook, code, wParam, lParam);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Boilerplate window-centering code.
|
||||
/// Split out of HookCallback() for clarity.
|
||||
/// </summary>
|
||||
/// <param name="hChildWnd">handle of child window to center</param>
|
||||
private static void CenterWindowOnParent(IntPtr hChildWnd)
|
||||
{
|
||||
// Get child (MessageBox) size
|
||||
Structures.RECT rcChild = new Structures.RECT();
|
||||
User32.GetWindowRect(hChildWnd, out rcChild);
|
||||
int cxChild = rcChild.right - rcChild.left;
|
||||
int cyChild = rcChild.bottom - rcChild.top;
|
||||
|
||||
// Get parent (Form) size & location
|
||||
IntPtr hParent = User32.GetParent(hChildWnd);
|
||||
Structures.RECT rcParent = new Structures.RECT();
|
||||
User32.GetWindowRect(hParent, out rcParent);
|
||||
int cxParent = rcParent.right - rcParent.left;
|
||||
int cyParent = rcParent.bottom - rcParent.top;
|
||||
|
||||
// Center the MessageBox on the Form
|
||||
int x = rcParent.left + (cxParent - cxChild) / 2;
|
||||
int y = rcParent.top + (cyParent - cyChild) / 2;
|
||||
uint uFlags = 0x15; // SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE;
|
||||
User32.SetWindowPos(hChildWnd, IntPtr.Zero, x, y, 0, 0, uFlags);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
408
WinForms/SysTray.cs
Normal file
408
WinForms/SysTray.cs
Normal file
@@ -0,0 +1,408 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using Yaulw.Thread;
|
||||
using System.Timers;
|
||||
|
||||
namespace Yaulw.WinForms
|
||||
{
|
||||
/// <remarks>
|
||||
/// Wrapper Class around .Net NotifyIcon, to make it easier to work with an System Tray Icon.
|
||||
/// Use the InitializeContextMenu Callback to create the ContextMenu.
|
||||
/// Subscripe to the MouseLeftClick, and MouseLeftDoubleClick event to get accurate events to handle,
|
||||
/// Call Show()/Hide() to show/hide the System Tray Icon, respectively.
|
||||
/// </remarks>
|
||||
public class SysTray : IDisposable
|
||||
{
|
||||
#region Public States
|
||||
|
||||
/// <summary>
|
||||
/// Allow caller to specify multipe states to show for the tray icon
|
||||
/// </summary>
|
||||
public struct TrayState
|
||||
{
|
||||
string nameOfState;
|
||||
string toolTip;
|
||||
Icon icon;
|
||||
}
|
||||
|
||||
// keep track of added States
|
||||
private List<TrayState> _states = new List<TrayState>();
|
||||
|
||||
/// <summary>
|
||||
/// Add a possible state to the collection of tray icon states
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
public void AddState(TrayState state)
|
||||
{
|
||||
_states.Add(state);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the Icon to show on the System Tray Notification
|
||||
/// </summary>
|
||||
public Icon Icon { get { return trayNotify.Icon; } set { trayNotify.Icon = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set ToolTip to show over System Tray Notification
|
||||
/// </summary>
|
||||
public string toolTip { get { return trayNotify.Text; } set { trayNotify.Text = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Is System Tray Notification Visible?
|
||||
/// </summary>
|
||||
public bool IsVisible { get { return trayNotify.Visible; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private NotifyIcon trayNotify { get; set; }
|
||||
private ContextMenu trayMenu { get { return trayNotify.ContextMenu; } set { trayNotify.ContextMenu = value; } }
|
||||
private ContextMenuStrip trayMenuStrip { get { return trayNotify.ContextMenuStrip; } set { trayNotify.ContextMenuStrip = value; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Events
|
||||
|
||||
/// <summary>
|
||||
/// System Tray Left Mouse Click Delegate
|
||||
/// </summary>
|
||||
/// <param name="e">MouseEventArgs</param>
|
||||
public delegate void SingleLeftMouseClick(MouseEventArgs e);
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to get the Left Mouse Single Click Event
|
||||
/// </summary>
|
||||
public event SingleLeftMouseClick LeftMouseClick;
|
||||
|
||||
/// <summary>
|
||||
/// System Tray Left Mouse Double Click Delegate
|
||||
/// </summary>
|
||||
/// <param name="e">MouseEventArgs</param>
|
||||
public delegate void DoubleLeftMouseClick(MouseEventArgs e);
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to get the Left Mouse Double Click Event
|
||||
/// </summary>
|
||||
public event DoubleLeftMouseClick LeftMouseDoubleClick;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize Context Menu Dynamically Call-back * i.e. On every Right Click *
|
||||
/// Allows the Context Menu to change depending on application state
|
||||
/// </summary>
|
||||
/// <param name="trayMenuStrip">Expected a new ContextMenuStrip to Display</param>
|
||||
/// <param name="MenuClickEventHandler">Event Handle to handle Menu Click Events</param>
|
||||
public delegate void InitializeContextMenu(out ContextMenuStrip trayMenuStrip, out EventHandler MenuClickEventHandler);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Members
|
||||
|
||||
private InitializeContextMenu _ContextMenuInitializer = null;
|
||||
private TTimerDisp SingleClickDetectTimer = null;
|
||||
private TimeSpan _LastFiredEvent = new TimeSpan(DateTime.Now.Ticks);
|
||||
private const int _MILISECONDS_FOR_SINGLEMOUSE_CLICKEVENT_TOCOUNT = 350;
|
||||
private const int _N_SECONDS_TOIGNORE_NEXT_SIGNLEMOUSE_CLICKEVENT = 2; // to avoid tripple clicks, etc... (only sends one double click)
|
||||
private bool _disposed = false;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if enough time since _LastFiredEvent has passed
|
||||
/// </summary>
|
||||
private bool EnoughTimeSinceLastEventHasElapsed
|
||||
{
|
||||
get
|
||||
{
|
||||
return (DateTime.Now.Ticks - _LastFiredEvent.Ticks) >= (TimeSpan.FromSeconds(_N_SECONDS_TOIGNORE_NEXT_SIGNLEMOUSE_CLICKEVENT).Ticks);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
/// Construct a System Tray Icon (use public properties like ContextMenu,Icon,toolTip to customize further)
|
||||
/// </summary>
|
||||
/// <param name="ContextMenuInitializer">Callback to initialize the Context Menu (can't be null)</param>
|
||||
/// <param name="toolTip">pass in an initial ToolTip to display, defaults to ""</param>
|
||||
/// <param name="icon">if null, defaults to systemIcons.Application</param>
|
||||
public SysTray(InitializeContextMenu ContextMenuInitializer, string toolTip = "", Icon icon = null)
|
||||
{
|
||||
if (ContextMenuInitializer == null)
|
||||
throw new ArgumentNullException("ContextMenuInitializer can not be Null");
|
||||
|
||||
// Imp, in order to initialize the Context Menu Everytime it is needed
|
||||
_ContextMenuInitializer = ContextMenuInitializer;
|
||||
|
||||
// Create internal objects
|
||||
this.trayNotify = new NotifyIcon();
|
||||
this.SingleClickDetectTimer = new TTimerDisp(new ElapsedEventHandler(RealSingleClickDetectTimer_ElapsedEventHandler), _MILISECONDS_FOR_SINGLEMOUSE_CLICKEVENT_TOCOUNT);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizer
|
||||
/// </summary>
|
||||
~SysTray()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Click Event Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Called by NotifyIcon DoubleClick Event, We filter for only the left mouse double-click,
|
||||
/// event and fire event when neccessary
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
// Called by NotifyIcon Click Event, We filter for only the left mouse click,
|
||||
/// event and fire event when neccessary
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
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
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void trayNotify_MouseDown(object sender, MouseEventArgs e)
|
||||
{
|
||||
MouseEventArgs args = (MouseEventArgs)e;
|
||||
if (args.Button == MouseButtons.Right)
|
||||
{
|
||||
// Dynamically re-create Menu on every Right-Click
|
||||
InitializeContextMenuFromScratchUsingInitializer();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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)
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
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 Private Helpers
|
||||
|
||||
/// <summary>
|
||||
/// (Re)Initialize Context Menu from scratch, allows us to build different menu's
|
||||
/// depending on the application state * External Caller responsible for passing in
|
||||
/// the context Menu and Click Event Handler *
|
||||
/// </summary>
|
||||
private void InitializeContextMenuFromScratchUsingInitializer()
|
||||
{
|
||||
if (_ContextMenuInitializer != null)
|
||||
{
|
||||
ContextMenuStrip menuStrip = null;
|
||||
EventHandler clickHandler = null;
|
||||
|
||||
// Call Outside Caller's Initialize Context menu Function
|
||||
_ContextMenuInitializer(out menuStrip, out clickHandler);
|
||||
|
||||
// Set up the Click Event
|
||||
if (menuStrip != null && clickHandler != null)
|
||||
AssignClickEventHandlerToAllMenuItems(menuStrip, clickHandler);
|
||||
|
||||
// Assign New Context Menu
|
||||
trayMenuStrip = menuStrip;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls AssignClickEventHandlerToMenuItem() for each Root Menu Item
|
||||
/// </summary>
|
||||
/// <param name="menuStrip"></param>
|
||||
/// <param name="clickHandler"></param>
|
||||
private void AssignClickEventHandlerToAllMenuItems(ContextMenuStrip menuStrip, EventHandler clickHandler)
|
||||
{
|
||||
if (menuStrip != null)
|
||||
{
|
||||
foreach (ToolStripMenuItem item in menuStrip.Items.OfType<ToolStripMenuItem>())
|
||||
AssignClickEventHandlerToMenuItem(item, clickHandler);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive Function, in order to assign all MenuItems as well as
|
||||
/// all subsequent MenuItems, in the DropDownList, the ToolStripMI_Click
|
||||
/// event Handler
|
||||
/// </summary>
|
||||
/// <param name="item">pass in a ToolStripMenuItem to asign the click handler to</param>
|
||||
/// <param name="clickHandler"></param>
|
||||
private void AssignClickEventHandlerToMenuItem(ToolStripMenuItem item, EventHandler clickHandler)
|
||||
{
|
||||
if (item.DropDownItems == null || item.DropDownItems.Count == 0)
|
||||
{
|
||||
if(clickHandler != null)
|
||||
item.Click += clickHandler;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (ToolStripMenuItem _item in item.DropDownItems.OfType<ToolStripMenuItem>())
|
||||
AssignClickEventHandlerToMenuItem(_item, clickHandler);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Show N' Hide
|
||||
|
||||
/// <summary>
|
||||
/// Show the System Tray Icon
|
||||
/// </summary>
|
||||
public void Show()
|
||||
{
|
||||
// Create Context Menu
|
||||
InitializeContextMenuFromScratchUsingInitializer();
|
||||
trayNotify.Visible = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hide the System Tray Icon
|
||||
/// </summary>
|
||||
public void Hide()
|
||||
{
|
||||
trayNotify.Visible = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public ShowBallon
|
||||
|
||||
/// <summary>
|
||||
/// Type of Icon to show over Ballon
|
||||
/// </summary>
|
||||
public enum BallonIcon
|
||||
{
|
||||
None,
|
||||
Error,
|
||||
Warning,
|
||||
Info
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pops up a Ballon over the System Tray Icon
|
||||
/// </summary>
|
||||
/// <param name="BallonTipTitle">Title to show on the Ballon Tip</param>
|
||||
/// <param name="BallonTipText">Text to show on the Ballon Tip</param>
|
||||
/// <param name="tipIcon">Icon to show on the Ballon tip</param>
|
||||
/// <param name="nTimeoutInSeconds">Specify the Timeout in Seconds (System mininimum is 10 seconds)</param>
|
||||
public void ShowBallon(string BallonTipTitle, string BallonTipText, BallonIcon tipIcon = BallonIcon.None, int nTimeoutInSeconds = 10)
|
||||
{
|
||||
ToolTipIcon _tipIcon = ToolTipIcon.None;
|
||||
switch (tipIcon)
|
||||
{
|
||||
case BallonIcon.Error:
|
||||
_tipIcon = ToolTipIcon.Error;
|
||||
break;
|
||||
case BallonIcon.Info:
|
||||
_tipIcon = ToolTipIcon.Info;
|
||||
break;
|
||||
case BallonIcon.Warning:
|
||||
_tipIcon = ToolTipIcon.Warning;
|
||||
break;
|
||||
}
|
||||
trayNotify.ShowBalloonTip((int)TimeSpan.FromSeconds(nTimeoutInSeconds).TotalMilliseconds, BallonTipTitle, BallonTipText, _tipIcon);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
/// <summary>
|
||||
/// Dispose the Registry Handle
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
// Use SupressFinalize in case a subclass
|
||||
// of this type implements a finalizer
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose the Registry Handle
|
||||
/// </summary>
|
||||
/// <param name="disposing">true, if called from within</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (trayNotify != null)
|
||||
trayNotify.Dispose();
|
||||
}
|
||||
|
||||
// Indicate that the instance has been disposed.
|
||||
trayNotify = null;
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user