【问题标题】:Click event delayed in ContextMenu attached to NotifyIcon附加到 NotifyIcon 的 ContextMenu 中的单击事件延迟
【发布时间】:2012-01-24 00:40:30
【问题描述】:

我正在开发一个插件(使用System.ComponentModel.Composition),以便应用程序在 Windows UI 的通知区域中放置一个图标。

trayMenu.MenuItems.Clear();

// Create context menu items
foreach( IJob job in jobs ) {
  MenuItem menuItem = new MenuItem( job.Name ) {Tag = job};
  menuItem.Click += MenuItemClick;
  trayMenu.MenuItems.Add( menuItem );
}

private void MenuItemClick( object sender, EventArgs e ) {
  // ...
}

现在,当我单击该图标的上下文菜单中的某个项目时,Click 处理程序不会被调用。
有趣的是,当我再次右键单击该图标(单击菜单项后)时,将调用先前单击的 MenuItemClick 处理程序。左键单击或悬停在图标上不会触发此步骤。

发生了什么事?

更新:我强烈感觉我的问题与this question 有关。但我仍在试图弄清楚如何将其应用于我的插件/应用程序。

【问题讨论】:

  • 你有没有做任何不寻常的事情,比如自己显示上下文菜单?在菜单外单击是否会导致其消失?
  • @Hans Passant:不,我不认为我在做任何不寻常的事情。菜单打开由 NotifyIcon 处理。在菜单外点击会导致它消失(如预期的那样)。

标签: c# .net windows composition system.componentmodel


【解决方案1】:

据我了解,问题在于 NotifyIcon 没有处理任何窗口消息(或者至少没有我喜欢/需要的那么多消息)。

我通过继承 Form 并为我的插件运行另一个消息泵解决了这个问题。

using System;
using ...

namespace JobTracker.Tray {
  [Export( typeof( IJobTrackerPlugin ) )]
  public class TrayPlugin : Form, IJobTrackerPlugin {

    #region Plugin Interface
    [Import( typeof( IJobTracker ) )]
#pragma warning disable 649
      private IJobTracker _host;
#pragma warning restore 649
    private IJobTracker Host {
      get { return _host; }
    }

    public void Initialize() {
      trayMenu = new ContextMenu();
      trayMenu.MenuItems.Add( "Exit", OnExit );

      trayIcon = new NotifyIcon();
      trayIcon.Icon = new Icon( SystemIcons.Application, 32, 32 );

      trayIcon.ContextMenu = trayMenu;

      // Show the proxy form to pump messages
      Load += TrayPluginLoad;
      Thread t = new Thread(
        () => {
          ShowInTaskbar    = false;
          FormBorderStyle  = FormBorderStyle.None;
          trayIcon.Visible = true;
          ShowDialog();
        } );
      t.Start();
    }

    private void TrayPluginLoad( object sender, EventArgs e ) {
      // Hide the form
      Size = new Size( 0, 0 );
    }
    #endregion

    private NotifyIcon trayIcon;    
    private ContextMenu trayMenu;

    private void OnExit( object sender, EventArgs e ) {
      Application.Exit();
    }

    #region Implementation of IDisposable

    // ...

    private void DisposeObject( bool disposing ) {
      if( _disposed ) {
        return;
      }
      if( disposing ) {
        // Dispose managed resources.
        if( InvokeRequired ) {
          EndInvoke( BeginInvoke( new MethodInvoker( Close ) ) );
        } else {
          Close();
        }
        trayIcon.Dispose();
        trayMenu.Dispose();
      }
      // Dispose unmanaged resources.
      _disposed = true;
    }
    #endregion
  }
}

看起来效果不错。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-02
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    相关资源
    最近更新 更多