2

フォーム上にいくつかの透明なコントロールを作成しています。各コントロールは六角形を表示し、それらはマップとしてグループ化されているため、六角形は端から端までです。もちろん、各ヘクスは正方形のコントロール内に含まれているため、隣接する各ヘクスと重なります。ヘクスの内側をクリックしてハイライト表示できるようにしたい。ただし、オーバーラップがないヘクスの中央をクリックしない限り、コントロールのスタック順序に応じて、クリックイベントは、必ずしも必要なコントロールではなく、一番上にあるコントロールによってピックアップされます。ですから、私が見ているように、私は2つのことをする必要があります。

  1. カーソルが六角形の内側にあることを確認する必要があります(各六角の端の間に小さなギャップがあります)。したがって、コントロールの隅の1つをクリックすると、そのコントロールはそのヘクスの外側にあるため、そのクリックに応答しません。
  2. クリックするとき、クリックしているヘクスを所有しているコントロールを決定する必要があります。
4

1 に答える 1

2

正確なコードの作成に時間を費やす必要があるため、コードを提供することはできませんが、どのようにそれを達成できるかについての提案があります...

1)マウスがクリックする可能性のあるすべてのコントロールを調べます。おそらく、すべてのコントロールに対するマウスの位置を計算し、重複するポイントを探すことでこれを行うことができます

2)すべての潜在的な候補を反復処理し、マウスポイントと各コントロールの中心点の間の距離を計算します(これは役立つ場合があります)。正しいコントロールは、最短距離のコントロールになります

あなたはこれのためにあなたの数学の頭を置く必要があるでしょう!


解決:

これは機能し、私はそれをテストしました。私が持っているもの:形状を描画するUserControl、これは「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 に答える