簡體   English   中英

選擇矩形(通過鼠標在畫布上繪制)無法識別位於該選擇矩形內的矩形(C# WPF)

[英]A selection-rectangle (drawn by mouse on canvas) does not recognize rectangles, which are inside that selection-rectangle (C# WPF)

我現在真的很絕望。 我只是無法更進一步,原則上它不應該那么困難。 我嘗試在過去 2 周內解決它。 以下任務/問題:我的 C# WPF 項目中有一個名為“MarkPointsMap”的 canvas 項目,上面有不同種類的標記點(3種不同類型的不同顏色的標記點) 一個 MarkPointsMap 可以在整個 MarkPointsMap 中包含大約 3000-4000 個不同的 MarkPoints(該畫布的子項)。 MarkPoints 的位置從一個.tab 文件中加載,該文件被轉換為一個名為“MarkPoints”的列表,並在加載相應的.tab 文件后作為子項添加到“MarkPointsMap”canvas 上。

這是 MarkPointsMap 的屏幕截圖: 這是 MarkPointsMap 的屏幕截圖:

例如,大部分是小矩形(綠色的),一些中間的矩形(黃色的)和兩個大的矩形(紅色的)。 應使用選擇矩形選擇多個標記點。 在我的項目中,我已經可以繪制選擇矩形,但是“if this.selectRect.Contains(MarkPointsMap.Children)”(見下文)部分不起作用。

選擇矩形如下所示:

選擇矩形如下所示:

以下方法“drawMarkPoints”,在程序中加載.tab文件后調用,在canvas“MarkPointsMap”上繪制標記點:

public void drawMarkPoints()
    {
        MarkPointsMap.Children.Clear();

        foreach (MarkPoint markpoint in this.Marks.markpoints)
        {
            if (markpoint.type.relevant)
            {
                Rectangle markpointArea = new Rectangle();
                markpointArea.Tag = markpoint;
                //!!
                SolidColorBrush mySolidColorBrush = new SolidColorBrush();
                mySolidColorBrush.Color = markpoint.fillColor;
                markpointArea.Fill = mySolidColorBrush;
                markpointArea.StrokeThickness = 0.2;
                markpointArea.Stroke = Brushes.Black;

                markpointArea.Width = markpoint.symbol.Width;
                markpointArea.Height = markpoint.symbol.Height;
                //set the markpoints in canvas 
                Canvas.SetLeft(markpointArea, getCanvasCoordinates(markpoint.center).X - 0.5 * markpoint.symbol.Width); 
                Canvas.SetTop(markpointArea, getCanvasCoordinates(markpoint.center).Y - 0.5 * markpoint.symbol.Height);

                MarkPointsMap.Children.Add(markpointArea);
          
            }
        }
    }

選擇矩形在 canvas“MarkPointsMap”中繪制,帶有三個鼠標事件(MarkPointsMap_MouseDown、MarkPointsMap_MouseMove、MarkPointsMap_MouseUp):

public Rect itemRect;
public Rect selectRect;
private point anchorPoint; 
private Rectangle manualDragRect = new Rectangle(); 

private void MarkPointsMap_MouseDown(object sender, MouseButtonEventArgs e)
    {
        if (e.ChangedButton == MouseButton.Left)
        {
            isLeftMouseButtonDownOnWindow = true;
            anchorPoint = e.MouseDevice.GetPosition(MarkPointsMap);
            MarkPointsMap.CaptureMouse();
            e.Handled = true;
            manualDragRect = new Rectangle
            {
                Stroke = Brushes.Red,
                StrokeThickness = 2
            };
            MarkPointsMap.Children.Add(manualDragRect); 
        }       
    }

private void MarkPointsMap_MouseMove(object sender, MouseEventArgs e)
    {
        if (!MarkPointsMap.IsMouseCaptured)
            return;

        Point location = e.MouseDevice.GetPosition(MarkPointsMap);
        double minX = Math.Min(location.X, anchorPoint.X);
        double minY = Math.Min(location.Y, anchorPoint.Y);
        double maxX = Math.Max(location.X, anchorPoint.X);
        double maxY = Math.Max(location.Y, anchorPoint.Y);

        Canvas.SetTop(manualDragRect, minY);
        Canvas.SetLeft(manualDragRect, minX);

        double height = maxY - minY;
        double width = maxX - minX;

        manualDragRect.Height = Math.Abs(height);
        manualDragRect.Width = Math.Abs(width);
        Point xy_2 = new Point((Canvas.GetLeft(manualDragRect) + 0.5 * width), (Canvas.GetTop(manualDragRect) + 0.5 * height));
        this.selectRect = new Rect(xy_2.X, xy_2.Y, width, height);
    }


private void MarkPointsMap _MouseUp(object sender, MouseButtonEventArgs e)
    {
        DefectMap.ReleaseMouseCapture();

        foreach (MarkPoint markpoint in this.Marks.markpoints) 
        {
            Rect itemRect = new Rect(markpoint.center.X, markpoint.center.Y, markpoint.symbol.Width, markpoint.symbol.Height);
            if (selectRect.Contains(itemRect))
            {
                MessageBox.Show("Test!"); // it does not reach this code, if I circle several markpoints with the red selection-rectangle called “selectRect”
                
            }

        }
    }

為什么這不起作用? 我想這與從矩形(使用 derictive 的 System.Windows.Shapes)到 struct Rect:IFormattable 的轉換有關。 未達到的“if (selectRect.Contains(itemRect)”應在透視圖中將選擇矩形內的所有標記點着色為紅色,然后計算中間的點(x-Coordinate,y-Coordinate) -選擇矩形的點並將這個中間點添加回 original.tab 文件。
任何想法或提示,我該如何繼續? 提前致謝。 此致!

看來你的計算是錯誤的。 您正在抵消selectRect 您將其相對於渲染的manualDragRect 這樣,您測試的區域與您通過呈現的選擇范圍定義的區域完全不同。

此外,您正在Canvas上捕獲鼠標,但在某些不同的控件上釋放捕獲。 它也應該在MarkPointsMap上發布。 還要小心將鼠標事件標記為已處理。 如果輸入處理不是自定義控件的一部分,您通常應該避免使用它。

您應該考慮使用帶有CanvasItemsControl作為面板。 然后,您可以將繪圖移動到標記並為MarkPoint數據定義DataTemplate

我建議使用從manualDragRect形狀返回的原始Rect 這意味着您應該刪除selectRect字段和相關計算:

private void MarkPointsMap_MouseUp(object sender, MouseButtonEventArgs e)
{
  MarkPointsMap.ReleaseMouseCapture();

  foreach (MarkPoint markpoint in this.Marks.markpoints)
  {
    Rect itemRect = new Rect(markpoint.center.X, markpoint.center.Y, markpoint.symbol.Width, markpoint.symbol.Height);

    Rect selectionBounds = manualDragRect.RenderedGeometry.Bounds;
    selectionBounds.Offset(Canvas.GetLeft(manualDragRect), Canvas.GetTop(manualDragRect));
    if (selectionBounds.Contains(itemRect))
    {
      MessageBox.Show("Test!");
    }

    // TODO::Calculate center of selectionBounds
    Point selectionBoundsCenter = ...;
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM