【问题标题】:How to move picturebox with arrow keys with listbox?如何使用带有列表框的箭头键移动图片框?
【发布时间】:2011-01-24 07:13:22
【问题描述】:

一切正常 form1+picturebox1 我可以使用下面的代码:


   public Form1()
        {
            InitializeComponent();
            KeyDown += new KeyEventHandler(Form1_KeyDown);
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            int x = pictureBox1.Location.X;
            int y = pictureBox1.Location.Y;

            if (e.KeyCode == Keys.Right) x += 5;
            else if (e.KeyCode == Keys.Left) x -= 5;
            else if (e.KeyCode == Keys.Up) y -= 5;
            else if (e.KeyCode == Keys.Down) y += 5;

            pictureBox1.Location = new Point(x, y);

        }

但是; 如果我添加列表框来写位置图片框,我不能用箭头键移动图片框我该怎么做?

【问题讨论】:

  • 只是好奇,你为什么要标记这个多线程?
  • 你能解释一下关于列表框的部分吗?这不是很清楚。

标签: c# .net visual-studio multithreading


【解决方案1】:

如果您的列表框获得焦点而不是表单,您可能必须监听列表框的 keydown-event。

编辑:

使用这个可聚焦的 PictureBoxEx 并监听它的 previewkeydown-event :

public class PictureBoxEx : PictureBox
{
    public PictureBoxEx()
    {
        this.SetStyle(ControlStyles.Selectable, true);
    }

    protected override void OnClick(EventArgs e)
    {
        this.Focus();
        base.OnClick(e);
    }
}

编辑:

或使用以下内容。这样您就不必在表单中移动控件,只需在控件中移动图像即可。

public class PictureBoxEx : Control
    {
        public PictureBoxEx()
        {
            this.SetStyle(ControlStyles.Selectable | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);


        }


        protected override void OnClick(EventArgs e)
        {
            this.Select();
            base.OnClick(e);
        }

        private Image _Image;
        public Image Image
        {
            get
            {
                return _Image;
            }
            set
            {
                _Image = value;
                this.Invalidate();
            }
        }

        private Point _ImageLocation = new Point(0,0);
        public Point ImageLocation
        {
            get
            {
                return _ImageLocation;
            }
            set
            {
                _ImageLocation = value;
                this.Invalidate();
            }
        }

        private int _ImageLocationLeft = 0;
        public int ImageLocationLeft
        {
            get
            {
                return _ImageLocationLeft;
            }
            set
            {
                _ImageLocationLeft = value;
                ImageLocation = new Point(value, ImageLocationTop);
            }
        }

        private int _ImageLocationTop = 0;
        public int ImageLocationTop
        {
            get
            {
                return _ImageLocationTop;
            }
            set
            {
                _ImageLocationTop = value;
                ImageLocation = new Point(ImageLocationLeft, value);
            }
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            if (Image != null)
            {
                pe.Graphics.DrawImage(Image, ImageLocation);
            }
            base.OnPaint(pe);
        }

        protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
        {
            if (e.KeyData == Keys.Up || e.KeyData == Keys.Down || e.KeyData == Keys.Left || e.KeyData == Keys.Right)
            e.IsInputKey = true;
            base.OnPreviewKeyDown(e);
        }
    }

【讨论】:

    【解决方案2】:

    您需要Invalidate,这将重绘您的用户界面;为了查看您所做的更改。

    您可以选择使用重载Invalidate(Region region) 重绘某些区域,也可以通过Control.Invalidate() 使整个控件无效。

    在创建新的Point 后尝试添加:this.Invalidate();

    您也可以使用Refresh(),这将使控件无效并强制重绘。

    这是一篇关于 "How to: Handle Keyboard input at Form Level" 的 MSDN 文章,您可能想阅读该文章并将其与您当前的代码进行比较。您可能希望将 KeyDown 更改为 KeyPress。而且正如我在评论中所说,它确实应该可以在不强制使用Invalidate()Refresh() 重绘表单的情况下工作。

    【讨论】:

    • 谢谢但不起作用:pictureBox1.Location = new Point(x, y); this.Invalidate(); this.Refresh();
    • @Phsika,什么都没有发生?您确定该事件甚至被触发了吗?即使没有 Invalidate/Refresh,它也应该可以工作,但可以肯定的是,暂时将它们留在那里。在该事件中放置一个断点,看看它是否触发。
    • @Phsika,你不明白哪一部分?我会尝试清除它。
    • 我认为;它与线程有关,因为它们是在表单加载中加载的,但是如果我单击箭头键来移动我的框,一切都会被锁定
    • @Phsika,你能在你的Form1_KeyDown 中放一个MessageBox.Show(@"Keyboard pressed!"); 看看它实际上是被调用的吗?否则它可能就像@Wowa 所说的那样,您的ListBox 会从表单中获取焦点,因此,您的击键不会被捕获。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-11
    • 1970-01-01
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多