问题 没有从透明图片框获取鼠标单击事件

mfwoo

成员
已加入
2020年11月2日
留言内容
7
编程经验
10+
我在另一个带有键盘背景的图片框的顶部有一个透明背景(橙色矩形)的图片框。如何从较小的透明图片框获取mouseclick事件返回。
请帮忙。

1604577383043.png
 
Solution
PointsOnScreen.gif
您也可以使用积分来完成。我为您创建了一些东西,以帮助您获取图片中按钮的位置。只需运行代码,然后精确地悬停即可获取每个按钮的x / y位置值。与跳伞运动员的示例不同,我使用了元组点字典。这些值将必须在运行时硬编码到字典中。然后,您可以使用MouseUp事件从MouseEventArgs中捕获鼠标位置。虽然我没有为您做所有。那会带来什么乐趣呢?您需要比较单击事件坐标,并查看它们是否在键之一的半径内。然后,您可以从字典中返回已按下的键。

放进去...

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,540
地点
弗吉尼亚州切萨皮克
编程经验
10+
首先,为什么要使用透明图片框进行点击测试?
 

mfwoo

成员
已加入
2020年11月2日
留言内容
7
编程经验
10+
首先,为什么要使用透明图片框进行点击测试?
客户已经提供了自助服务机触摸屏键盘的设计和布局。我正在考虑用透明的图片框或标签覆盖这些单独的键,然后挂接鼠标单击事件以获取用户触摸过的键。

期待任何其他建议。
 
Last edited:

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,540
地点
弗吉尼亚州切萨皮克
编程经验
10+
只要有矩形列表和"keys" something like:
C#:
class KeyRect
{
    public string Key { get; set; }
    public Rectangle Rect { get; set; }
}
:
List<KeyRect> _keys = new List<KeyRect>()
    {
        new KeyRect() { "Delete", new Rectangle(150, 5, 40, 20) },
        new KeyRect() { "A", new Rectangle(10, 75, 10, 10) },
        :
    }

然后,当您按下鼠标或单击事件时,您遍历列表以检查鼠标的位置是否在矩形内。显然你的形状很奇怪"Enter"键,则需要有两个或多个矩形来进行命中测试。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,933
地点
英国
编程经验
10+
PointsOnScreen.gif
您也可以使用积分来完成。我为您创建了一些东西,以帮助您获取图片中按钮的位置。只需运行代码,然后精确地悬停即可获取每个按钮的x / y位置值。与跳伞运动员的示例不同,我使用了元组点字典。这些值将必须在运行时硬编码到字典中。然后,您可以使用MouseUp事件从MouseEventArgs中捕获鼠标位置。虽然我没有为您做所有。那会带来什么乐趣呢?您需要比较单击事件坐标,并查看它们是否在键之一的半径内。然后,您可以从字典中返回已按下的键。

将其放入您的局部表单类中:
C#:
        public Dictionary<string, Tuple<Point, Point>> Key_Positions = new Dictionary<string, Tuple<Point, Point>>();
将其放在您的表单显示事件中:
FormShown:
        private void Form1_Shown(object sender, EventArgs e)
        {
            // These : new Point(50, 30), cover from the left of the form to left side of number 1 (50). Top of the form to top of the number 1 is (30).
            // These : new Point(120, 80), cover from the left of the form to right side of number 1 (120). Top of the form to bottom of the number 1 is (80).
            Key_Positions.Add("1", Tuple.Create(new Point(50, 30), new Point(120, 80)));
            /* Add your custom MouseMove and MouseUpEvents */
            pictureBox1.MouseMove += PictureBox1_MouseMove;
            pictureBox1.MouseUp += PictureBox1_MouseUp;
        }
您的鼠标移动事件将如下所示:
MouseMove Event:
        private void PictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            label1.Location = e.Location;
            label1.Text = e.Location.ToString();
            /* This will move the label away from the actual position so not to prvent clicking the picture box. Otherwise the label will block your click. */
            label1.Location = new Point(e.Location.X + 20, e.Location.Y + 10);
        }
