C# 显示气球通知

C# 显示气球通知,c#,.net,winforms,notifyicon,notification-area,C#,.net,Winforms,Notifyicon,Notification Area,我正在尝试使用下面的代码显示气球通知。我已经验证了它是通过使用断点执行的。它也没有显示错误 既然它没有抛出错误,也没有显示气球,我应该如何调试它 private void showBalloon(string title, string body) { NotifyIcon notifyIcon = new NotifyIcon(); notifyIcon.Visible = true; if (title != null) { notifyIc

我正在尝试使用下面的代码显示气球通知。我已经验证了它是通过使用断点执行的。它也没有显示错误

既然它没有抛出错误,也没有显示气球,我应该如何调试它

private void showBalloon(string title, string body)
{
    NotifyIcon notifyIcon = new NotifyIcon();
    notifyIcon.Visible = true;

    if (title != null)
    {
        notifyIcon.BalloonTipTitle = title;
    }

    if (body != null)
    {
        notifyIcon.BalloonTipText = body;
    }

    notifyIcon.ShowBalloonTip(30000);
}

ShowBalloonTip以毫秒为单位。3毫秒可能太快了,你甚至看不见。试试3000之类的

您可能需要将组件模型传递给构造函数。这就是我在所有例子中看到的。对不起,我已经很久没用了。请参见此处的第一个答案:


看看这里的示例


我看到它和您的代码之间有一些明显的区别,有许多部分您正在忽略,例如创建一个
ComponentModelContainer
,并将其传递到
NotifyIcon
的构造函数中。

您实际上没有指定要在任务栏中显示的图标。在LINQPad中运行代码,只需在调用
showBalloodTip
之前添加
notifyIcon.Icon=SystemIcons.Application
,我就可以获得要显示的提示。还请注意,当您完成
NotifyIcon
实例时,应调用
Dispose

请参阅下面的源代码

using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Windows.Forms;

namespace ShowToolTip
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btBallonToolTip_Click(object sender, EventArgs e)
        {
            ShowBalloonTip();
            this.Hide();
        }

        private void ShowBalloonTip()
        {
            Container bpcomponents = new Container();
            ContextMenu contextMenu1 = new ContextMenu();

            MenuItem runMenu = new MenuItem();
            runMenu.Index = 1;
            runMenu.Text = "Run...";
            runMenu.Click += new EventHandler(runMenu_Click);

            MenuItem breakMenu = new MenuItem();
            breakMenu.Index = 2;
            breakMenu.Text = "-------------";

            MenuItem exitMenu = new MenuItem();
            exitMenu.Index = 3;
            exitMenu.Text = "E&xit";

            exitMenu.Click += new EventHandler(exitMenu_Click);

            // Initialize contextMenu1
            contextMenu1.MenuItems.AddRange(
                        new System.Windows.Forms.MenuItem[] { runMenu, breakMenu, exitMenu });

            // Initialize menuItem1

            this.ClientSize = new System.Drawing.Size(0, 0);
            this.Text = "Ballon Tootip Example";

            // Create the NotifyIcon.
            NotifyIcon notifyIcon = new NotifyIcon(bpcomponents);

            // The Icon property sets the icon that will appear
            // in the systray for this application.
            string iconPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\setup-icon.ico";
            notifyIcon.Icon = new Icon(iconPath);

            // The ContextMenu property sets the menu that will
            // appear when the systray icon is right clicked.
            notifyIcon.ContextMenu = contextMenu1;

            notifyIcon.Visible = true;

            // The Text property sets the text that will be displayed,
            // in a tooltip, when the mouse hovers over the systray icon.
            notifyIcon.Text = "Morgan Tech Space BallonTip Running...";
            notifyIcon.BalloonTipText = "Morgan Tech Space BallonTip Running...";
            notifyIcon.BalloonTipTitle = "Morgan Tech Space";
            notifyIcon.ShowBalloonTip(1000);
        }

        void exitMenu_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        void runMenu_Click(object sender, EventArgs e)
        {
            MessageBox.Show("BallonTip is Running....");
        }
    }
}

马修指出了问题所在,但我仍在努力把所有的部分整合起来。因此,我认为在LINQPad中使用一个简洁的示例会有所帮助(可能在其他地方也是如此)。只需引用
System.Windows.Forms
程序集,然后将此代码粘贴到中

