一、扩展弹窗
创建1个Form窗体,添加2个label(一个显示标题,一个显示消息内容),添加3个button
/// <summary>
/// 扩展弹窗
/// </summary>
public partial class MessageBoxEx : Form
{
private const int WM_SYSCOMMAND = 0x0112;//该变量表示将向Windows发送的消息类型
private const int SC_MOVE = 0xF010;//该变量表示发送消息的附加消息
private const int HTCAPTION = 0x0002;//该变量表示发送消息的附加消息
[DllImport("user32.dll")]//从当前线程中的窗口释放鼠标捕获(释放被当前线程中某个窗口捕获的光标),并恢复正常的鼠标输入处理
public static extern bool ReleaseCapture();
[DllImport("user32.dll")]//向指定的窗体发送Windows消息
public static extern bool SendMessage(IntPtr hwdn, int wMsg, int mParam, int lParam);
/// <summary>
///
/// </summary>
public MessageBoxEx()
{
InitializeComponent();
}
private MessageBoxButtons messageBoxButtons = MessageBoxButtons.OK;
/// <summary>
/// 显示
/// </summary>
/// <param name="mgs">内容</param>
/// <param name="title">标题</param>
/// <param name="buttons">显示的按钮</param>
/// <returns></returns>
public static DialogResult Show(string mgs, string title = "提示!", MessageBoxButtons buttons = MessageBoxButtons.OK)
{
MessageBoxEx messageBox = new MessageBoxEx();
messageBox.messageBoxButtons = buttons;
messageBox.ButtonShow(buttons);
messageBox.lbTitle.Text = title;
messageBox.lbMsg.Text = mgs;
messageBox.changeLabelFont(messageBox.lbTitle);
messageBox.changeLabelFont(messageBox.lbMsg);
return messageBox.ShowDialog();
}
/// <summary>
/// 显示
/// </summary>
/// <param name="mgs">内容</param>
/// <param name="title">标题</param>
/// <param name="text">按钮上显示的text,数组长度3,如:{"确定", "忽略", "取消"}</param>
/// <param name="buttons">显示的按钮</param>
/// <returns></returns>
public static DialogResult Show(string mgs, string title, string[] text, MessageBoxButtons buttons = MessageBoxButtons.OK)
{
MessageBoxEx messageBox = new MessageBoxEx();
messageBox.messageBoxButtons = buttons;
messageBox.ButtonShow(buttons, text);
messageBox.lbTitle.Text = title;
messageBox.lbMsg.Text = mgs;
messageBox.changeLabelFont(messageBox.lbTitle);
messageBox.changeLabelFont(messageBox.lbMsg);
return messageBox.ShowDialog();
}
/// <summary>
/// Label内字体随着字数的增加而自动减小,Label大小不变
/// </summary>
/// <param name="label"></param>
/// <returns></returns>
private Label changeLabelFont(Label label)
{
FontStyle fontStyle = FontStyle.Regular;
System.Drawing.FontFamily ff = new System.Drawing.FontFamily(label.Font.Name);
float size = 24F;
string content = label.Text;
label.Font = new Font(ff, size, fontStyle, GraphicsUnit.Point); //初始化label字体状态
while (true)
{
//获取当前一行能放多少个字======================================================
//1、获取label宽度
int labelwidth = label.Width;
//2、获取当前字体宽度
Graphics gh = label.CreateGraphics();
SizeF sf = gh.MeasureString("0", label.Font);
float fontwidth = sf.Width;
//3、得到一行放几个字
int OneRowFontNum = (int)((double)labelwidth / (double)fontwidth);
//判断当前的Label能放多少列======================================================
//1、获取当前字体的高度
float fontheight = sf.Height;
//2、获取当前label的高度
int labelheight = label.Height;
//3、得到当前label能放多少列
int ColNum = (int)((double)labelheight / (double)fontheight);
//获取当前字符串需要放多少列======================================================
var NeedColNum = Math.Ceiling((double)content.Length / (double)OneRowFontNum);
//如果超出范围,则缩小字体,然后返回再判断一次===================================
if (ColNum < NeedColNum)
{
size -= 0.25F;
label.Font = new Font(ff, size, fontStyle, GraphicsUnit.Point);
}
else
{
break;
}
}
return label;
}
private void ButtonShow(MessageBoxButtons buttons, bool disableAllButton = false)
{
if (disableAllButton)
{
btnNoRight.Visible = false;
btnYesLeft.Visible = false;
btnIgnoreMiddle.Visible = false;
return;
}
btnYesLeft.Font = new Font("微软雅黑", 27.75f, FontStyle.Bold);
btnIgnoreMiddle.Font = new Font("微软雅黑", 27.75f, FontStyle.Bold);
btnNoRight.Font = new Font("微软雅黑", 27.75f, FontStyle.Bold);
switch (buttons)
{
case MessageBoxButtons.AbortRetryIgnore:
btnNoRight.Visible = true;
btnYesLeft.Visible = true;
btnIgnoreMiddle.Visible = true;
btnNoRight.Text = "终止";
btnYesLeft.Text = "重试";
btnIgnoreMiddle.Text = "忽略";
break;
case MessageBoxButtons.OKCancel:
btnNoRight.Visible = true;
btnYesLeft.Visible = true;
btnIgnoreMiddle.Visible = false;
btnNoRight.Text = "取消";
btnYesLeft.Text = "确定";
btnIgnoreMiddle.Text = "忽略";
break;
case MessageBoxButtons.RetryCancel:
btnNoRight.Visible = true;
btnYesLeft.Visible = true;
btnIgnoreMiddle.Visible = false;
btnNoRight.Text = "取消";
btnYesLeft.Text = "重试";
btnIgnoreMiddle.Text = "忽略";
break;
case MessageBoxButtons.YesNo:
btnNoRight.Visible = true;
btnYesLeft.Visible = true;
btnIgnoreMiddle.Visible = false;
btnNoRight.Text = "退出";
btnYesLeft.Text = "继续";
btnIgnoreMiddle.Text = "忽略";
break;
case MessageBoxButtons.YesNoCancel:
btnNoRight.Visible = true;
btnYesLeft.Visible = true;
btnIgnoreMiddle.Visible = true;
btnNoRight.Text = "否";
btnYesLeft.Text = "是";
btnIgnoreMiddle.Text = "取消";
break;
default:
btnNoRight.Visible = false;
btnYesLeft.Visible = true;
btnIgnoreMiddle.Visible = false;
btnNoRight.Text = "取消";
btnYesLeft.Text = "确定";
btnIgnoreMiddle.Text = "忽略";
break;
}
}
private void ButtonShow(MessageBoxButtons buttons, string[] text)
{
if (text.Length != 3)
{
text = new string[] { "确定", "忽略", "取消" };
}
btnYesLeft.Visible = true;
btnNoRight.Visible = true;
btnYesLeft.Font = new Font("微软雅黑", 27.75f, FontStyle.Bold);
btnIgnoreMiddle.Font = new Font("微软雅黑", 27.75f, FontStyle.Bold);
btnNoRight.Font = new Font("微软雅黑", 27.75f, FontStyle.Bold);
switch (buttons)
{
case MessageBoxButtons.AbortRetryIgnore:
btnIgnoreMiddle.Visible = true;
break;
case MessageBoxButtons.OKCancel:
btnIgnoreMiddle.Visible = false;
break;
case MessageBoxButtons.RetryCancel:
btnIgnoreMiddle.Visible = false;
break;
case MessageBoxButtons.YesNo:
btnIgnoreMiddle.Visible = false;
break;
case MessageBoxButtons.YesNoCancel:
btnIgnoreMiddle.Visible = true;
break;
default:
btnNoRight.Visible = false;
btnIgnoreMiddle.Visible = false;
break;
}
btnNoRight.Text = text[2];
btnYesLeft.Text = text[0];
btnIgnoreMiddle.Text = text[1];
if (text[0].Length >= 3)
{
btnYesLeft.Font = new Font("微软雅黑", 15.75f, FontStyle.Bold);
}
if (text[1].Length >= 3)
{
btnIgnoreMiddle.Font = new Font("微软雅黑", 15.75f, FontStyle.Bold);
}
if (text[2].Length >= 3)
{
btnNoRight.Font = new Font("微软雅黑", 15.75f, FontStyle.Bold);
}
}
private void ButtonResult(object sender, MessageBoxButtons buttons = MessageBoxButtons.OK)
{
Button btn = (Button)sender;
switch (buttons)
{
case MessageBoxButtons.AbortRetryIgnore:
if (btn.Name == "btnNoRight")
{
this.DialogResult = DialogResult.Abort;
}
else if (btn.Name == "btnYesLeft")
{
this.DialogResult = DialogResult.Retry;
}
else
{
this.DialogResult = DialogResult.Ignore;
}
break;
case MessageBoxButtons.OKCancel:
if (btn.Name == "btnNoRight")
{
this.DialogResult = DialogResult.Cancel;
}
else if (btn.Name == "btnYesLeft")
{
this.DialogResult = DialogResult.OK;
}
else
{
this.DialogResult = DialogResult.Ignore;
}
break;
case MessageBoxButtons.RetryCancel:
if (btn.Name == "btnNoRight")
{
this.DialogResult = DialogResult.Cancel;
}
else if (btn.Name == "btnYesLeft")
{
this.DialogResult = DialogResult.Retry;
}
else
{
this.DialogResult = DialogResult.Ignore;
}
break;
case MessageBoxButtons.YesNo:
if (btn.Name == "btnNoRight")
{
this.DialogResult = DialogResult.No;
}
else if (btn.Name == "btnYesLeft")
{
this.DialogResult = DialogResult.Yes;
}
else
{
this.DialogResult = DialogResult.Ignore;
}
break;
case MessageBoxButtons.YesNoCancel:
if (btn.Name == "btnNoRight")
{
this.DialogResult = DialogResult.No;
}
else if (btn.Name == "btnYesLeft")
{
this.DialogResult = DialogResult.Yes;
}
else
{
this.DialogResult = DialogResult.Cancel;
}
break;
default:
if (btn.Name == "btnNoRight")
{
this.DialogResult = DialogResult.Cancel;
}
else if (btn.Name == "btnYesLeft")
{
this.DialogResult = DialogResult.OK;
}
else
{
this.DialogResult = DialogResult.Ignore;
}
break;
}
}
private void btnYesLeft_Click(object sender, EventArgs e)
{
ButtonResult(sender, messageBoxButtons);
this.Dispose();
}
private void btnIgnoreMiddle_Click(object sender, EventArgs e)
{
ButtonResult(sender, messageBoxButtons);
this.Dispose();
}
private void btnNoRight_Click(object sender, EventArgs e)
{
ButtonResult(sender, messageBoxButtons);
this.Dispose();
}
private void MessageBoxEx_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)//左键按下移动,拖拽调整大小
{
// MousePosition的参考点是屏幕的左上角,表示鼠标当前相对于屏幕左上角的坐标。this.Left和this.Top的参考点也是屏幕
if (Cursor == Cursors.SizeNWSE) // 倾斜拖拽
{
// 改变窗体宽和高的代码,其宽高为鼠标屏幕位置减去窗体的Left,Top距离
this.Width = MousePosition.X - this.Left;
this.Height = MousePosition.Y - this.Top;
}
else if (Cursor == Cursors.SizeWE) // 水平拖拽
{
Width = MousePosition.X - this.Left;
}
else if (Cursor == Cursors.SizeNS) // 垂直拖拽
{
Height = MousePosition.Y - this.Top;
}
}
int maxPixels = 10;
//鼠标移动过程中,坐标时刻在改变
//当鼠标移动时横坐标距离窗体右边缘5像素以内且纵坐标距离下边缘也在5像素以内时,要将光标变为倾斜的箭头形状
if (e.Location.X > this.Width - maxPixels && e.Location.Y > this.Height - maxPixels)
{
this.Cursor = Cursors.SizeNWSE; // 右下角 双向对角线光标
}
//当鼠标移动时横坐标距离窗体右边缘5像素以内时,要将光标变为双向水平箭头形状
else if (e.Location.X > this.Width - maxPixels)
{
this.Cursor = Cursors.SizeWE; // 双向水平光标
}
//当鼠标移动时纵坐标距离窗体下边缘5像素以内时,要将光标变为垂直水平箭头形状
else if (e.Location.Y > this.Height - maxPixels)
{
this.Cursor = Cursors.SizeNS; // 双向垂直光标
}
else//否则,以外的窗体区域,鼠标星座均为单向箭头(默认)
{
this.Cursor = Cursors.Arrow;
if (e.Button == MouseButtons.Left)
{
ReleaseCapture(); // 释放鼠标捕获
// 向Windows发送拖动窗体的消息,下面的消息仅在左键按下时有效
SendMessage(this.Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
}
}
}
protected override void WndProc(ref Message m)
{
const int WM_NCHITTEST = 0x84;
const int HTCLIENT = 0x01;
const int HTCAPTION = 0x02;
if (m.Msg == WM_NCHITTEST)
{
this.DefWndProc(ref m);
if (m.Result.ToInt32() == HTCLIENT)
m.Result = new IntPtr(HTCAPTION);
else
base.WndProc(ref m);
}
else
{
base.WndProc(ref m);
}
}
}
二、气泡弹窗
创建1个Form窗体,添加2个label(一个显示标题,一个显示消息内容),添加1个button
/// <summary>
/// 报警、提示弹窗
/// </summary>
public partial class FrmMessage : Form
{
/// <summary>
/// 窗口显示报警和提示 弹窗委
/// </summary>
/// <param name="msg"></param>
/// <param name="isAlarm"></param>
/// <param name="title"></param>
/// <param name="isFlash"></param>
/// <param name="wait"></param>
private delegate void FromShowAlarmInfo(string msg, bool isAlarm, string title, bool isFlash, int wait);
/// <summary>
/// 窗口显示报警和提示 弹窗事件
/// </summary>
private static event FromShowAlarmInfo EventFromShowAlarmInfo;
private static Form mainFrm;
bool isAlarm_m = false;
//private static void CreateFrmMessage()
//{
// bool bCreate = false;
// if (mainFrm == null)
// {
// //在主窗口线程上创建 mainFrm 对象
// FormCollection forms = Application.OpenForms;
// foreach (Form item in forms)
// {
// if (item.Name.ToUpper().Contains("MAIN"))
// {
// bCreate = true;
// item.Invoke((MethodInvoker)delegate
// {
// mainFrm = new Form();
// mainFrm.Load += new System.EventHandler(mainFrm_Load);
// mainFrm.Show();
// mainFrm.Hide();
// });
// break;
// }
// }
// if (!bCreate)
// {
// forms[0].Invoke((MethodInvoker)delegate//如果没有main名称的窗口,则在第1个窗口线程上创建 mainFrm 对象
// {
// mainFrm = new Form();
// mainFrm.Load += new System.EventHandler(mainFrm_Load);
// mainFrm.Show();
// mainFrm.Hide();
// });
// }
// }
//}
/// <summary>
/// 报警弹窗不卡流程,需手动关闭;
/// </summary>
/// <param name="msg">信息</param>
/// <param name="title">标题 - 报警弹窗才有效</param>
public static void ShowAlarm(string msg, string title = "报警!")
{
//EventFromShowAlarmInfo?.Invoke(msg, true, title, true, 3);
ShowAlarmFunction(msg, true, title, true, 3);
}
/// <summary>
/// 信息弹窗不卡流程,需手动关闭
/// </summary>
/// <param name="msg">信息</param>
/// <param name="title">标题</param>
public static void ShowInfo(string msg, string title = "提示!")
{
//if (mainFrm == null)
//{
// mainFrm = new Form();
// mainFrm.Load += new System.EventHandler(mainFrm_Load);
// mainFrm.Show();
// mainFrm.Hide();
//}
//EventFromShowAlarmInfo?.Invoke(msg, true, title, false, 3);
ShowAlarmFunction(msg, true, title, false, 3);
}
/// <summary>
/// 信息弹窗不卡流程,自动关闭
/// </summary>
/// <param name="msg">信息</param>
/// <param name="wait">等待关闭时间S</param>
public static void ShowMsg(string msg, int wait = 3)
{
ShowAlarmFunction(msg, false, "", false, wait);
}
private static void mainFrm_Load(object sender, EventArgs e)
{
//在主界面注册事件,显示弹窗,如果其他线程显示时,其他线程关闭后,弹窗也一起被关闭
//EventFromShowAlarmInfo += ShowAlarmFunction;
}
/// <summary>
///
/// </summary>
/// <param name="msg">显示的消息</param>
/// <param name="isManualClose">是否需手动关闭弹窗</param>
/// <param name="title">标题</param>
/// <param name="isFlash">背景色闪烁</param>
/// <param name="wait">不需要手动关闭时,关闭等待的时间S</param>
private static void ShowAlarmFunction(string msg, bool isManualClose, string title = "报警!", bool isFlash = true, int wait = 3)
{
//在进程的 Form 对象
FormCollection forms = Application.OpenForms;
Form formShow = forms[0];
foreach (Form item in forms)
{
if (item.Name.ToUpper().Contains("MAIN"))
{
formShow = item;
break;
}
}
if (formShow != null)
{
//在窗口线程显示弹窗,如果其他线程显示时,其他线程关闭后,弹窗也一起被关闭,且调用的线程阻塞,弹窗显示会卡住
formShow.BeginInvoke((MethodInvoker)delegate
{
FrmMessage frmMessage = new FrmMessage(msg, isManualClose, title, isFlash);
frmMessage.Show();
frmMessage.TopMost = true;
Task.Run(delegate
{
if (isManualClose)
{
ConfigFileMgr.Instance.SaveAlarmMsg(msg);
if (isFlash)
{
do
{
Thread.Sleep(500);
frmMessage.lbMsg.BackColor = Color.OrangeRed;
Thread.Sleep(500);
frmMessage.lbMsg.BackColor = Color.MediumVioletRed;
if (frmMessage.IsDisposed)
{
break;
}
} while (true);
}
}
else
{
ConfigFileMgr.Instance.SaveLogInfo(msg);
DateTime start = DateTime.Now;
do
{
Thread.Sleep(10);
if (DateTime.Now.Subtract(start).TotalSeconds > wait)
{
if (frmMessage != null && !frmMessage.IsDisposed)
{
frmMessage.BeginInvoke((MethodInvoker)delegate
{
frmMessage.Close();
frmMessage.Dispose();
});
}
break;
}
} while (true);
}
});
});
}
}
/// <summary>
///
/// </summary>
/// <param name="msg">显示消息</param>
/// <param name="isAlarm">是否为报警</param>
/// <param name="title">标题</param>
/// <param name="isFlash">是否闪烁,即变更文本背景色</param>
private FrmMessage(string msg, bool isAlarm, string title = "报警!", bool isFlash = true)
{
InitializeComponent();
isAlarm_m = isAlarm;
lbMsg.Text = msg;
if (!isAlarm)
{
btnCloseForm.Visible = false;
panel1.Visible = false;
this.Size = new Size(910, 100);
panel2.Location = new Point(5, 5);
panel2.Size = new Size(900, 90);
}
else
{
lbTitle.Text = title;
if (isFlash)
{
lbTitle.BackColor = Color.Tomato;
btnCloseForm.BackColor = Color.Tomato;
lbMsg.BackColor = Color.MediumVioletRed;
}
}
}
private void btnCloseForm_Click(object sender, EventArgs e)
{
Close();
Dispose();
}
/// <summary>
/// 重写WndProc方法,当窗体属性FormBorderStyle.None时,也可以拖动
/// </summary>
/// <param name="m"></param>
protected override void WndProc(ref Message m)
{
const int WM_NCHITTEST = 0x84;
const int HTCLIENT = 0x01;
const int HTCAPTION = 0x02;
if (m.Msg == WM_NCHITTEST)
{
this.DefWndProc(ref m);
if (m.Result.ToInt32() == HTCLIENT)
m.Result = new IntPtr(HTCAPTION);
else
base.WndProc(ref m);
}
else
{
base.WndProc(ref m);
}
}
/// <summary>
/// Label内字体随着字数的增加而自动减小,Label大小不变
/// </summary>
/// <param name="label"></param>
/// <returns></returns>
private Label changeLabelFont(Label label)
{
FontStyle fontStyle = FontStyle.Regular;
System.Drawing.FontFamily ff = new System.Drawing.FontFamily(label.Font.Name);
float size = 24F;
string content = label.Text;
label.Font = new Font(ff, size, fontStyle, GraphicsUnit.Point); //初始化label字体状态
while (true)
{
//获取当前一行能放多少个字======================================================
//1、获取label宽度
int labelwidth = label.Width;
//2、获取当前字体宽度
Graphics gh = label.CreateGraphics();
SizeF sf = gh.MeasureString("0", label.Font);
float fontwidth = sf.Width;
//3、得到一行放几个字
int OneRowFontNum = (int)((double)labelwidth / (double)fontwidth);
//判断当前的Label能放多少列======================================================
//1、获取当前字体的高度
float fontheight = sf.Height;
//2、获取当前label的高度
int labelheight = label.Height;
//3、得到当前label能放多少列
int ColNum = (int)((double)labelheight / (double)fontheight);
//获取当前字符串需要放多少列======================================================
var NeedColNum = Math.Ceiling((double)content.Length / (double)OneRowFontNum);
//如果超出范围,则缩小字体,然后返回再判断一次===================================
if (ColNum < NeedColNum)
{
size -= 0.25F;
label.Font = new Font(ff, size, fontStyle, GraphicsUnit.Point);
}
else
{
break;
}
}
return label;
}
private void FrmMessage_Load(object sender, EventArgs e)
{
changeLabelFont(lbTitle);
changeLabelFont(lbMsg);
int width = (Screen.PrimaryScreen.Bounds.Width - Width) / 2;
int height = isAlarm_m ? 80 : 0;
Location = new Point(width, height);//显示在屏幕顶部中间位置
}
private void lbMsg_MouseDoubleClick(object sender, MouseEventArgs e)
{
Close();
Dispose();
}
}
public class User32API
{
private static Hashtable processWnd = null;
public delegate bool WNDENUMPROC(IntPtr hwnd, uint lParam);
static User32API()
{
if (processWnd == null)
{
processWnd = new Hashtable();
}
}
[DllImport("user32.dll", EntryPoint = "EnumWindows", SetLastError = true)]
public static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, uint lParam);
[DllImport("user32.dll", EntryPoint = "GetParent", SetLastError = true)]
public static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, ref uint lpdwProcessId);
[DllImport("user32.dll", EntryPoint = "IsWindow")]
public static extern bool IsWindow(IntPtr hWnd);
[DllImport("kernel32.dll", EntryPoint = "SetLastError")]
public static extern void SetLastError(uint dwErrCode);
public static IntPtr GetCurrentWindowHandle()
{
IntPtr ptrWnd = IntPtr.Zero;
uint uiPid = (uint)Process.GetCurrentProcess().Id; // 当前进程 ID
object objWnd = processWnd[uiPid];
if (objWnd != null)
{
ptrWnd = (IntPtr)objWnd;
if (ptrWnd != IntPtr.Zero && IsWindow(ptrWnd)) // 从缓存中获取句柄
{
return ptrWnd;
}
else
{
ptrWnd = IntPtr.Zero;
}
}
bool bResult = EnumWindows(new WNDENUMPROC(EnumWindowsProc), uiPid);
// 枚举窗口返回 false 并且没有错误号时表明获取成功
if (!bResult && Marshal.GetLastWin32Error() == 0)
{
objWnd = processWnd[uiPid];
if (objWnd != null)
{
ptrWnd = (IntPtr)objWnd;
}
}
return ptrWnd;
}
private static bool EnumWindowsProc(IntPtr hwnd, uint lParam)
{
uint uiPid = 0;
if (GetParent(hwnd) == IntPtr.Zero)
{
GetWindowThreadProcessId(hwnd, ref uiPid);
if (uiPid == lParam) // 找到进程对应的主窗口句柄
{
processWnd[uiPid] = hwnd; // 把句柄缓存起来
SetLastError(0); // 设置无错误
return false; // 返回 false 以终止枚举窗口
}
}
return true;
}
}