web-dev-qa-db-ja.com

NotifyIconのコンテキストメニューを呼び出す

NotifyIconを左クリックすると、コンテキストメニュー(ContextMenuStripプロパティで設定)も開くようにしたいのですが。どうすればこれを達成できますか? Clickを処理して自分で位置を把握する必要がありますか?
編集:trayIcon.ContextMenuStrip.Show()の結果でメニューを表示すると、いくつかの望ましくない動作が発生します。

NotifyIconを右クリックした場合と同じ場所にメニューが表示されません(少なくとも、実行しているWindows 7では、タスクバーの場所にx座標とy座標を設定できないようです)。タスクバーの上に表示されます(それほど大きな問題ではありませんが、一貫性はいいでしょう)。

メニューが表示されている間、タスクバーに追加のアイコンが追加されています。

メニュー以外の場所をクリックしても、メニューは閉じません(右クリックしてコンテキストメニューを表示した場合、他の場所をクリックすると、自動的にコンテキストメニューが閉じます)。

組み込みの右クリックハンドラーがメニューを呼び出すだけでまったく可能ですか?

40
BarrettJ

通常、MouseClickイベントを処理してクリックを検出し、ContextMenuStrip.Show()メソッドを呼び出します。

    private void notifyIcon1_MouseClick(object sender, MouseEventArgs e) {
        contextMenuStrip1.Show(Control.MousePosition);
    }

しかし、それは実際には正しく機能しません。CMSの外側をクリックしても、CMSは閉じません。根本的な問題は このKB記事 で説明されているWindowsの癖(別名「バグ」)です。

独自のコードでこの回避策を呼び出すのはかなり面倒です。ピンボークは不愉快です。 NotifyIconクラスの ShowContextMenu()メソッド にこの回避策があります。プライベートメソッドであるため、アクセスが困難になっています。リフレクションはその制限を回避できます。私は5年前にこのハッキングを発見しましたが、まだ誰も問題を報告していません。 NFIのContextMenuStripプロパティを設定し、次のようにMouseUpイベントを実装します。

using System.Reflection;
...
    private void notifyIcon1_MouseUp(object sender, MouseEventArgs e) {
      if (e.Button == MouseButtons.Left) {
        MethodInfo mi = typeof(NotifyIcon).GetMethod("ShowContextMenu", BindingFlags.Instance | BindingFlags.NonPublic);
        mi.Invoke(notifyIcon1, null);
      }
    }
86
Hans Passant

次のコードを使用して、notifyiconの右クリックと左クリックの両方でコンテキストメニューを表示します。問題が見つかった場合は、arshad_mcs786 @ hotmail.com(Islamabdからのarshad)にテキストメッセージを送信してください。
// System.Runtime.InteropServicesはこれを参照として使用します

    [DllImport("User32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
    public static extern bool SetForegroundWindow(HandleRef hWnd);

    private void notifyIcon1_Click(object sender, EventArgs e)
    {
        SetForegroundWindow(new HandleRef(this, this.Handle));
        int x = Control.MousePosition.X;
        int y = Control.MousePosition.Y;
         x = x - 10;
        y = y - 40;
        this.contextMenuStrip1.Show(x,y );
        //this.PointToClient(Cursor.Position)
    }
2
Arshad

通知アイコンのonClickイベントに配線してから、クリック時にshowを呼び出すことができます

private void wire()
{
     notifyIcon1.Click += new EventHandler(notifyIcon1_Click);
}

void notifyIcon1_Click(object sender, EventArgs e)
 {
    contextMenuStrip1.Show(Cursor.Position);
 }
2
Patrick Kafka

ClickではなくMouseUpを処理する場合は、クリックされたボタンと、クリックの location を確認できます。この場所をContextMenuを表示する場所として使用できます

notifyIcon.MouseUp += new MouseEventHandler(delegate(object sender, MouseEventArgs e) { contextMenu.Show(e.Location); });
2
scottm