none
アイコンのポップアップメニューが表示されない RRS feed

  • 質問

  • コンソールアプリを
    VisualStudio2008で作成していて
    プログラムのアイコンをタスクトレイに表示しようと
    考えてますが表示されません。
    どなたかお知恵を拝借お願いします。

    NotifyIconMainをコンソールで作成しています。
    コンソールの待機中にアイコンを右クリックしても
    メニューが表示されなかったり、イベントが飛んできません
    msdnをみて作成したのですが…

    namespase A
    {
     class NotifyIconMain
     {
      // アイコン
      static private NotifyIcon m_csIcon;
      
      static void Main(string[] args)
      {
       // アイコンクラス生成
       m_csIcon = new NotifyIcon();

       // アイコンの表示(この中で生成している)
       m_csIcon.ShowIcon();

       while (true)
       {
        // コンソール画面から取得
        string str = Console.ReadLine();
       
        // 入力を小文字にしてendだったら終了
        if (str.ToLower().Equals("end"))
        {
         break;
        }
       }
      }
     }
    }

    namespase B
    {
     class NotifyIcon
     {
      private System.Windows.Forms.NotifyIcon m_csNotifyIcon;
      private System.Windows.Forms.ContextMenu m_csContextMenu;
      private System.Windows.Forms.MenuItem m_csVerInfo;
      private System.Windows.Forms.MenuItem m_csAppEnd;
      private System.ComponentModel.IContainer m_csComponent;

      public void ShowIcon()
      {
       // コンテナ生成
       this.m_csComponent = new System.ComponentModel.Container();

       // メニュー生成
       this.m_csContextMenu = new System.Windows.Forms.ContextMenu();

       // メニュー項目
       this.m_csVerInfo = new System.Windows.Forms.MenuItem();
       this.m_csAppEnd = new System.Windows.Forms.MenuItem();


       // contextMenu1初期化
       this.m_csContextMenu.MenuItems.AddRange(
          new System.Windows.Forms.MenuItem[] { this.m_csVerInfo,
                     this.m_csAppEnd});

       // menuItem1初期化
       this.m_csVerInfo.Index = 0;
       this.m_csVerInfo.Text = "バージョン情報を表示";
       this.m_csVerInfo.Enabled = true;
       this.m_csVerInfo.Click += new System.EventHandler(this.VerInfo_Click);

       // menuItem2初期化
       this.m_csAppEnd.Index = 1;
       this.m_csAppEnd.Text = "アプリケージョンの終了";
       this.m_csAppEnd.Enabled = true;
       this.m_csAppEnd.Click += new System.EventHandler(this.AppEnd_Click);

       // アイコン生成
       this.m_csNotifyIcon = new System.Windows.Forms.NotifyIcon(this.m_csComponent);

       // アイコン設定
       m_csNotifyIcon.Icon = Properties.Resources.ClientIcon;
        
       // アイコンにメニューを設定
       m_csNotifyIcon.ContextMenu = this.m_csContextMenu;

       // アイオンのツールチップ設定
       m_csNotifyIcon.Text = "アイコンのツールチップ";
        
       // アイコン表示
       m_csNotifyIcon.Visible = true;

       // アイコンダブルクリックイベント作成
       m_csNotifyIcon.DoubleClick += new System.EventHandler(this.NotifyIcon_DoubleClick);
      }
     }
    }

    2010年7月28日 10:07

