42

I'm trying to use the below code to show a Balloon notification. I've verified that it's being executed by using breakpoints. It's also showing no errors.

What should I do to debug this since it's not throwing errors and not showing the balloon?

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);
}
abatishchev
  • 98,240
  • 88
  • 296
  • 433
Ben
  • 769
  • 2
  • 7
  • 17

6 Answers6

49

You have not actually specified an icon to display in the task bar. Running your code in LINQPad, by simply adding notifyIcon.Icon = SystemIcons.Application before the call to ShowBalloonTip I was able to get the tip to be displayed. Also note that you should call Dispose when you are done with your NotifyIcon instance.

  • 2
    I use `Dispose` on Window Closing/Closed, otherwise it lingers until you move the mouse over it. – Andrew Grinder Jul 16 '14 at 01:24
  • @AndrewGrinder that is Microsoft intention to keep on showing the info as long the user is absent and reach the timeout only when he is using the computer – oo_dev Apr 10 '18 at 09:21
35

Matthew identified the issue, but I still struggled to put all the pieces together. So I thought a concise example that works in LINQPad as-is would be helpful (and presumably elsewhere). Just reference the System.Windows.Forms assembly, and paste this code in.

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();
user276648
  • 6,018
  • 6
  • 60
  • 86
Jeremy Cook
  • 20,840
  • 9
  • 71
  • 77
  • This works great but it works only for 5 seconds, even if I have make the ShowBaloonTip value, 1 minute, although I have rebuilded the project... I couldn't find why... – Bengi Besçeli Feb 21 '17 at 21:15
  • I have found this question for this: http://stackoverflow.com/questions/3906531/tooltip-balloon-disappears-after-5-seconds – Bengi Besçeli Feb 21 '17 at 21:42
  • @HQtunes.com: your link is for a `ToolTip`, not a `NotifyIcon`. It may have to do with the fact that `This [the timeout] parameter is deprecated as of Windows Vista. Notification display times are now based on system accessibility settings.` – user276648 Jul 20 '17 at 10:11
  • 2
    Thanks for this example, just noting an approach to disposing the notification - adding these event handlers before `ShowBalloonTip()` seems to work fairly well for me without needing a thread sleep: `notification.BalloonTipClosed += (sender, args) => notification.Dispose();`, and `notification.BalloonTipClicked += (sender, args) => notification.Dispose();` (I found both to be required, depending on whether the user clicks to close or leaves it to time out). – jlmt Jun 24 '18 at 15:53
2

See the below source code.

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....");
        }
    }
}
Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Kevin M
  • 5,436
  • 4
  • 44
  • 46
  • 1
    Where is the explanation of the implementation? I tried to run the code as is and nothing happens. Please explain how to make this code actually show the balloon notification. – Agrejus Jun 24 '16 at 14:42
2

For the sake of future coders:

the [timeout] parameter is deprecated as of windows vista

See: C# NotifyIcon Show Balloon Parameter Deprecated

So you might as well just put 0 into the parameter for > Windows Vista. What's worse, comments on the linked answer suggests that the replacement for these balloons, toast notifications, were only introduced in Windows 8. So for poor old Windows 7 falling between two stools, with Vista < 7 < 8, we seem to be at the mercy of however long Windows wants to keep that balloon there! It does eventually fade away, I've noticed, but after some empirical testing I'm quite sure that parameter is indeed being ignored.

So, building on the answers above, and in particular taking the lambda functions suggested by @jlmt in the comments, here's a solution that works for me on 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();
        }

Notes

  • I've put a TODO in there to write another implementation for Windows 8, as people are 50/50 now on Windows 7/8 so would be good to support a newer functionality. I guess anyone else coding this for multiple versions of windows should probably do the same, ideally. Or just stop supporting 7 and switch to using ToastNotification.
  • I purposely defined the disposal in a function so I could debug and verify that the breakpoint was indeed being hit.
Colm Bhandal
  • 3,343
  • 2
  • 18
  • 29
1

ShowBalloonnTip takes the number of milliseconds. 3 milliseconds might be too fast for you to even see. Try something more like 3000

You might need to pass a component model to the contructor. It's what I see in all the examples. Sorry been a long time since I've used it. See first answer here:

NotifyIcon not showing

Community
  • 1
  • 1
AaronLS
  • 37,329
  • 20
  • 143
  • 202
  • Nope, didn't fix anything... is there some requirement like I have to have the application running in the system tray in order to use that? – Ben Nov 14 '12 at 04:34
  • @Ben if you didn't notice I linked a similar question and added another suggestion. Beyond that, no other ideas. I am guessing it simply is not in any way related to your application. In other words, must controls get added to some sort of controls container/collection or reference in your form. I suspect this is the purpose of the component model that gets passed to the constructor, to wire it up to your application. – AaronLS Nov 14 '12 at 04:58
0

Take a look at the example here http://msdn.microsoft.com/en-us/library/system.windows.forms.notifyicon.aspx

I see some distinct differences between it an your code, there are many pieces you're leaving out such as creating a ComponentModelContainer and passing that into the NotifyIcon's constructor.

evanmcdonnal
  • 46,131
  • 16
  • 104
  • 115