Snipping tool laggy highlighter

2019-08-09 18:07发布

问题:

I trying to create a highlighter in C# Winforms. Most of the code i used is here Highlight effect like snipping tool But when i try to draw too fast it lags. Not sure what i'm doing wrong. Here is what i have tried.

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    Bitmap bmp = (Bitmap)pictureBox1.Image;
    using (Graphics g = Graphics.FromImage(pictureBox1.Image))
    {
        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
        g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
        IntPtr hBMP = bmp.GetHbitmap();
        IntPtr bDC = g.GetHdc();
        IntPtr mDC = CreateCompatibleDC(bDC);
        IntPtr oDC = SelectObject(mDC, hBMP);

        int useColor = System.Drawing.ColorTranslator.ToWin32(brush.Color);
        IntPtr pen = CreatePen(PS_SOLID, _w, (uint)useColor);
        IntPtr xDC = SelectObject(mDC, pen);
        SetROP2(mDC, R2_MASKPEN);
        Rectangle dest = new Rectangle(currentX - _x, currentY - _y, _w, _h);
        Rectangle(mDC, dest.Left, dest.Top, dest.Right, dest.Bottom);
        SetROP2(mDC, R2_COPYPEN);

        BitBlt(bDC, 0, 0, bmp.Width, bmp.Height, mDC, 0, 0, SRCCOPY);
        SelectObject(mDC, xDC);
        DeleteObject(pen);
        g.ReleaseHdc(bDC);
        SelectObject(mDC, oDC);
        DeleteDC(mDC);
        DeleteObject(hBMP);
    }
}

What I'm trying to do is:

Edit

bool draw = false;
int currentX = 0;
int currentY = 0;

//Rectangle width/height
int _w = 6;
int _h = 18

//These are just to center the cursor according to the width and height of rectangle.
int _x = 3; //(half of _w)
int _y = 9; //(half of _h)

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
    draw = true;
}

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left && draw == true)
    {
        currentX = e.X;
        currentY = e.Y;
        pictureBox1.Invalidate();
    }
}

回答1:

You need to store points in a list and then to have a smooth drawing, draw a curve based on those points using DrawCurve. Also you need to setup a wide pen with suitable settings (For example Round) for LineJoin, StartCap and EndCap, then you can have a highlight drawing like following:

List<List<Point>> Lines = new List<List<Point>>();
bool drawing = false;
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
    Lines.Add(new List<Point>());
    Lines.Last().Add(e.Location);
    drawing = true;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    if (drawing) { Lines.Last().Add(e.Location); pictureBox1.Invalidate(); }
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
    if (drawing)
    {
        this.drawing = false;
        Lines.Last().Add(e.Location);
        pictureBox1.Invalidate();
    }
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
    using (var pen = new Pen(Color.FromArgb(150, Color.Yellow), 30)
    {
        LineJoin = System.Drawing.Drawing2D.LineJoin.Round,
        StartCap = System.Drawing.Drawing2D.LineCap.Round,
        EndCap = System.Drawing.Drawing2D.LineCap.Round,
    })
        foreach (var item in Lines)
            e.Graphics.DrawCurve(pen, item.ToArray());
}