回答

  • MessageBox以外のWinFormを動作させるためにはMessage Loopを回してやる必要があります。具体的にはApplication.Run() のオーバーロードのうちのいずれかです。WinFormのプロジェクトの場合、Program.csを見るとApplication.Run(Form)が書かれていることが確認できます。

    なお、Run()メソッドを呼んでMessage Loopが終了するまでRun()メソッドは返ってきません。逆にRun()メソッドが返ってきたということはMessage Loopが終了したことを意味します。他の処理を行いたい場合は、マルチスレッド等の対応が必要になります。

    2010年7月28日 10:38
  • 以前、似たようなことを試したことがあるので、その時のサンプルコードを貼り付けておきます。(名前空間やクラス名は変更しています)

    using System;
    using System.ComponentModel;
    using System.Threading;
    using System.Windows.Forms;
    using SystemTraySample.Properties;
    
    namespace SystemTraySample
    {
      class Program
      {
        static void Main(string[] args)
        {
          // メッセージループを処理するための Form
          NotifyIconForm form = null;
          Thread thread = new Thread((ThreadStart)delegate
          {
            // 別スレッドでメッセージループをまわす
            try
            {
              form = new NotifyIconForm();
              Application.Run(form);
            }
            catch (Exception ex)
            {
              Console.WriteLine(ex.Message);
            }
          });
          thread.Start();
    
          // ここでユーザーに入力させたりする
    
          Console.WriteLine("Enter で終了");
          Console.ReadLine();
          if (form != null)
          {
            form.Invoke((Action)delegate
            {
              form.Close();
            });
          }
        }
      }
    
      class NotifyIconForm : Form
      {
        private NotifyIcon _notifyIcon;
    
        public NotifyIconForm()
        {
          WindowState = FormWindowState.Minimized;
          InitNotifyIcon();
        }
    
        protected override void OnLoad(EventArgs e)
        {
          base.OnLoad(e);
          
          // タスクバーに表示されないようにする
          Hide();
        }
    
        protected override void Dispose(bool disposing)
        {
          _notifyIcon.Dispose();
          base.Dispose(disposing);
        }
    
        public void InitNotifyIcon()
        {
          MenuItem versionMenuItem = new MenuItem();
          versionMenuItem.Text = "バージョン情報を表示";
          versionMenuItem.Click += new EventHandler(versionMenuItem_Click);
    
          ContextMenu _notifyIconMenu = new ContextMenu();
          _notifyIconMenu.MenuItems.Add(versionMenuItem);
    
          IContainer m_csComponent = new Container();
          _notifyIcon = new NotifyIcon(m_csComponent);
          _notifyIcon.Icon = Resources.Icon1; // システムトレイに表示したいアイコン
          _notifyIcon.ContextMenu = _notifyIconMenu;
          _notifyIcon.Text = "アイコンのツールチップ";
          _notifyIcon.Visible = true;
        }
    
        private void versionMenuItem_Click(object sender, EventArgs e)
        {
          MessageBox.Show("Version 0.1");
        }
      }
    }
    
    

    なかむら(http://d.hatena.ne.jp/griefworker)
    2010年7月29日 4:08

すべての返信

  • MessageBox以外のWinFormを動作させるためにはMessage Loopを回してやる必要があります。具体的にはApplication.Run() のオーバーロードのうちのいずれかです。WinFormのプロジェクトの場合、Program.csを見るとApplication.Run(Form)が書かれていることが確認できます。

    なお、Run()メソッドを呼んでMessage Loopが終了するまでRun()メソッドは返ってきません。逆にRun()メソッドが返ってきたということはMessage Loopが終了したことを意味します。他の処理を行いたい場合は、マルチスレッド等の対応が必要になります。

    2010年7月28日 10:38
  • 以前、似たようなことを試したことがあるので、その時のサンプルコードを貼り付けておきます。(名前空間やクラス名は変更しています)

    using System;
    using System.ComponentModel;
    using System.Threading;
    using System.Windows.Forms;
    using SystemTraySample.Properties;
    
    namespace SystemTraySample
    {
      class Program
      {
        static void Main(string[] args)
        {
          // メッセージループを処理するための Form
          NotifyIconForm form = null;
          Thread thread = new Thread((ThreadStart)delegate
          {
            // 別スレッドでメッセージループをまわす
            try
            {
              form = new NotifyIconForm();
              Application.Run(form);
            }
            catch (Exception ex)
            {
              Console.WriteLine(ex.Message);
            }
          });
          thread.Start();
    
          // ここでユーザーに入力させたりする
    
          Console.WriteLine("Enter で終了");
          Console.ReadLine();
          if (form != null)
          {
            form.Invoke((Action)delegate
            {
              form.Close();
            });
          }
        }
      }
    
      class NotifyIconForm : Form
      {
        private NotifyIcon _notifyIcon;
    
        public NotifyIconForm()
        {
          WindowState = FormWindowState.Minimized;
          InitNotifyIcon();
        }
    
        protected override void OnLoad(EventArgs e)
        {
          base.OnLoad(e);
          
          // タスクバーに表示されないようにする
          Hide();
        }
    
        protected override void Dispose(bool disposing)
        {
          _notifyIcon.Dispose();
          base.Dispose(disposing);
        }
    
        public void InitNotifyIcon()
        {
          MenuItem versionMenuItem = new MenuItem();
          versionMenuItem.Text = "バージョン情報を表示";
          versionMenuItem.Click += new EventHandler(versionMenuItem_Click);
    
          ContextMenu _notifyIconMenu = new ContextMenu();
          _notifyIconMenu.MenuItems.Add(versionMenuItem);
    
          IContainer m_csComponent = new Container();
          _notifyIcon = new NotifyIcon(m_csComponent);
          _notifyIcon.Icon = Resources.Icon1; // システムトレイに表示したいアイコン
          _notifyIcon.ContextMenu = _notifyIconMenu;
          _notifyIcon.Text = "アイコンのツールチップ";
          _notifyIcon.Visible = true;
        }
    
        private void versionMenuItem_Click(object sender, EventArgs e)
        {
          MessageBox.Show("Version 0.1");
        }
      }
    }
    
    

    なかむら(http://d.hatena.ne.jp/griefworker)
    2010年7月29日 4:08
  • ありがとうございます

    試してみます。

    2010年7月30日 4:20