显示气球通知

42

我正在尝试使用以下代码来显示气球通知。 我已通过使用断点验证它正在执行。 它也没有显示任何错误。

由于它没有抛出错误并且没有显示气球,我该怎么调试?

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);
}
6个回答

49

您尚未指定要在任务栏中显示的图标。在LINQPad中运行代码时,只需在调用ShowBalloonTip之前添加notifyIcon.Icon = SystemIcons.Application,即可显示提示。还请注意,在完成NotifyIcon实例后,应调用Dispose


2
我在窗口关闭时使用 Dispose,否则它会一直存在,直到你将鼠标移到上面。 - Andrew Grinder
@AndrewGrinder,这是微软的意图,只要用户不在场并且在使用计算机时达到超时,就会继续显示信息。 - oo_dev

35

Matthew发现了这个问题,但我仍然很难将所有的部分组合在一起。所以我认为一个在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();

这个很好用,但只有5秒钟的有效时间,即使我已经将ShowBaloonTip值设为1分钟,并重新构建了项目……我找不到原因…… - Bengi Besçeli
我找到了这个问题的解答:https://dev59.com/WFHTa4cB1Zd3GeqPOQ9a - Bengi Besçeli
@HQtunes.com:你的链接是一个ToolTip,而不是一个NotifyIcon。这可能与“此参数(超时)已在Windows Vista中停用。通知显示时间现在基于系统辅助功能设置。”有关。 - user276648
2
谢谢这个例子,只是注意到一种处理通知的方法 - 在 ShowBalloonTip() 之前添加这些事件处理程序似乎对我来说效果不错,而无需线程睡眠:notification.BalloonTipClosed += (sender, args) => notification.Dispose();notification.BalloonTipClicked += (sender, args) => notification.Dispose();(我发现两者都是必需的,具体取决于用户是点击关闭还是让其超时)。 - jlmt

2
为了未来的编码人员:
timeout参数自Windows Vista起已被弃用。
参见:C# NotifyIcon Show Balloon Parameter Deprecated 因此,对于> Windows Vista的情况,您可以将0放入参数中。更糟糕的是,链接答案上的评论表明这些气球的替代品——Toast通知——仅在Windows 8中引入。因此,对于落在两个凳子之间的可怜的Windows 7,即Vista < 7 < 8,我们似乎要看Windows想保留那个气球多长时间!我注意到它最终会消失,但经过一些实证测试,我很确定该参数确实被忽略了。
因此,在上面的答案基础上构建,并特别采用@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%,所以支持较新的功能会很好。我想,任何编写多个Windows版本的人都应该这样做,理想情况下。或者只停止支持7并切换到使用ToastNotification。
  • 我故意在一个函数中定义了处理,以便我可以调试和验证断点是否确实被触发。

2
请见下面的源代码。
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....");
        }
    }
}

1
实现的说明在哪里?我尝试按原样运行代码,但什么也没有发生。请解释如何使此代码实际显示气球通知。 - Agrejus

1

ShowBalloonnTip需要指定毫秒数。3 毫秒可能太快了,你甚至看不到它。尝试设置更长的时间,如 3000。

你可能需要将组件模型传递给构造函数。这是我在所有示例中看到的。很抱歉我已经很久没有使用过了。请参见以下第一个答案:

NotifyIcon not showing


没有,什么都没修好... 是否有一些要求,比如我必须让应用程序在系统托盘中运行才能使用它? - Ben
@Ben 如果你没有注意到,我已经链接了一个类似的问题并添加了另一个建议。除此之外,没有其他想法。我猜这与你的应用程序没有任何关系。换句话说,必须将控件添加到某种控件容器/集合或表单中的引用中。我怀疑这就是传递给构造函数的组件模型的目的,将其连接到您的应用程序。 - AaronLS

0

1
完成了...它没有修复任何东西 :-\ - Ben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接