处理表单中的箭头键

Handling arrow keys in a Form

我刚刚发现我们不能将 KeyDown 事件直接与 PictureBox 一起使用。所以我必须改变我的策略。

我决定将 Keydown 事件添加到实际表单中:

private void FullColourPaletteForm_KeyDown(object sender, KeyEventArgs e)
{
    switch (e.KeyCode)
    {
        case Keys.Left:
            {
                MessageBox.Show("Left");
                e.Handled = true;
                return;
            }
    }

}

没有被执行。当我按下左允许时,我看不到消息框。相反(这是正确的)它只是将光标从一个控件移动到另一个控件。

我希望能够通过拦截图片框内的箭头键来模仿某种对颜色块的光标支持。

我不确定前进的最佳方式。我不想破坏在控件之间移动的标准对话功能,但我现在想包含检测键的支持端口,这样我就可以添加我的代码来移动我的颜色块。

可以吗?不确定为什么我的事件无论如何都没有在表单中触发。

我看到了这个question。所以我尝试设置我的表单 KeyPreview 属性。没有快乐。我也查看了 ProcessCmdKey,但它似乎不适合手头的问题。

更新:

如果我尝试按照评论中的想法创建一个 SelectablePictureBox 控件,它看起来像这样:

我有两个问题。 1. 我似乎仍然无法弄清楚如何处理我的 pictureBox 对象本身的 keydown 事件。我不愿意手动将任何处理程序添加到设计器文件,以免我的更改丢失。

此外,当使用光标键在表单上进行一般控件导航时,它似乎不知道此控件。

如果您想在表单级别处理箭头键,您可以这样覆盖表单的 ProcessCmdKey 函数:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    if (keyData == Keys.Left)
    {
        MessageBox.Show("Left");
        return true;
    }
    return base.ProcessCmdKey(ref msg, keyData);
}

但一般来说,最好创建一个像 this 这样的自定义绘画可选控件,而不是将这种逻辑放在表单级别。你的控件应该包含这样的逻辑。


备注

OP: I have just found out that we can't use the KeyDown event directly with a PictureBox

正如Hans in 所提到的,PictureBox控件在默认情况下是不可选择的并且不能被聚焦,并且您不能为该控件处理键盘事件。

但是你可以强制它是可选的并支持键盘事件:

using System;
using System.Reflection;
using System.Windows.Forms;
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        this.pictureBox1.SetStyle(ControlStyles.Selectable, true);
        this.pictureBox1.SetStyle(ControlStyles.UserMouse, true);
        this.pictureBox1.PreviewKeyDown +=
            new PreviewKeyDownEventHandler(pictureBox1_PreviewKeyDown);
    }
    void pictureBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
    {
        if (e.KeyData == Keys.Left)
            MessageBox.Show("Left");
    }
}
public static class Extensions
{
    public static void SetStyle(this Control control, ControlStyles flags, bool value)
    {
        Type type = control.GetType();
        BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
        MethodInfo method = type.GetMethod("SetStyle", bindingFlags);
        if (method != null)
        {
            object[] param = { flags, value };
            method.Invoke(control, param);
        }
    }
}

至少知道这种方法是一种技巧,您以后可以重用扩展方法来启用或禁用控件上的某些样式。