using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
namespace JY.Inspection
{
public enum Logstype//枚举类型
{
Message,
Warning,
Error
}
///
/// 轻快型消息提示类
///
public static class MessageTip
{
static readonly Image _iconOk;
static readonly Image _iconWarning;
static readonly Image _iconError;
///
/// 全局停留时长(毫秒),影响后续弹出的tip。默认500
///
public static int DefaultDelay { get; set; }
///
/// 是否允许上浮动画。默认true
///
public static bool AllowFloating { get; set; }
static MessageTip()
{
DefaultDelay = 500;
AllowFloating = true;
Bitmap spriteImage;
using (var ms = new MemoryStream(Convert.FromBase64String(DefaultIconData)))
{
//不能直接用Img.FromMs得到的对象,怀疑因该方法得到的对象与源ms有瓜葛
//ms释放后会导致莫名问题,比如下面的Clone会引发内存不足异常
//而new Bitmap(Image)相当于基于Image重造了一个全新的bmp
spriteImage = new Bitmap(Image.FromStream(ms));
}
_iconOk = spriteImage.Clone(new Rectangle(0, 0, 32, 32), spriteImage.PixelFormat);
_iconWarning = spriteImage.Clone(new RectangleF(32, 0, 32, 32), spriteImage.PixelFormat);
_iconError = spriteImage.Clone(new RectangleF(64, 0, 32, 32), spriteImage.PixelFormat);
}
///
/// 显示良好消息,图标为绿勾 √
///
/// 消息文本
/// 消息停留时长(毫秒)。指定负数则使用 DefaultDelay
public static void ShowOk(string text = null, int delay = -1)
{
Show(text, _iconOk, Color.SeaGreen, Color.White, delay);
}
///
/// 显示警告消息,图标为黄色感叹号 !
///
/// 消息文本
/// 消息停留时长(毫秒)。指定负数则使用 DefaultDelay
public static void ShowWarning(string text = null, int delay = -1)
{
Show(text, _iconWarning, Color.DarkOrange, Color.Black, delay);
}
///
/// 显示出错消息,图标为红叉 X
///
/// 消息文本
/// 消息停留时长(毫秒)。指定负数则使用 DefaultDelay
public static void ShowError(string text = null, int delay = -1)
{
Show(text, _iconError, Color.Red, Color.White, delay);
}
///
/// 显示消息
///
/// 消息文本
/// 图标。不会进行缩放
/// 消息停留时长(毫秒)。指定负数则使用 DefaultDelay
public static void Show(string text, Image icon, Color bkColor, Color textColor, int delay = -1)
{
ThreadPool.QueueUserWorkItem(obj => new TipForm
{
TipText = text,
TipIcon = icon,
Delay = delay < 0 ? DefaultDelay : delay,
Floating = AllowFloating,
BkColor = bkColor,
TextColor= textColor,
BasePoint = Control.MousePosition //在鼠标点击的附近弹出
}.ShowDialog()); ;//要让创建浮动窗体的线程具有消息循环,所以要用ShowDialog
}
///
/// 内置图标数据:√ ! X
///
const string DefaultIconData = @"R0lGODlhYAAgANUAAOrcJ9LORebm5tJKShPLJLczM/z3s/XrkNfSOhS2JKaYMezeaMoREfhwcNS3
t7IREVSkWpWQZjCpPfz8+zS4RN3PZdTU1EjLWG9uaO/w7/Dke1HVYfHsx5UzM8Q8PLjYuqmmn8bl
yeO3txsbD+fck9DAUeDaVV1cHuHXMDGTOO3iSeHy4+BYWDvGTPn25O/hN5PIl8K1Pbfhu/z78nW/
fPb39lbeZ5/WpIAzM2HpcqITExGiIjV/N8S9luLbqf///yH5BAAAAAAALAAAAABgACAAAAb/wJ9w
SCwaj8ikcslsOp/QKFNUEEGpVqm2OQtUZlJqo+oUk7fHFUWmJWk0pKi4Mc4qxaw6uli7bNZRMxUG
BhUuT3gseWdIc4p6e0I0Fzk5EmxPboQHcU2Jiot2RZ+PjFs3LTk2G5aYTC6DBweFh0wFDaC5kERi
Ayy+v4oFeyEUNqsbrJdNmm8GcJ63A9PUA7s/VL/V0yymUWobNhfj4xsSTByxb7MVHNEN29xn2fG+
3lB9F+LkfstLFbMWaBAoq0KZWx4SJhzgoZuIbB4YLox4DwqNFuJaaGxxgQIMdIM0RMCAIYKGQu6a
OCjAQqHLAQUKSHSZsOKTG8YubNRIgUYT/4AHFpAkqaHghIMtPRRQuhAm06VQHSiRAQhJCAl/JCSQ
wJUChBogDQgcimHBggPtnqyEGbOt27c2hciQYMNfkRUSOu7Yu1fCVyYTAA5cMJKk2aJfEHVgC9et
UqlJqNowZlfIBAgULvDtK2FFEx+DzArFcCKCaLQ+rixVCpd1B1FG5k6mQNnVDxoUNmzewTUElxIH
BhMeMeJEiQBeFpQAo7YDa9YPdEiP+0M27evmMN2QQCNBgs0SbjgBHXSBCQQniJ9AjnxBhU4H2Uqf
L/21ErrXrydoIeHD1Q3e7eDdVh814QJwGpjAngLEKcBeeyWA5cli9FVYH2xEzPUHBS0MuP+fBClc
4KGA3B3FTAUaBICAigEocMIJCqy4ohcBwHeHczpEZyF99iGhIQUeetfCH0H6lYETByaIwJJLxvBi
DEwyaUIJtSThQAcFPBCdljl2uWV0PR7xQV4EDFhmAmWe6R0EnjlRQQULRLmkCW+cJ6eCBiUhApZa
9unnn312AJmYErRAwKFopplmAin45gQHJWgg56SUTpmSEVcyAKiWHXSwKaeDGjGmooeWemgKHzwR
mAkmoODqqygwOIICsL66Yp6j4KDpA7vuKuiVWu7KK6hJfJCCqcimUOCjJSxQ66vEEffsqyVcKoQD
umqqrbY4QJYprwxs+4CgxR6LLAEp+KT/agkmqAArANBG+yy8KARQgok/YBvuvvx2S4S+4PLLgL9I
GIvsDhDg+1kM7gLgMLwPR0BcBA8/jMLDMaQmRLYCh0vwvxx3jIMSBiMKwZGqxmDCCxW3rIIsKrTc
MgIxmKivyKGC3PHAOf8wQQ0ZZCAACObyYIEAQWdQw9ITNH2EDwzLLPXUFWc8xM37fnwE1h73/APQ
AlggNgg88NCD2EcLgLTSThtB6wsqvCD33HIDwDLLVDsc678dZO11EZl2jcTPQattuNpJK11D020T
MUEPCkQu+eSUV255DwrrS65Kum4eyRJNAy304aSXXrriTk8wOgg4gIB22okbjjbrICC9E/jnuEcR
+uiHB73076KT7rvTQQAAOw==";
///
/// 浮动消息层
///
private class TipForm : Form
{
///
/// 图标和文本之间的间距(像素)
///
const int IconTextSpacing = 3;
///
/// 基准点。用于指导本窗体显示位置
///
public Point BasePoint { get; set; }
///
/// 显示文字
///
string _tipText;
///
/// 背景色
///
Color _bkColor = Color.SeaGreen;
///
/// 文字颜色
///
Color _textColor=Color.Black;
///
/// 提示图标
///
public Image TipIcon { get; set; }
///
/// 提示文本
///
public string TipText
{
get { return _tipText ?? string.Empty; }
set { _tipText = value; }
}
///
/// 文字显示颜色
///
//[DefaultValue(500)]
public Color TextColor
{
get { return _textColor; }
set
{
_textColor = value;
this.ForeColor = _textColor;
}
}
///
/// 停留时长(毫秒)
///
[DefaultValue(500)]
public int Delay { get; set; }
///
/// 停留时长(毫秒)
///
//[DefaultValue(Color.White)]
public Color BkColor
{
get { return _bkColor; }
set
{
_bkColor = value;
this.BackColor = _bkColor;
}
}
///
/// 是否允许浮动
///
[DefaultValue(true)]
public bool Floating { get; set; }
//显示后不激活,即不抢焦点
protected override bool ShowWithoutActivation
{
get { return true; }
}
public TipForm()
{
//双缓冲。有必要
SetStyle(ControlStyles.UserPaint, true);
DoubleBuffered = true;
InitializeComponent();
Delay = 500;
Floating = true;
BkColor = Color.White;
this._timer.Tick += timer_Tick;
this.Load += TipForm_Load;
this.Shown += TipForm_Shown;
this.FormClosing += TipForm_FormClosing;
}
///
/// 根据图标和文字处理窗体尺寸
///
private void ProcessClientSize()
{
Size size = Size.Empty;
if (TipIcon != null)
{
size += TipIcon.Size;
}
if (TipText.Length != 0)
{
if (TipIcon != null)
{
size.Width += IconTextSpacing;//图标与文字的间距
}
var textSize = TextRenderer.MeasureText(TipText, this.Font);
size.Width += textSize.Width;
if (size.Height < textSize.Height) { size.Height = textSize.Height; }
}
this.ClientSize = size + Padding.Size;
}
private int x, y; //显示的坐标变量
///
/// 根据基准点处理窗体显示位置
///
private void ProcessLocation()
{
#region 弹窗显示在屏幕中间
this.y = (Screen.PrimaryScreen.Bounds.Height - 30 - this.Height) / 2;
this.x = (Screen.PrimaryScreen.Bounds.Width - 10 - this.Width) / 2;
this.Location = new Point(this.x, this.y);
#endregion
#region 弹窗显示在屏幕右下角
//this.x = Screen.PrimaryScreen.WorkingArea.Width - this.Width + 15;
//this.y = Screen.PrimaryScreen.WorkingArea.Height - this.Height * i - 5 * i;
//this.Location = new Point(this.x, this.y);
#endregion
#region 弹窗跟随鼠标位置
//var p = BasePoint;
//p.X -= Screen.PrimaryScreen.WorkingArea.Width - this.Width - 1000;//Screen.PrimaryScreen.WorkingArea.Width-this.Width / 2;
////横向处理。距离屏幕左右两边太近时的处理
//int screenWidth;
//if (p.X < 10)
//{
// p.X = 10;
//}
//else if (p.X + this.Width > (screenWidth = Screen.PrimaryScreen.Bounds.Width) - 10)
//{
// p.X = screenWidth - 10 - this.Width;
//}
////纵向处理。在鼠标上方显示
//p.Y -= this.Height + 20;
//this.Location = p;
#endregion
}
void TipForm_Load(object sender, EventArgs e)
{
ProcessClientSize();
ProcessLocation();
//上浮窗体动画。采用异步,以不阻塞透明渐变动画的进行
if (Floating)
{
ThreadPool.QueueUserWorkItem(obj =>
{
while (this.IsHandleCreated)
{
this.BeginInvoke(new Action