【问题标题】:How do I ensure the correct control gets clicked when controls are overlapping?当控件重叠时,如何确保单击正确的控件?
【发布时间】:2012-12-30 21:54:43
【问题描述】:

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

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

【问题讨论】:

  • 澄清一下,我们说的是 Winforms 还是 WPF?
  • 这是一个非常基本的 UI 可用性问题。它的行为就像它应该的那样,最上面的应该得到点击。如果您想允许用户选择另一个,那么您确实需要一个不同的用户界面。也许是一个组合框或箭头按钮来选择一个。
  • @HansPassant:如果它不起作用,这只是一个可用性问题。概念和要求是完全有效的 UI。
  • Winforms,基本上是为了让用户点击一个十六进制来使其成为某种颜色。此外,根据用户的偏好(5x5、10x10 等),地图可以有不同的大小,这就是为什么每个十六进制都在自己的控制之下。

标签: c# controls transparent overlapping


【解决方案1】:

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

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

2) 遍历所有潜在候选对象并计算鼠标点与每个控件中心点之间的距离 (this might help)。正确的控制将是距离最短的控制

你将需要在这门课上投入你的数学!


解决方案:

这行得通,我已经测试过了。我有:一个绘制形状的用户控件,这称为“ClickControl”。我所有的 ClickControl 都在一个名为 mainPanelPanel 内。每个 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
}

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

【讨论】:

  • 这可能正是我需要的!非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多