2

我在一个表单上创建了许多透明控件,每个控件都显示一个十六进制形状,它们被分组为一个地图,这样六边形是边到边的。当然,每个十六进制都包含在一个方形控件中,因此它们与每个相邻的十六进制重叠。我希望能够在十六进制内单击以使其突出显示。但是,除非我在没有重叠的十六进制中间单击,否则根据控件的堆栈顺序,单击事件将被顶部的任何控件拾取,不一定是我想要的控件。所以在我看来,我需要做两件事:

  1. 我需要确保光标位于六角形内(每个六角形的边缘之间有一个小间隙)。因此,如果我单击控件的一个角,该控件将不会响应该单击,因为它位于十六进制之外。
  2. 当我单击时,我需要确定哪个控件拥有我单击的十六进制。
4

1 回答 1

2

我不能给你代码,因为我需要花一些时间来编写确切的代码,但我确实有一个关于如何实现它的建议......

1) 找出鼠标可能点击的所有控件。也许您可以通过计算鼠标相对于所有控件的位置并寻找重叠点来做到这一点

2)遍历所有潜在的候选并计算鼠标点和每个控件的中心点之间的距离(这可能会有所帮助)。正确的控制将是距离最短的控制

你将需要把你的数学放在这一点上!


解决方案:

这行得通,我已经测试过了。我有:一个绘制形状的用户控件,这称为“ClickControl”。我所有的 ClickControls 都在一个Panel被调用的mainPanel. 每个 ClickControl 都MouseClick注册了相同的事件,在本例中为control_MouseClick事件。考虑到所有这些,这里是示例代码:

void control_MouseClick(object sender, MouseEventArgs e)
{
    //get mouse point relative to panel
    var mousePoint = panelMain.PointToClient(Cursor.Position);
    int startX = mousePoint.X;
    int startY = mousePoint.Y;

    //store the best match as we find them
    ClickControl selected = null;
    double? closestDistance = null;

    //loop all controls to find the best match
    foreach (Control c in panelMain.Controls)
    {
        ClickControl control = c as ClickControl;
        if (control != null)
        {
            //calculate the center point of the control relative to the parent panel
            int endX = control.Location.X + (control.Width / 2);
            int endY = control.Location.Y + (control.Height / 2);

            //calculate the distance between the center point and the mouse point
            double distance = Math.Sqrt(Math.Pow(endX - startX, 2) + Math.Pow(endY - startY, 2));

            //if this one is closer then we store this as our best match and look for the next best match
            if (closestDistance == null || closestDistance > distance)
            {
                selected = control;
                closestDistance = distance;
            }
        }
    }

    //`selected` is now the correct control
}

我敢肯定,如果您遇到性能问题,可以进行大量优化,但这至少是一个工作的开始!

于 2013-01-16T14:59:39.147 回答