c# メニューのショートカットキー実行タイミング

ToolStripMenuItemShortcutKeys に指定したショートカットキーは、 ContainerControl の、 ProcessCmdKey で実行されます。

Form は、ContainerControl の派生クラスで、ProcessCmdKey は virtual なので、Form の ProcessCmdKey でオーバーライドできます。

フォーカスのあるコントロールによって挙動を変化させたいショートカットキーは、メニューの ShortcutKeys に指定しないで、各コントロールの ProcessCmdKey で処理すると良いでしょう。メニューにショートカットキーを処理させずに、テキストだけ表示するには、ShortcutKeyDisplayString を使います。

詳しい方法は、c# ショートカットキーを正しく処理するには? をご覧ください。

実験の詳細

ShortcutKeys に Ctrl+O を指定、コマンドハンドラで、スタックトレースを調べます。

出力結果

UnitTest.TestMenuShortcutKeys+FormMenuTestShortcutKeys::Open_Click
System.Windows.Forms.ToolStripItem::RaiseEvent
System.Windows.Forms.ToolStripMenuItem::OnClick
System.Windows.Forms.ToolStripItem::HandleClick
System.Windows.Forms.ToolStripItem::FireEventInteractive
System.Windows.Forms.ToolStripItem::FireEvent
System.Windows.Forms.ToolStripMenuItem::ProcessCmdKey
System.Windows.Forms.ToolStripManager::ProcessShortcut
System.Windows.Forms.ToolStripManager::ProcessCmdKey
System.Windows.Forms.ContainerControl::ProcessCmdKey
System.Windows.Forms.Form::ProcessCmdKey
System.Windows.Forms.Control::PreProcessMessage
System.Windows.Forms.Control::PreProcessControlMessageInternal
System.Windows.Forms.Application+ThreadContext::PreTranslateMessage
System.Windows.Forms.Application+ThreadContext::System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FPreTranslateMessage
System.Windows.Forms.Application+ComponentManager::System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop
System.Windows.Forms.Application+ThreadContext::RunMessageLoopInner
System.Windows.Forms.Application+ThreadContext::RunMessageLoop
System.Windows.Forms.Application::Run
UnitTest.TestMenuShortcutKeys::Test
UnitTest.Program::Test
UnitTest.Program::Main

Open_Click がハンドラです。Form の ProcessCmdKey からハンドラが呼ばれていることがわかります。

ソースコード

using System;
using System.Windows.Forms;

namespace UnitTest
{
  class TestMenuShortcutKeys : Tester
  {
    class FormTestMenuShortcutKeys : Form
    {
      public FormTestMenuShortcutKeys()
      {
        menuStrip = new MenuStrip();
        menuItemOpen = new ToolStripMenuItem();

        // レイアウト停止 //

        menuStrip.SuspendLayout();
        SuspendLayout();

        // メニュー //

        menuStrip.Items.Add(menuItemOpen);
        menuStrip.Name = "menuStrip";
        menuStrip.RenderMode = ToolStripRenderMode.System;
        menuStrip.TabIndex = 0;
        menuStrip.Text = "menuStrip";

        menuItemOpen.Name = "menuItemOpen";
        menuItemOpen.Text = "開く(&O)...";
        menuItemOpen.Click += new System.EventHandler(Open_Click);
        menuItemOpen.ShortcutKeys = ((Keys)((Keys.Control | Keys.O)));

        // フォーム //

        Controls.Add(menuStrip);
        MainMenuStrip = menuStrip;
        MaximizeBox = false;
        FormBorderStyle = FormBorderStyle.FixedSingle;

        // レイアウト //

        menuStrip.ResumeLayout(false);
        ResumeLayout(false);
        PerformLayout();
      }

      private MenuStrip menuStrip;
      private ToolStripMenuItem menuItemOpen;

      private void Open_Click(object sender, EventArgs e)
      {
        Console.WriteLine(SSS.DebugUtil.CallStackLines(0));
      }
    }

    public override void Test()
    {
      Application.Run(new FormTestMenuShortcutKeys());
    }
  }
}

コンソールアプリケーションの Main() から、Test() を呼んで実行します。コードのほんどの部分は、単にメニューを作成しているだけです。スタックトレースを出力している SSS.DebugUtil.CallStackLines は、こちらをご覧ください。

となりのページ

このサイトについて

このサイトのページへのリンクは自由に行っていただいてかまいません。
このサイトで公開している全ての画像、プログラム、文書の無断転載を禁止します。

連絡先

ここをクリック すると表示されるページから作者へメールで連絡できます。

共有