C# 实现捕捉到画布网格线

C# 实现捕捉到画布网格线,c#,wpf,wpf-controls,C#,Wpf,Wpf Controls,我对此感到有点困惑,但我有一个问题,那就是我的头总是绕着一只抓拍到网格上的鼠标。目前,我正在通过覆盖OnRender来绘制网格,就像这样 protected override void OnRender(DrawingContext drawingContext) { int numberOfVerticalLines = 8; int numberOfHorizontalLines = 8; Cell

我对此感到有点困惑,但我有一个问题,那就是我的头总是绕着一只抓拍到网格上的鼠标。目前,我正在通过覆盖
OnRender
来绘制网格,就像这样

 protected override void OnRender(DrawingContext drawingContext)
        {

            int numberOfVerticalLines = 8;
            int numberOfHorizontalLines = 8;

            CellHeight = this.ActualHeight / numberOfVerticalLines;
            CellWidth = this.ActualWidth / numberOfHorizontalLines;

            double verticalOffset = 0;
            double horizontalOffset = 0;

            Pen pen = new Pen(Stroke, StrokeThickness);

            pen.DashStyle = DashStyle;

            for (int i = 0; i <= numberOfHorizontalLines; i++)
            {
                for (int j = 0; j <= numberOfVerticalLines; j++)
                {

                    drawingContext.DrawLine(pen, new Point(horizontalOffset, verticalOffset), new Point(horizontalOffset, CellHeight + verticalOffset));

                    verticalOffset += CellHeight;
                }

                horizontalOffset += CellWidth;
                verticalOffset = 0;
            }

            horizontalOffset = 0;
            verticalOffset = 0;

            for (int i = 0; i <= numberOfVerticalLines; i++)
            {
                for (int j = 0; j <= numberOfHorizontalLines; j++)
                {
                    drawingContext.DrawLine(pen, new Point(horizontalOffset, verticalOffset), new Point(CellWidth + horizontalOffset, verticalOffset));

                    horizontalOffset += CellWidth;
                }

                verticalOffset += CellHeight;
                horizontalOffset = 0;
            }
        }
protected override void OnRender(DrawingContext DrawingContext)
{
int numberofverticalline=8;
int numberOfHorizontalLines=8;
CellHeight=此值。实际高度/垂直线数;
CellWidth=this.ActualWidth/numberOfHorizontalLines;
双垂直偏移=0;
双水平偏移=0;
钢笔=新钢笔(笔划、笔划厚度);
pen.DashStyle=DashStyle;

对于(int i=0;i一个答案的粗略开始:

int nearGridX = CellWidth * Math.Round( mouseX / CellWidth);
int nearGridY = CellHeight * Math.Round( mouseY / CellHeight);

一种基本方法是通过以下方式将鼠标的(x,y)与十字进行比较: 1.计算鼠标所在单元格宽度和高度的起点和终点;以及 2.将这两个间隔(宽度和高度)与实际鼠标(x,y)进行比较,以找到最近的单元格点

下面是一些快速组合的示例代码,用于演示捕捉:

/// <summary>
/// When left shift key is pressed we snap the mouse to the closest
/// intersection
/// </summary>
void MainWindow_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.LeftShift)
    {
        var p = GetSnappingPoint(Mouse.GetPosition(this), new Size(200, 200));
        SetCursorPos((int)p.X, (int)p.Y+20);
    }

}

[DllImport("User32.dll")]
private static extern bool SetCursorPos(int x, int y);

/// <summary>
/// Get snapping point by
/// </summary>
Point GetSnappingPoint(Point mouse,Size cellSize)
{
    //Get x interval based on cell width
    var xInterval = GetInterval(mouse.X, cellSize.Width);

    //Get y interal based in cell height
    var yInterval = GetInterval(mouse.Y, cellSize.Height);

    // return the point on cell grid closest to the mouseposition
    return new Point()
    {
        X = Math.Abs(xInterval.Lower - mouse.X) > Math.Abs(xInterval.Upper - mouse.X) ? xInterval.Upper : xInterval.Lower,
        Y = Math.Abs(yInterval.Lower - mouse.Y) > Math.Abs(yInterval.Upper - mouse.Y) ? yInterval.Upper : yInterval.Lower,
    };
}

/// <summary>
///  Find an interval of the celsize based on mouse position and size
/// </summary>
Interval GetInterval(double mousePos,double size)
{
    return new Interval()
    {
        Lower = ((int)(mousePos / size)) * size,
        Upper = ((int)(mousePos / size)) * size + size
    };
}

/// <summary>
/// Basic interval class
/// </summary>
class Interval
{
    public double Lower { get; set; }
    public double Upper { get; set; }
}
//
///当按下左shift键时,我们将鼠标捕捉到最近的位置
///交叉口
/// 
void main window_KeyDown(对象发送器,KeyEventArgs e)
{
if(e.Key==Key.LeftShift)
{
var p=GetSnappingPoint(Mouse.GetPosition(this),新大小(200200));
SetCursorPos((int)p.X,(int)p.Y+20);
}
}
[DllImport(“User32.dll”)]
私有静态外部bool SetCursorPos(intx,inty);
/// 
///获取捕捉点
/// 
Point GetSnappingPoint(点鼠标,大小cellSize)
{
//根据单元格宽度获取x间隔
var xInterval=GetInterval(mouse.X,cellSize.Width);
//获取基于单元格高度的y内部
var yInterval=GetInterval(mouse.Y,cellSize.Height);
//返回单元格网格上最靠近鼠标位置的点
返回新点()
{
X=Math.Abs(xInterval.Lower-mouse.X)>Math.Abs(xInterval.Upper-mouse.X)?xInterval.Upper:xInterval.Lower,
Y=Math.Abs(yInterval.Lower-mouse.Y)>Math.Abs(yInterval.Upper-mouse.Y)?yInterval.Upper:yInterval.Lower,
};
}
/// 
///根据鼠标位置和大小查找大小的间隔
/// 
Interval GetInterval(双鼠标点,双大小)
{
返回新间隔()
{
下限=((int)(鼠标点/大小))*大小,
上限=((int)(鼠标点/大小))*大小+大小
};
}
/// 
///基本区间类
/// 
课间休息
{
公共双下{get;set;}
公共双上{get;set;}
}

这将使您快速而不干净地捕捉到当前网格的左上角。这不考虑您是否更接近当前网格的底部或右侧。它只查看您所在的网格并将其扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑通扑似乎是一个很好的起点!出于某种原因,键控似乎从未触发。是的,我把它连接到了一个控件上:你说的“未校准”是什么意思?我在这里启动并运行它,捕捉就在这里…啊,真的吗?我在画一个椭圆,它应该捕捉到那里,有时它会在整个单元格之外绘制它们。嗯,我不知道椭圆(这不是你问题的一部分),但这段代码的作用是在按下左shift键时根据鼠标位置查找单元格边界的最近角点/交点。设置鼠标时的+20用于处理光标高度。使其工作到大约85%的准确度:)(当时正在用省略号进行测试,以显示电流和捕捉点,因此可以关闭以进行此操作)但在其他方面效果很好!感谢您的帮助!
xPos= mouseX - (mouseX % gridWidth);
yPos= mouseY - (mouseY % gridHeight);