var notification = new System.Windows.Forms.NotifyIcon()
{
    Visible = true,
    Icon = System.Drawing.SystemIcons.Information,
    // optional - BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info,
    // optional - BalloonTipTitle = "My Title",
    BalloonTipText = "My long description...",
};

// Display for 5 seconds.
notification.ShowBalloonTip(5000);

// This will let the balloon close after it's 5 second timeout
// for demonstration purposes. Comment this out to see what happens
// when dispose is called while a balloon is still visible.
Thread.Sleep(10000);

// The notification should be disposed when you don't need it anymore,
// but doing so will immediately close the balloon if it's visible.
notification.Dispose();

为了未来的编码人员:

[timeout]参数在windows vista中已被弃用

见:

因此,您不妨将0放入>Windows Vista的参数中。更糟糕的是,链接答案上的评论表明,这些气球的替代品toast通知仅在Windows8中引入。因此,对于可怜的老Windows7来说,由于Vista<7<8,我们似乎在任由Windows7将气球保持在那里的时间长短决定!我注意到,它最终会消失,但经过一些实证测试,我很确定这个参数确实被忽略了

因此,在上述答案的基础上,特别是考虑到@jlmt在评论中建议的lambda函数,这里有一个在Windows 7上适用的解决方案:

//Todo: use abstract factory pattern to detect Windows 8 and in that case use a toastnotification instead
        private void DisplayNotificationBalloon(string header, string message)
        {
            NotifyIcon notifyIcon = new NotifyIcon
            {
                Visible = true,
                Icon = SystemIcons.Application
            };
            if (header != null)
            {
                notifyIcon.BalloonTipTitle = header;
            }
            if (message != null)
            {
                notifyIcon.BalloonTipText = message;
            }
            notifyIcon.BalloonTipClosed += (sender, args) => dispose(notifyIcon);
            notifyIcon.BalloonTipClicked += (sender, args) => dispose(notifyIcon);
            notifyIcon.ShowBalloonTip(0);
        }

        private void dispose(NotifyIcon notifyIcon)
        {
            notifyIcon.Dispose();
        }
笔记
  • 我在这里写了一个TODO来为Windows编写另一个实现 8,因为现在Windows 7/8上的用户是50/50,所以最好支持它 更新的功能。我猜还有人在为多个 理想情况下,windows版本可能也应该这样做。或者只是 停止支持7并切换到使用ToastNotification
  • 我特意在函数中定义了处理,以便调试和验证断点是否确实被命中

没有,没有修复任何问题。。。是否有一些要求,比如我必须让应用程序在系统托盘中运行才能使用它?@Ben,如果你没有注意到,我链接了一个类似的问题,并添加了另一个建议。除此之外,没有其他想法。我猜这与你的申请毫无关系。换句话说,必须将控件添加到表单中的某种控件容器/集合或引用中。我怀疑这就是传递给构造函数的组件模型的目的,将其连接到应用程序。完成。。。它没有修复任何问题:-\n我在窗口关闭/关闭时使用
Dispose
,否则它会一直保留,直到您将鼠标移到它上面。@AndrewGrinder这是Microsoft的意图,只要用户不在,并且只有在他使用计算机时才达到超时,那么对实现的解释是什么?我试图按原样运行代码,但什么也没发生。请解释如何使这段代码实际显示气球通知。这很好,但仅能工作5秒,即使我已使ShowBaloonTip值为1分钟,但我已重建了项目。。。我找不到原因…我找到了这个问题:@HQtunes.com:您的链接是针对
工具提示的,而不是针对
通知图标的。这可能与以下事实有关:
此[TheTimeout]参数在Windows Vista中被弃用。通知显示时间现在基于系统可访问性设置。
感谢这个示例,请注意一种处理通知的方法-在
showBallootTip()
之前添加这些事件处理程序对我来说似乎相当有效,而不需要线程睡眠:
Notification.balloottipClosed+=(发送方,args)=>notification.Dispose()
notification.balloottipclicked+=(发送方,args)=>notification.Dispose()(我发现两者都是必需的,这取决于用户是单击关闭还是让它超时)。