如何创建一个 UserControl,显示使用计时器以特定时间间隔重复的 NotifyIcon 的气球提示?
How to create a UserControl showing a balloon tip from a NotifyIcon repeated at a certain interval using a timer?
我正在创建一个在用户定义的时间创建通知的应用程序。
基本上我用两个WinForms
:
- 数字 1 用于获取通知数据并创建
NotificationObject
class 的新实例,其中包含消息、标题、截止时间等通知数据。
Form
数字 2 用于跟踪通知。
程序启动时,Form
2 号打开,有一个按钮可以打开 Form
1 号。当 1 号表格关闭时,它会将通知数据保存到 NotificationObject
class。 Form
数字 2 获取在 Form
数字 1 关闭时创建的 NotificationObject
,并将其添加到 ObservableCollection
。当向 ObservableCollection
添加某些内容时,它会创建一个带有构造函数参数 DueTime
、Title
和 Message
的 UserControl
。然后在 UserControl
中,我使用 System.Threading.Timer
和 NotifyIcon
创建通知。
即使我设置了 Callback
方法来创建 NotifyIcon
气球,它也没有显示任何东西。
Form number 1
public partial class NotificationCreator : Form
{
public NotificationObject ntfObj;
public NotificationCreator()
{
InitializeComponent();
}
private void createNotification_Click(object sender, EventArgs e)
{
if (String.IsNullOrEmpty(timeInput.Text))
{
MessageBox.Show(
"Please set the time.",
"Time is not set",
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
return;
}
if (String.IsNullOrEmpty(titleInput.Text))
{
MessageBox.Show(
"Please set the title.",
"Title is not set",
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
return;
}
if (String.IsNullOrEmpty(messageInput.Text))
{
MessageBox.Show(
"Please set the message.",
"Message is not set",
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
return;
}
DateTime time = DateTime.Parse(timeInput.Text);
DateTime dt = new DateTime(dateInput.Value.Year,
dateInput.Value.Month,
dateInput.Value.Day,
time.Hour,
time.Minute,
0
);
ntfObj = new NotificationObject(dt, titleInput.Text, messageInput.Text);
Close();
Dispose();
}
private void timeInput_TextChanged(object sender, EventArgs e)
{
if (timeInput.Text.Length == 5)
{
try
{
DateTime dummy = DateTime.Parse(timeInput.Text);
if (dummy.Hour <= DateTime.Now.Hour && dummy.Minute <= DateTime.Now.Minute && dummy.Hour != 00 && dummy.Minute != 00)
{
MessageBox.Show("Please set the time for future",
"Invalid time",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
return;
}
catch
{
MessageBox.Show("Please set a valid time",
"Invalid time",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
}
}
private void dateInput_ValueChanged(object sender, EventArgs e)
{
if (dateInput.Value < DateTime.Now.AddDays(-1))
{
MessageBox.Show("Please set the date for future.",
"Invalid date",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
dateInput.Value = DateTime.Now;
return;
}
}
}
}
Form number 2
public partial class TrackingPanel : Form
{
ObservableCollection<NotificationObject> ntfList = new ObservableCollection<NotificationObject>();
public TrackingPanel()
{
InitializeComponent();
ntfList.CollectionChanged += NtfList_CollectionChanged;
}
private void NtfList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
NotificationObject ntfObj = e.NewItems[0] as NotificationObject;
Notification ntf = new Notification(ntfObj.DueTime, ntfObj.ntfTitle, ntfObj.ntfMessage);
ntfPanel.Controls.Add(ntf);
}
}
private void TrackingPanel_Load(object sender, EventArgs e)
{}
private void TrackingPanel_Resize(object sender, EventArgs e)
{
if (WindowState == FormWindowState.Minimized)
{}
}
private void createNotification_Click(object sender, EventArgs e)
{
NotificationCreator Tool = new NotificationCreator();
Tool.ShowDialog();
ntfList.Add(Tool.ntfObj);
}
}
NotificationObject
/// <summary>
/// An object that represents the Notification and contains Notification information.
/// </summary>
public class NotificationObject
{
/// <summary>
/// Notification due time.
/// </summary>
public DateTime DueTime { get; set; }
/// <summary>
/// Title of Notification.
/// </summary>
public string ntfTitle { get; set; }
/// <summary>
/// Notification Message.
/// </summary>
public string ntfMessage{ get; set; }
public NotificationObject(DateTime dueTime, string title, string message)
{
DueTime = dueTime;
ntfTitle = title;
ntfMessage = message;
}
}
UserControl
public partial class Notification : UserControl
{
private readonly System.Threading.Timer timer;
public Notification(DateTime dt, string Title, string Message)
{
InitializeComponent();
this.Title.Text = Title;
this.Message.Text = Message;
ntfIco.Visible = false;
timer = new System.Threading.Timer(NotificationOccurs, null, dt - DateTime.Now, TimeSpan.FromSeconds(20));
}
private void NotificationOccurs(object state)
{
ntfIco.Visible = true;
ntfIco.ShowBalloonTip(3500, Title.Text, Message.Text, ToolTipIcon.Info);
ntfIco.Visible = false;
}
private void Notification_Load(object sender, EventArgs e)
{
ntfPic.Image = Properties.Resources.Search_Png;
}
}
编辑
我在 UserControl 中使用了 System.Windows.Forms.Timer,但仍然没有用。
public partial class Notification : UserControl
{
public Notification(DateTime dt, string Title, string Message)
{
InitializeComponent();
this.Title.Text = Title;
this.Message.Text = Message;
ntfIco.Visible = false;
Timer.Interval = (int)(dt - DateTime.Now).TotalMilliseconds;
Timer.Start();
}
private void Notification_Load(object sender, EventArgs e)
{
ntfPic.Image = Properties.Resources.Search_Png;
}
private void Timer_Tick(object sender, EventArgs e)
{
ntfIco.Visible = true;
ntfIco.ShowBalloonTip(3500, Title.Text, Message.Text, ToolTipIcon.Info);
Timer.Interval = 10 * 1000;
ntfIco.Visible = false;
}
}
来自评论讨论:
一定要设置通知图标的Icon属性。
让 WinForms 计时器与 UI 线程一起工作。
不要在气球提示弹出后立即将通知图标设置为 false,否则它会关闭。
让气球尖自己褪色。
如果要隐藏通知图标,请在 BallonTipClosed 事件中执行此操作。
private void Timer_Tick(object sender, EventArgs e)
{
ntfIco.Visible = true;
ntfIco.ShowBalloonTip(3500, Title.Text, Message.Text, ToolTipIcon.Info);
Timer.Interval = 10 * 1000;
}
public Notification(DateTime dt, string Title, string Message)
{
InitializeComponent();
this.Title.Text = Title;
this.Message.Text = Message;
ntfIco.Visible = false;
ntfIco.BalloonTipClosed += (sender, e) => ntfIco.Visible = false;
Timer.Interval = (int)( dt - DateTime.Now ).TotalMilliseconds;
Timer.Start();
}
我正在创建一个在用户定义的时间创建通知的应用程序。
基本上我用两个WinForms
:
- 数字 1 用于获取通知数据并创建
NotificationObject
class 的新实例,其中包含消息、标题、截止时间等通知数据。 Form
数字 2 用于跟踪通知。
程序启动时,Form
2 号打开,有一个按钮可以打开 Form
1 号。当 1 号表格关闭时,它会将通知数据保存到 NotificationObject
class。 Form
数字 2 获取在 Form
数字 1 关闭时创建的 NotificationObject
,并将其添加到 ObservableCollection
。当向 ObservableCollection
添加某些内容时,它会创建一个带有构造函数参数 DueTime
、Title
和 Message
的 UserControl
。然后在 UserControl
中,我使用 System.Threading.Timer
和 NotifyIcon
创建通知。
即使我设置了 Callback
方法来创建 NotifyIcon
气球,它也没有显示任何东西。
Form number 1
public partial class NotificationCreator : Form
{
public NotificationObject ntfObj;
public NotificationCreator()
{
InitializeComponent();
}
private void createNotification_Click(object sender, EventArgs e)
{
if (String.IsNullOrEmpty(timeInput.Text))
{
MessageBox.Show(
"Please set the time.",
"Time is not set",
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
return;
}
if (String.IsNullOrEmpty(titleInput.Text))
{
MessageBox.Show(
"Please set the title.",
"Title is not set",
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
return;
}
if (String.IsNullOrEmpty(messageInput.Text))
{
MessageBox.Show(
"Please set the message.",
"Message is not set",
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
return;
}
DateTime time = DateTime.Parse(timeInput.Text);
DateTime dt = new DateTime(dateInput.Value.Year,
dateInput.Value.Month,
dateInput.Value.Day,
time.Hour,
time.Minute,
0
);
ntfObj = new NotificationObject(dt, titleInput.Text, messageInput.Text);
Close();
Dispose();
}
private void timeInput_TextChanged(object sender, EventArgs e)
{
if (timeInput.Text.Length == 5)
{
try
{
DateTime dummy = DateTime.Parse(timeInput.Text);
if (dummy.Hour <= DateTime.Now.Hour && dummy.Minute <= DateTime.Now.Minute && dummy.Hour != 00 && dummy.Minute != 00)
{
MessageBox.Show("Please set the time for future",
"Invalid time",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
return;
}
catch
{
MessageBox.Show("Please set a valid time",
"Invalid time",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
}
}
private void dateInput_ValueChanged(object sender, EventArgs e)
{
if (dateInput.Value < DateTime.Now.AddDays(-1))
{
MessageBox.Show("Please set the date for future.",
"Invalid date",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
dateInput.Value = DateTime.Now;
return;
}
}
}
}
Form number 2
public partial class TrackingPanel : Form
{
ObservableCollection<NotificationObject> ntfList = new ObservableCollection<NotificationObject>();
public TrackingPanel()
{
InitializeComponent();
ntfList.CollectionChanged += NtfList_CollectionChanged;
}
private void NtfList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
NotificationObject ntfObj = e.NewItems[0] as NotificationObject;
Notification ntf = new Notification(ntfObj.DueTime, ntfObj.ntfTitle, ntfObj.ntfMessage);
ntfPanel.Controls.Add(ntf);
}
}
private void TrackingPanel_Load(object sender, EventArgs e)
{}
private void TrackingPanel_Resize(object sender, EventArgs e)
{
if (WindowState == FormWindowState.Minimized)
{}
}
private void createNotification_Click(object sender, EventArgs e)
{
NotificationCreator Tool = new NotificationCreator();
Tool.ShowDialog();
ntfList.Add(Tool.ntfObj);
}
}
NotificationObject
/// <summary>
/// An object that represents the Notification and contains Notification information.
/// </summary>
public class NotificationObject
{
/// <summary>
/// Notification due time.
/// </summary>
public DateTime DueTime { get; set; }
/// <summary>
/// Title of Notification.
/// </summary>
public string ntfTitle { get; set; }
/// <summary>
/// Notification Message.
/// </summary>
public string ntfMessage{ get; set; }
public NotificationObject(DateTime dueTime, string title, string message)
{
DueTime = dueTime;
ntfTitle = title;
ntfMessage = message;
}
}
UserControl
public partial class Notification : UserControl
{
private readonly System.Threading.Timer timer;
public Notification(DateTime dt, string Title, string Message)
{
InitializeComponent();
this.Title.Text = Title;
this.Message.Text = Message;
ntfIco.Visible = false;
timer = new System.Threading.Timer(NotificationOccurs, null, dt - DateTime.Now, TimeSpan.FromSeconds(20));
}
private void NotificationOccurs(object state)
{
ntfIco.Visible = true;
ntfIco.ShowBalloonTip(3500, Title.Text, Message.Text, ToolTipIcon.Info);
ntfIco.Visible = false;
}
private void Notification_Load(object sender, EventArgs e)
{
ntfPic.Image = Properties.Resources.Search_Png;
}
}
编辑
我在 UserControl 中使用了 System.Windows.Forms.Timer,但仍然没有用。
public partial class Notification : UserControl
{
public Notification(DateTime dt, string Title, string Message)
{
InitializeComponent();
this.Title.Text = Title;
this.Message.Text = Message;
ntfIco.Visible = false;
Timer.Interval = (int)(dt - DateTime.Now).TotalMilliseconds;
Timer.Start();
}
private void Notification_Load(object sender, EventArgs e)
{
ntfPic.Image = Properties.Resources.Search_Png;
}
private void Timer_Tick(object sender, EventArgs e)
{
ntfIco.Visible = true;
ntfIco.ShowBalloonTip(3500, Title.Text, Message.Text, ToolTipIcon.Info);
Timer.Interval = 10 * 1000;
ntfIco.Visible = false;
}
}
来自评论讨论:
一定要设置通知图标的Icon属性。
让 WinForms 计时器与 UI 线程一起工作。
不要在气球提示弹出后立即将通知图标设置为 false,否则它会关闭。
让气球尖自己褪色。
如果要隐藏通知图标,请在 BallonTipClosed 事件中执行此操作。
private void Timer_Tick(object sender, EventArgs e)
{
ntfIco.Visible = true;
ntfIco.ShowBalloonTip(3500, Title.Text, Message.Text, ToolTipIcon.Info);
Timer.Interval = 10 * 1000;
}
public Notification(DateTime dt, string Title, string Message)
{
InitializeComponent();
this.Title.Text = Title;
this.Message.Text = Message;
ntfIco.Visible = false;
ntfIco.BalloonTipClosed += (sender, e) => ntfIco.Visible = false;
Timer.Interval = (int)( dt - DateTime.Now ).TotalMilliseconds;
Timer.Start();
}