注意上面代码中的最后一行。当您要单击数字时,请务必留在那里。否则,标签将被放置在光标的前面,并且您的单击事件将被注册在您的标签而不是图片框上。将该代码行保留在末尾不加注释不会影响打印到标签Text属性的位置。接下来,您将需要PictureBox的MouseDown事件:
Code:
        private void PictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            foreach (var kp in from KeyValuePair<string, Tuple<Point, Point>> kp in Key_Positions
                               let X_Pos1 = e.Location.X >= kp.Value.Item1.X/* is Greater than 50 */
                               let X_Pos2 = e.Location.X <= kp.Value.Item2.X/* is Less than 30 */
                               let x_Pos3 = e.Location.Y >= kp.Value.Item1.Y/* is Gtreater than 30 */
                               let x_Pos4 = e.Location.Y <= kp.Value.Item2.Y/* is Less than 80 */
                               select kp)
            {
                if (e.Location.X >= kp.Value.Item1.X && e.Location.X <= kp.Value.Item2.X &&
                    e.Location.Y >= kp.Value.Item1.Y && e.Location.Y <= kp.Value.Item2.Y)
                {
                    Debug.WriteLine("You clicked 1");
                }
                else
                {
                    Debug.WriteLine("1 was not clicked");
                }
            }
        }
就像我说的;我没有为你做任何事。接下来,您需要在linq表达式中使用Where()子句来缩小范围,其中选定的值与每个键的点值不大于且不小于此值相关。与我在第10到18行中使用if.x / y坐标的e。位置(单击数字1的键的位置等等)对图像上的每个其他键编写逻辑的方式类似。虽然我了解到您在此设计中没有选择的余地,但我想指出,这是一个可怕的项目,更糟糕的是,当客户要求在WPF中完成时,您的客户希望它在Winforms中完成因此,您可以使用WPF获得速度和性能的好处。再看看 @跳伞在上面的帖子中,如果您喜欢他的推荐方式,则可以轻松编辑此代码以适合您的需求。希望这篇快速的帖子对您​​有所帮助。到您完成时,您应该已经:
Full Example:
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        public Dictionary<string, Tuple<Point, Point>> Key_Positions = new Dictionary<string, Tuple<Point, Point>>();       
        private void Form1_Shown(object sender, EventArgs e)
        {
            // These : new Point(50, 30), cover from the left of the form to left side of number 1 (50). Top of the form to top of the number 1 is (30).
            // These : new Point(120, 80), cover from the left of the form to right side of number 1 (120). Top of the form to bottom of the number 1 is (80).
            Key_Positions.Add("1", Tuple.Create(new Point(50, 30), new Point(120, 80)));
            /* Add your custom MouseMove and MouseUpEvents */
            pictureBox1.MouseMove += PictureBox1_MouseMove;
            pictureBox1.MouseUp += PictureBox1_MouseUp;
        }
        private void PictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            label1.Location = e.Location;
            label1.Text = e.Location.ToString();
            /* This will move the label away from the actual position so not to prvent clicking the picture box. Otherwise the label will block your click. */
            label1.Location = new Point(e.Location.X + 20, e.Location.Y + 10);
        }


        private void PictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            foreach (var kp in from KeyValuePair<string, Tuple<Point, Point>> kp in Key_Positions
                               let X_Pos1 = e.Location.X >= kp.Value.Item1.X/* is Greater than 50 */
                               let X_Pos2 = e.Location.X <= kp.Value.Item2.X/* is Less than 30 */
                               let x_Pos3 = e.Location.Y >= kp.Value.Item1.Y/* is Gtreater than 30 */
                               let x_Pos4 = e.Location.Y <= kp.Value.Item2.Y/* is Less than 80 */
                               select kp)
            {
                if (e.Location.X >= kp.Value.Item1.X && e.Location.X <= kp.Value.Item2.X &&
                    e.Location.Y >= kp.Value.Item1.Y && e.Location.Y <= kp.Value.Item2.Y)
                {
                    Debug.WriteLine("You clicked 1");
                }
                else
                {
                    Debug.WriteLine("1 was not clicked");
                }
            }
        }
    }
 
解决方案

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,933
地点
英国
编程经验
10+
全面使用矩形会更好。我只是想提出一个不同的建议,使用特定点作为图像上每个按钮的坐标。但是对于该输入按钮,使用点而不是矩形可能会更好。
 
最佳 底部