可以增强十字准线光标吗?

Enhanced crosshair cursor possible?

我发现了这个问题(和其他一些问题一样),但这是我目前实施的问题:

Crosshair cursor with additional lines in C#

如其所述,我可以直接在 IDE 中使用股票光标“十字”。这是做事的好方法。上面答案中指定的答案在屏幕上以给定的宽度/高度画了一个十字。例如:

private Cursor crossCursor(Pen pen, Brush brush, int x, int y)
{
    var pic = new Bitmap(x, y);
    Graphics gr = Graphics.FromImage(pic);

    var pathX = new GraphicsPath();
    var pathY = new GraphicsPath();
    pathX.AddLine(0, y / 2, x, y / 2);
    pathY.AddLine(x / 2, 0, x / 2, y);
    gr.DrawPath(pen, pathX);
    gr.DrawPath(pen, pathY);

    IntPtr ptr = pic.GetHicon();
    var c = new Cursor(ptr);
    return c;
}

我的问题是我希望我的十字准线延伸到查看区域的边界。为了在这里提供上下文,我有:

//Form
  //TableLayoutPanel
      //UserControl (fills the TableLayoutPanel visible area)

那么如何调整我的光标以使线条延伸(很像在 CAD 程序包中)?

谢谢。

更新:我试过从这里调用方法:

protected override void OnLoad(System.EventArgs e)
{
    Cursor = crossCursor(Pens.WhiteSmoke, Brushes.WhiteSmoke, Bounds.Width, Bounds.Height);
}

但这还不行,因为此时 Bounds 正在返回 150 x 150 的尺寸,这不是 TableLayoutPanel.

的尺寸

更新:我已将其调整为使用 Resize 处理程序,它确实改进了一些东西:

protected override void OnResize(EventArgs e)
{
    base.OnResize(e);

    Cursor = crossCursor(Pens.WhiteSmoke, Brushes.WhiteSmoke, Bounds.Width, Bounds.Height);
}

现在唯一的问题(我想这是有道理的)是​​当光标位于 central 时,光标只会占用视图的全部宽度和高度看法。一旦我在光标不调整的视图中移动。我总是想要一条 horizontal/vertical 线穿过鼠标位置(不仅仅是初始交叉)。

参见:

十字准线需要延长(较粗的红线)。要么我需要在鼠标移动时不断创建光标,要么以另一种方式构建两条线。怎么办?

我遇到了这个:

https://social.msdn.microsoft.com/Forums/vstudio/en-US/7bdbad6d-1f65-461b-8f0c-6ef4f243fa6b/crosshair-cursor-using-c?forum=csharpgeneral

因此,我现在不再更改光标对象,而是在控件 MouseMove 处理程序中绘制线条:

Region r = new Region();
r.Union(new Rectangle(0, lastY, this.Width, 1));
r.Union(new Rectangle(lastX, 0, 1, this.Height));
this.Invalidate(r);
this.Update();
Graphics g = Graphics.FromHwnd(this.Handle);
g.DrawLine(Pens.White, 0, e.Y, this.Width, e.Y);
g.DrawLine(Pens.White, e.X, 0, e.X, this.Height);
int intDiameter = 20;//the diameter of this circle
g.DrawEllipse(Pens.White, e.X - intDiameter / 2, e.Y - intDiameter / 2, 20, 20);
//to draw the circle
lastX = e.X;
lastY = e.Y;

它有效,但我这样做时屏幕闪烁很明显。

您不需要创建游标。您可以创建双缓冲控件并绘制交叉控件。

using System;
using System.Drawing;
using System.Windows.Forms;
public class DrawingSurface : Control
{
    Pen crossPen;
    Pen rectanglePen;
    Brush rectangleBrush;

    public DrawingSurface()
    {
        this.DoubleBuffered = true;
        this.ResizeRedraw = true;
        crossPen = new Pen(Color.Red, 2);
        rectangleBrush = new SolidBrush(Color.FromArgb(50, Color.Blue));
        rectanglePen = new Pen(Color.Blue, 1);
    }
    bool mouseDown = false;
    Point startPoint = Point.Empty;
    Point endPoint = Point.Empty;
    protected override void OnMouseDown(MouseEventArgs e)
    {
        startPoint = e.Location;
        mouseDown = true;
        base.OnMouseDown(e);
    }
    protected override void OnMouseUp(MouseEventArgs e)
    {
        mouseDown = false;
        base.OnMouseUp(e);
    }
    protected override void OnMouseMove(MouseEventArgs e)
    {
        endPoint = e.Location;
        this.Invalidate();
        base.OnMouseMove(e);
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        var g = e.Graphics;

        if (this.ClientRectangle.Contains(endPoint))
            DrawCross(e.Graphics, endPoint);

        if (mouseDown)
            DrawRectangle(e.Graphics, startPoint, endPoint);
    }

    void DrawCross(Graphics g, Point point)
    {
        g.DrawLine(crossPen, new Point(0, point.Y), new Point(Width, point.Y));
        g.DrawLine(crossPen, new Point(point.X, 0), new Point(point.X, Height));
    }
    void DrawRectangle(Graphics g, Point point1, Point point2)
    {
        var rectangle = new Rectangle(
            Math.Min(point1.X, point2.X), Math.Min(point1.Y, point2.Y),
            Math.Abs(point1.X - point2.X), Math.Abs(point1.Y - point2.Y));

        g.FillRectangle(rectangleBrush, rectangle);
        g.DrawRectangle(rectanglePen, rectangle);
    }
    protected override void Dispose(bool disposing)
    {
        crossPen.Dispose();
        rectanglePen.Dispose();
        rectangleBrush.Dispose();
        base.Dispose(disposing);
    }
}