C# Control.PreviewKeyDown Event

 こんなボタンだけの簡単なアプリを作ってみた。「シャットダウン」がハイライト表示になっているけれどもマウスポインタをボタンの上に置くとこのような表示になる。MouseHoverイベントを利用したらこれは簡単にできる。しかしTabや[↑]Up、[↓]Downキー操作でフォーカスが移ってアクティブにはなってくれるがKeyDownイベントではどうがんばってもそれを捕捉できない。ボタンコントロールでそれは出来ないということだ。なのでプログラムで目的のボタンをアクティブにしてハイライト表示するということができないのである。そこのところを補うのがPreviewKeyDownというイベントらしい。Visual Studio 2022のボタン・プロパティ・イベントには、「フォーカスがこのコントロール上にあるときキーが押される、KeyDpwnイベントの前に発生しまいす。」と説明がある。マイクロソフトの説明はココ。なるほどということでマイクロソフトの使用例に倣って組み込んでみたのが以下のコード。

        //
        private void Button_MouseHover(object sender, EventArgs e)
        {
            var bt = (Button)sender;
            Button_Highlight(bt);
        }
        //
        private void Button_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Down:
                case Keys.Left:
                case Keys.Up:
                case Keys.Right:
                case Keys.Tab:
                    e.IsInputKey = true;
                    break;
            }
        }
        //
        private void Button_KeyDown(object sender, KeyEventArgs e)
        {
            Keys KeyTop = e.KeyCode;
            bool UpKey = true;
            switch (KeyTop)
            {
                case Keys.Up:
                case Keys.Tab:
                    break;
                case Keys.Down:
                    UpKey = false;
                    break;
                case Keys.Escape:
                    Application.Exit();
                    return;
                default:
                    return;
            }
            var v = hb.TabIndex + (UpKey ? +1 : -1);
            var ix = v > 5 ? 0 : (v < 0 ? 5 : v);
            Button_Highlight(Bt[ix]);
        }
        //
        private void Form1_Load(object sender, EventArgs e)
        {
            var size = new Size(26, 26);
            Bt = new Button[6] { B6, B5, B4, B3, B2, B1 };
            var img = new Image[]
            { Properties.Resources.cancel, Properties.Resources.LogOff,
                Properties.Resources.Reboot, Properties.Resources.shutdown, 
                Properties.Resources.Hibernation, Properties.Resources.Sleep };
            for (int ix = 0; ix < 6; ix++)
            {
                Bt[ix].TextAlign = ContentAlignment.MiddleLeft;
                Bt[ix].Image = new Bitmap(img[ix], size);
                Bt[ix].ImageAlign = ContentAlignment.MiddleLeft;
                Bt[ix].TextImageRelation = TextImageRelation.ImageBeforeText;
                Bt[ix].PreviewKeyDown += Button_PreviewKeyDown;
                Bt[ix].KeyDown += Button_KeyDown;
            }
            Button_Highlight(B6);
        }

これで[←]Leftキーと[→]Rightキーの押下は無視されてフォーカスが移ることはない。

コメント