简体   繁体   English

选择矩形(通过鼠标在画布上绘制)无法识别位于该选择矩形内的矩形(C# WPF)

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

I am now really desperate.我现在真的很绝望。 I just can't get any further and in principle it shouldn't be that difficult.我只是无法更进一步,原则上它不应该那么困难。 I tried solving it the last 2 weeks.我尝试在过去 2 周内解决它。 The following task/problem: I have a canvas in my C# WPF project called “MarkPointsMap”, on which there are different kind of mark points (3 different kind of rectangles with different colors).以下任务/问题:我的 C# WPF 项目中有一个名为“MarkPointsMap”的 canvas 项目,上面有不同种类的标记点(3种不同类型的不同颜色的标记点) One MarkPointsMap can contain round about 3000-4000 different MarkPoints (Children of that canvas) all over across the MarkPointsMap.一个 MarkPointsMap 可以在整个 MarkPointsMap 中包含大约 3000-4000 个不同的 MarkPoints(该画布的子项)。 The positions of that MarkPoints are loaded from a.tab-file, which is converted into a list called “MarkPoints” and added as Children on the “MarkPointsMap” canvas after loading the respective.tab-file. MarkPoints 的位置从一个.tab 文件中加载,该文件被转换为一个名为“MarkPoints”的列表,并在加载相应的.tab 文件后作为子项添加到“MarkPointsMap”canvas 上。

This a screenshot of the MarkPointsMap:这是 MarkPointsMap 的屏幕截图: 这是 MarkPointsMap 的屏幕截图:

There are eg mostly small rectangles (the green ones), a few middle rectangles (the yellow ones) and two big rectangles (the red ones).例如,大部分是小矩形(绿色的),一些中间的矩形(黄色的)和两个大的矩形(红色的)。 Mulitple markpoints should be selected with a selection-rectangle.应使用选择矩形选择多个标记点。 In my project I can already draw the selection rectangle, but the “if this.selectRect.Contains(MarkPointsMap.Children)” (see below) part does not work.在我的项目中,我已经可以绘制选择矩形,但是“if this.selectRect.Contains(MarkPointsMap.Children)”(见下文)部分不起作用。

The selection-rectangle looks as follows:选择矩形如下所示:

选择矩形如下所示:

The following method “drawMarkPoints”, which is called after loading the.tab file in the program, draws the markpoints on the canvas “MarkPointsMap”:以下方法“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);
          
            }
        }
    }

The selection-rectangle is drawn in the canvas “MarkPointsMap” with the three Mouse-Events (MarkPointsMap_MouseDown, MarkPointsMap_MouseMove, MarkPointsMap_MouseUp):选择矩形在 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”
                
            }

        }
    }

Why doesn't this work?为什么这不起作用? I guess it has to do with the converting from rectangle (System.Windows.Shapes using derictive) to struct Rect: IFormattable.我想这与从矩形(使用 derictive 的 System.Windows.Shapes)到 struct Rect:IFormattable 的转换有关。 The “if (selectRect.Contains(itemRect)”, which is not reached should in perspective color all mark points, which are inside the selection-rectangle in red, then compute the Point (x-Coordinate, y-Coordinate) of the middle-point of the selection-rectangle and add this middle point back to the original.tab-file.未达到的“if (selectRect.Contains(itemRect)”应在透视图中将选择矩形内的所有标记点着色为红色,然后计算中间的点(x-Coordinate,y-Coordinate) -选择矩形的点并将这个中间点添加回 original.tab 文件。
Any ideas or hints, how I could continue?任何想法或提示,我该如何继续? Thanks in advance.提前致谢。 Best regards!此致!

It looks like your calculations are wrong.看来你的计算是错误的。 You are offsetting the selectRect .您正在抵消selectRect You are centering it relative to the rendered manualDragRect .您将其相对于渲染的manualDragRect This way you are testing a totally different area than the one you have defined by the rendered selection bounds.这样,您测试的区域与您通过呈现的选择范围定义的区域完全不同。

Additionally, you are capturing the mouse on the Canvas but release the capture on some different control.此外,您正在Canvas上捕获鼠标,但在某些不同的控件上释放捕获。 It should be released on the MarkPointsMap too.它也应该在MarkPointsMap上发布。 Also be careful with marking mouse events as handled.还要小心将鼠标事件标记为已处理。 If the input handling is not part of a custom control, you should generally avoid it.如果输入处理不是自定义控件的一部分,您通常应该避免使用它。

You should consider to use an ItemsControl with a Canvas as panel.您应该考虑使用带有CanvasItemsControl作为面板。 You can then move the drawing to the markup and define a DataTemplate for the MarkPoint data.然后,您可以将绘图移动到标记并为MarkPoint数据定义DataTemplate

I recommend to use the original Rect returned from the manualDragRect shape.我建议使用从manualDragRect形状返回的原始Rect This means you should remove the selectRect field and related computations:这意味着您应该删除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