2016-07-26 66 views
0

我想仅在需要显示气球提示时显示系统任务栏图标,然后在气球提示关闭时隐藏图标。使用计时器时未启动事件处理程序

然而,一旦显示的图标,我不能让它消失,因为事件处理函数不是解雇:从由定时器触发的方法

public partial class MainWindow : Window { 

    public static NotifyIcon trayIcon = new NotifyIcon(); 

    public MainWindow() { 
     InitializeTrayIcon(); 
    } 

    void InitializeTrayIcon() { 
     trayIcon.Text = "My App"; 
     trayIcon.Icon = MyApp.Properties.Resources.myIcon; 
     trayIcon.Visible = false; 

     //the following never gets fired: 
     trayIcon.BalloonTipClosed += (sender, e) => { 
      trayIcon.Visible = false; 
     }; 
     } 

     public static void ShowTrayNotification(ToolTipIcon icon, string title, string text, int duration) { 
      trayIcon.Visible = true; 
      trayIcon.ShowBalloonTip(duration, title, text, icon); 
     } 
} 

ShowTrayNotification()被称为:

public abstract class Watcher { 

    protected System.Timers.Timer myTimer = new System.Timers.Timer(1000); 

    //the following is called in a subclass of Watcher, which is instantiated in MainWindow 
    protected void SetupMyTimer() { 
     myTimer.AutoReset = true; 
     myTimer.Elapsed += myTimer_Elapsed; 
     myTimer.Start(); 
    } 

    protected virtual void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { 
     myTimer.Enabled = false; 
     MyTimerElapsedCallback(); 
     myTimer.Enabled = true; 
    } 

    void MyTimerElapsedCallback() { 
     MainWindow.ShowTrayNotification(ToolTipIcon.Info, "Hello There!", "Balloon text here.", 5000); 
    } 
} 

因此显示气球。但BalloonTipClosedMainWindow从未被解雇。

我曾尝试:

  • 把(1)创建NotifyIcon的,(2)气球的显示,和(3)MainWindow设置BalloonTipClosed一切,它工作正常(即BalloonTipClosed是烧制)

  • 推杆(1),(2)和(3)在SetupMyTimer()并能正常工作以及

  • 推杆(1),(2)和(3)在MyTimerElapsedCallback()而不是工作(即, BalloonTipClosed没有解雇)

  • 改变BalloonTipClosedBalloonTipClicked和它工作为好。

  • 使用非lambda BalloonTipClosed EventHandler,不是工作。

这一点,我想这个问题已经通过定时器做的,但我不知道它是如何影响事件处理,也不怎么解决。

任何想法?

+0

你在你的MainWindow中调用SetUpMyTimer吗? – apomene

+0

@apomene不直接。在MainWindow中,我创建了一个新的WatcherSubclass,它最终调用SetupMyTimer()' – Obay

回答

2

您的代码中存在线程错误,计时器的Elapsed事件在线程池线程上引发。当你做这种事情时,你通常会得到一个InvalidOperationException,但是这个检查并没有为NotifyIcon实现。

使其在错误线程中可见的副作用是在该线程上创建了一个用于接收事件通知的其他隐藏窗口。它根本不能接收任何通知,线程池线程不会抽取消息循环。糟糕的诊断,没有例外,也没有什么好的方法来看它为什么会出错。

您的ShowTrayNotification()方法必须使用窗体的BeginInvoke()方法,以便代码在UI线程上运行。由于该方法是静态的,因此您可以使用Application.OpenForms [0] .BeginInvoke()进行绝对捏合,这使得难度更大。但是让Watcher类引发事件而不是直接调用表单的方法肯定会更好。或者考虑使用一个简单的Winforms'定时器,您可以在工具箱中找到它。发布后,Watcher类没有可见的附加值。

+0

我通过在MainWindow中创建一个Dispatcher dispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher来解决这个问题,并封装了创建,在Dispatcher.Invoke(new Action(()=> {...}));'ShowTrayNotification()'内部显示和隐藏'NotifyIcon'。谢谢! – Obay

+0

哦,对,WPF。当您可以使用BeginInvoke()时,切勿使用Invoke()。 –

相关问题