如何检测鼠标是否在 winform 应用程序的 c# 中单击了某个形状的内部?

How to detect if mouse has clicked inside of a certain shape in c# on winform app?

假设我有一个 win form 应用程序和一个名为 pictureBox1 的图片框。然后我运行下面的代码:

public System.Drawing.Graphics graphics;
public System.Drawing.Pen blackPen = new System.Drawing.Pen(Color.Black, 2);

public void drawVennDiagram()
{
    graphics = pictureBox1.CreateGraphics();
    graphics.DrawEllipse(blackPen, 0, 0, 100, 100);
    graphics.DrawEllipse(blackPen, 55, 0, 100, 100);
}

如果我调用 drawVennDiagram() ,它将在 pictureBox1 中绘制两个圆圈,并且圆圈重叠得刚好看起来像维恩图。

我想要实现的目标如下:

  • Run Method A if the mouse clicks anywhere outside of the venn diagram but in the picturebox.

  • Run Method B if the mouse clicks only inside of the first circle.

  • Run Method C if the mouse clicks inside of both circles.

  • Run Method D if the mouse clicks only inside of the second circle.

到目前为止我已经写了下面的代码,它基本上跟踪光标点击的位置,但我无法弄清楚光标位置跟随哪个参数(a,b,c,d)。

private void pictureBox1_Click(object sender, EventArgs e)
{
    this.Cursor = new Cursor(Cursor.Current.Handle);
    int xCoordinate = Cursor.Position.X;
    int yCoordinate = Cursor.Position.Y;
}

private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
    int xCoordinate = e.X;
    int yCoordinate = e.Y;
}

实现此目标的最佳方法是什么?

可以通过判断一个点到圆心的距离是否小于圆的半径来判断一个点是否在圆内。在您的示例中,第一个圆的圆心为 (50,50),半径为 50。要测试单击的点是否在圆心的 50 像素范围内,请执行以下操作:

private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
    double xdiff = e.X - 50;
    double ydiff = e.Y - 50;
    double dist = Math.Sqrt(xdiff * xdiff + ydiff * ydiff);
    if (dist <= 50)
    {
      // do something here
    }
}

您可以使用 GraphicsPath and AddXXXX methods like AddEllipse to create the shape and then use IsVisible 方法来检查给定的 Point 是否在形状中。

例如:

public bool Contains(Rectangle ellipse, Point location)
{
    var contains = false;
    using(var gp= new System.Drawing.Drawing2D.GraphicsPath())
    {
        gp.AddEllipse(ellipse);
        contains = gp.IsVisible(location);
    }
    return contains;
}

使用这个想法,您可以检查所有类型的形状。

是的。给定圆心 (xc,yc) 和半径 r,坐标(x,y)在圆内,如果:(x-xc)2+(y-yc)2≤r2.

鉴于我们知道这一点,我们也知道您的圈子的中心位于 (50,50)(105,50) 并且每个都有 50 的半径。所以现在我们定义一个方法:

public static bool InsideCircle (int xc, int yc, int r, int x, int y) {
    int dx = xc-x;
    int dy = yc-y;
    return dx*dx+dy*dy <= r*r;
}

现在您可以使用:

private void pictureBox1_MouseUp(object sender, MouseEventArgs e) {
    int x = e.X;
    int y = e.Y;
    bool inA = InsideCircle(50,50,50,x,y);
    bool inB = InsideCircle(105,50,50,x,y);
    if(inA && inB) {
        C();
    } else if(inA) {
        B();
    } else if(inB) {
        D();
    } else {
        A();
    }
}

但是请注意,目前,您绘制的两个圆圈无论如何都不会重叠。

我认为您需要先检测实时鼠标位置。然后你需要设置你的形状的触发位置。然后是逻辑判断代码:如果mouse_position(x,y)在你shape的范围内,那么....

我以前写过类似的代码,你可以在这里下载代码:C#_mouse_hook_DEMO

demo 2有点像,可以满足你的要求。我将 space 的右侧 1/5 设置为触发事件

> if (e.X > (Screen.PrimaryScreen.Bounds.Width / 5 * 4))

 { 

}