Управление формой с клавиатуры

Вы там только вверх нажимаете, а надо во все стороны. В одном из предыдущих постов я делал поправку на это.

Так надо просто добавить все стрелки )

Я добавлял и нифига :man_shrugging:

А в коде что сейчас?

Ну вот так можно сделать.

 InitializeComponent();

            foreach (Control control in Controls)
            {
                control.PreviewKeyDown += (ox, ex) =>
                {
                    if (ex.KeyData == Keys.Up || ex.KeyData == Keys.Down)
                    {
                        ex.IsInputKey = true;                       
                    }
                };
            }

Это если надо чтобы при любом фокусе. А тут задача только когда нет фокуса, так что IsInputKey или PreviewKeyDown только у формы нужен.

нет фокуса на чем?

На элементах формы.
В коде выше кликом по форме снимается.

Так вроде при щелчке на форму итак снимается без дополнительных действий.

Неа


namespace WindowsFormsApp1
{
    partial class Form1
    {
        /// <summary>
        /// Обязательная переменная конструктора.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Освободить все используемые ресурсы.
        /// </summary>
        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Код, автоматически созданный конструктором форм Windows

        /// <summary>
        /// Требуемый метод для поддержки конструктора — не изменяйте 
        /// содержимое этого метода с помощью редактора кода.
        /// </summary>
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.listBox1 = new System.Windows.Forms.ListBox();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(202, 391);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 0;
            this.button1.Text = "button1";
            this.button1.UseVisualStyleBackColor = true;
            // 
            // listBox1
            // 
            this.listBox1.FormattingEnabled = true;
            this.listBox1.Location = new System.Drawing.Point(403, 126);
            this.listBox1.Name = "listBox1";
            this.listBox1.Size = new System.Drawing.Size(154, 199);
            this.listBox1.TabIndex = 1;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.Controls.Add(this.listBox1);
            this.Controls.Add(this.button1);
            this.KeyPreview = true;
            this.Name = "Form1";
            this.Text = "Form1";
            this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
            this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseDown);
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.ListBox listBox1;
    }
}

форма:

using System;
using System.Diagnostics;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            Debug.WriteLine(e.KeyCode);
            Debug.WriteLine($"ActiveControl = {ActiveControl}");
            if (ActiveControl != null)
            {
                return;
            }

            if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down || e.KeyCode == Keys.Left || e.KeyCode == Keys.Right)
            {
                Debug.WriteLine("arrow");

                e.Handled = true;
            }
        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            ActiveControl = null;
            Focus(); //не знаю, это надо или нет
        }

        protected override bool IsInputKey(Keys keyData)
        {
            return keyData == Keys.Up || base.IsInputKey(keyData);
        }

    }
}

выхлоп:

Space
ActiveControl = 
Space
ActiveControl = 
Up
ActiveControl = 
arrow
"WindowsFormsApp1.exe" (CLR v4.0.30319: WindowsFormsApp1.exe). Загружено "C:\Windows\Microsoft.Net\assembly\GAC_MSIL\mscorlib.resources\v4.0_4.0.0.0_ru_b77a5c561934e089\mscorlib.resources.dll". Сборка модуля выполнена без символов.
Down
ActiveControl = System.Windows.Forms.ListBox
Down
ActiveControl = System.Windows.Forms.ListBox
Down
ActiveControl = System.Windows.Forms.ListBox
Left
ActiveControl = System.Windows.Forms.ListBox

Так в IsInputKey нет же остальных стрелок.

Вообще стрелками обычно не особо удобно управлять, надо переключаться с мышки и обратно, а на ноутах часто еще и с Fn. Лучше WASD.

а, ещё и туда надо было? Чёт я совсем тупанул.

Ну это уже формальности. Я не игру пишу.

не понял :thinking:

Это зависит от расположения мышки и клавиатуры, но обычно ж когда одна рука на мышке, то вторая в левой части клавиатуры, а к правой части надо или как-то неудобно тянуться, или убирать вторую руку с мышки. Особенно если стол с полочкой для клавиатуры.
Потому в играх и WASD.
Ну а на клавиатурах без стрелок две руки, чтоб зажимать Fn.
И сейчас и не для ноутов некоторые берут урезанные клавиатуры, чтоб занимало меньше место.

А, понял. Но тут одновременно мышь и клаву не надо.

Это не игра :slightly_smiling_face:

Добавил на форму CheckBox со свойством Appearance = Button.
Теперь при нажатии вверх влево вниз фокус скачет на чекбокс и обратно на форму. А при нажатии вправо - никуда не скачет :dizzy_face:
Помогает только такой финт ушами:


        private void checkBoxTimer_Enter(object sender, EventArgs e)
        {
            ActiveControl = null;
            Focus();
        }

Ничего не скачет.

        Dictionary<Keys, string> keyTextMap = new Dictionary<Keys, string>
        {
            { Keys.Up, "⬆️" },
            { Keys.Right, "➡️" },
            { Keys.Down, "⬇️" },
            { Keys.Left, "⬅️" },
        };

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            Debug.WriteLine(e.KeyCode);
            Debug.WriteLine($"ActiveControl = {ActiveControl}");
            if (ActiveControl != null)
            {
                return;
            }

            if (keyTextMap.ContainsKey(e.KeyCode))
            {
                Debug.WriteLine($"Handled {keyTextMap[e.KeyCode]}");

                e.Handled = true;
            }
        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            ActiveControl = null;
            Focus();
        }

        Keys[] additionalInputKeys = new[] { Keys.Up, Keys.Right, Keys.Down, Keys.Left };

        protected override bool IsInputKey(Keys keyData)
        {
            return additionalInputKeys.Contains(keyData) || base.IsInputKey(keyData);
        }

Peek 2021-07-01 15-36

Обнаружил еще вот что. Если в Load сделать WindowState = FormWindowState.Maximized;, то при запуске форма не приобретает фокус.

        private void Form1_Activated(object sender, EventArgs e)
        {
            ActiveControl = null;
            Focus();
        }

Вместо этого фокус ставится на кнопку.
А если сделать так:


        private void btnPrevImage_Enter(object sender, EventArgs e)
        {
            ActiveControl = null;
            Focus();
        }

то всё нормально.

Не вижу никакой разницы. Всегда в фокусе первый по таб индексу элемент.

и при этом, это

        private void Form1_Activated(object sender, EventArgs e)
        {
            ActiveControl = null;
            Focus();
        }

не ставит фокус на форму

хм, да, странно.
Можно попробовать сообщить о баге ) Visual Studio Feedback