winforms 放置一个按钮后,我不能移动的形状使用箭头键

mpgws1up  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(84)

这是一个示例代码,是一个更大的代码的一部分,我想用这个代码来移动一个图片框,但当按钮被引入的形式,我不能移动它后,我已经尝试了许多修复在互联网上,但没有像this.KeyPreview = true;修复工作,但似乎没有工作。

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

        private void pictureBox1_Click(object sender, EventArgs e)
        {

        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Right
                && (pictureBox1.Location.X + pictureBox1.Width) < this.Width)
            {
                pictureBox1.Location = new Point(pictureBox1.Location.X + 15,
                    pictureBox1.Location.Y);
            }
            else if (e.KeyData == Keys.Left)
            {
                pictureBox1.Location = new Point(pictureBox1.Location.X - 15,
                    pictureBox1.Location.Y);
            }
            else if (e.KeyData == Keys.Up)
            {
                pictureBox1.Location = new Point(pictureBox1.Location.X,
                    pictureBox1.Location.Y - 15);
            }
            else if (e.KeyData == Keys.Down)
            {
                pictureBox1.Location = new Point(pictureBox1.Location.X,
                    pictureBox1.Location.Y + 15);
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.KeyPreview = true;

        }
    }
}

字符串

wgmfuz8q

wgmfuz8q1#

事实上,你是正确的,只要表单上有一个焦点按钮,它就会独占Key消息,Form1_KeyDown将不再被调用或移动图片框。
解决这个问题的方法是实现IMessageFilter,这样我们就可以选择无条件地拦截Win32WM_KEYDOWN消息。试试这样:

public partial class MainForm : Form, IMessageFilter
{
    public MainForm()
    {
        InitializeComponent();
        Application.AddMessageFilter(this);
        Disposed += (sender, e) =>Application.RemoveMessageFilter(this);
    }
    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg == WM_KEYDOWN)
        {
            var e = new KeyEventArgs(((Keys)m.WParam) | Control.ModifierKeys);
            OnHotKeyPreview(FromHandle(m.HWnd), e);
            return (e.Handled);
        }
        return false;
    }
    private void OnHotKeyPreview(Control? control, KeyEventArgs e)
    {
        switch (e.KeyData)
        {
            case Keys.Left: onMoveLeft(); e.Handled = true; break;
            case Keys.Up: onMoveUp(); e.Handled = true; break;
            case Keys.Right:  onMoveRight(); e.Handled = true; break;
            case Keys.Down: onMoveDown(); e.Handled = true; break;
        }
    }
    private void onMoveLeft() =>
        pictureBox1.Location = new Point(pictureBox1.Location.X - 15, pictureBox1.Location.Y);
    private void onMoveUp() => 
        pictureBox1.Location = new Point(pictureBox1.Location.X, pictureBox1.Location.Y - 15);
    private void onMoveRight() =>
        pictureBox1.Location = new Point(pictureBox1.Location.X + 15,
            pictureBox1.Location.Y);
    private void onMoveDown() =>
        pictureBox1.Location = new Point(pictureBox1.Location.X, pictureBox1.Location.Y + 15);
    private const int WM_KEYDOWN = 0x0100;
}

字符串

备选方案

然而,更干净的方法是继承PictureBox并在 there 实现IMessageFilter,以创建一个扩展的PictureBoxEx控件,该控件知道如何通过处理拦截的键事件来移动 * 自身 *。


的数据
要使用此控件,请转到Designer.cs文件,并将PictureBox的示例交换为扩展类PictureBoxEx。这是最终的替代解决方案,结果是简化了Form类。这里的方案是将图片框的边框设置为移动。

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        buttonDeselect.Click += (sender, e) =>
        {
            foreach (var pb in Controls.OfType<PictureBoxEx>())
            {
                pb.BorderStyle = BorderStyle.None;
            }
        };
    }
}

PictureBoxEx

class PictureBoxEx : PictureBox, IMessageFilter
{
    public PictureBoxEx()
    {
        Application.AddMessageFilter(this);
        Disposed += (sender, e) => Application.RemoveMessageFilter(this);
    }
    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        if (ModifierKeys != Keys.Control)   // Allow multiple select.
        {
            foreach (var pb in Parent.Controls.OfType<PictureBoxEx>())
            {
                pb.BorderStyle = BorderStyle.None;
            }
        }
        BorderStyle = BorderStyle.FixedSingle;
    }
    private const int WM_KEYDOWN = 0x0100;
    public bool PreFilterMessage(ref Message m)
    {
        if ((m.Msg == WM_KEYDOWN) && (BorderStyle == BorderStyle.FixedSingle))
        {

            var e = new KeyEventArgs(((Keys)m.WParam) | Control.ModifierKeys);
            OnKeyDown(e);
            return (e.Handled);
        }
        return false;
    }
    protected override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);
        switch (e.KeyData)
        {
            case Keys.Left:
                Location = new Point(Location.X - 15, Location.Y);
                break;
            case Keys.Up:
                Location = new Point(Location.X, Location.Y - 15);
                break;
            case Keys.Right:
                Location = new Point(Location.X + 15, Location.Y);
                break;
            case Keys.Down:
                Location = new Point(Location.X, Location.Y + 15);
                break;
        }
    }
}

相关问题