C # Drawing using gdi32.dll and System.Drawing.Graphics

So, I have some code that creates a highlight effect on top of a window with gdi32.dll, and I wonder if there is an easier way to do this with System.Drawing.Graphics? Mostly with gdi32.dll, I have to take a screenshot after drawing, publish it in my drawer, and then I can draw more things and change the color of the pen used. If I just try to change the thickness and color of the pen and draw on the screen again, change what I already painted.

Now I have a version of this that uses a System.Drawing.Graphicslot of math FillPolygon, but if I draw an area that I have already drawn, it just makes the area that I painted darker. It does not do this with gdi32.dll, which justr shades if you have not already shaded the area with the mouse. Any suggestions?

public partial class Form9 : Form
{
    private bool is_mouse_down { get; set; } // Will check if the mouse is down or not.

    private Color Pen_Color = new Color();

    private int Pen_Type { get; set; }

    private int Thickness { get; set; }

    private bool Start { get; set; }

    List<Point> Points = new List<Point>();

    public Form9()
    {
        InitializeComponent();

        pictureBox1.Dock = DockStyle.Fill;

        Pen_Color = Color.Blue;
        Pen_Type = 13; // Type = 9 for highlighter, Type = 13 for solid.
        Thickness = 2;
        Start = false;

        pictureBox1.MouseDown += pictureBox1_MouseDown;
        pictureBox1.MouseUp += pictureBox1_MouseUp;
        pictureBox1.MouseMove += pictureBox1_MouseMove;
        pictureBox1.Paint += pictureBox1_OnPaint;
    }

    private void DrawHighlight(Graphics g, Point[] usePoints, int brushSize, int penType, Color brushColor)
    {
        int useColor = System.Drawing.ColorTranslator.ToWin32(brushColor);
        IntPtr pen = GetImage.GDI32.CreatePen(GetImage.GDI32.PS_SOLID, brushSize, (uint)useColor);
        IntPtr hDC = g.GetHdc();
        IntPtr xDC = GetImage.GDI32.SelectObject(hDC, pen);
        GetImage.GDI32.SetROP2(hDC, penType);//GetImage.GDI32.R2_MASKPEN);
        for (int i = 1; i <= usePoints.Length - 1; i++)
        {
            Point p1 = usePoints[i - 1];
            Point p2 = usePoints[i];
            GetImage.GDI32.MoveToEx(hDC, p1.X, p1.Y, IntPtr.Zero);
            GetImage.GDI32.LineTo(hDC, p2.X, p2.Y);
        }
        GetImage.GDI32.SetROP2(hDC, GetImage.GDI32.R2_COPYPEN);
        GetImage.GDI32.SelectObject(hDC, xDC);
        GetImage.GDI32.DeleteObject(pen);
        g.ReleaseHdc(hDC);
    }

    private void pictureBox1_OnPaint(object sender, PaintEventArgs e)
    {
        if (Start)
        {
            base.OnPaint(e);
            if (is_mouse_down)
            {
                DrawHighlight(e.Graphics, Points.ToArray(), Thickness, Pen_Type, Pen_Color);
            }
        }
    }

    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        Points.Clear();

        Start = true;
        is_mouse_down = true;
    }

    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        is_mouse_down = false;

        using (Image img = CaptureScreen())
        {
            try
            {
                if (System.IO.File.Exists(Program.ProgramPath + @"\Temp\marked.bmp"))
                {
                    System.IO.File.Delete(Program.ProgramPath + @"\Temp\marked.bmp");
                }
            }
            catch (Exception Ex)
            {
                MessageBox.Show("File Delete Error" + Environment.NewLine + Convert.ToString(Ex));
            }

            try
            {
                img.Save(Program.ProgramPath + @"\Temp\marked.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
            }
            catch (Exception Ex)
            {
                MessageBox.Show("Unable to save Screenshot" + Environment.NewLine + Convert.ToString(Ex));
            }
        }

        if (System.IO.File.Exists(Program.ProgramPath + @"\Temp\marked.bmp"))
        {
            using (FileStream fs = new System.IO.FileStream(Program.ProgramPath + @"\Temp\marked.bmp", System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.Read))
            {
                pictureBox1.Image = Image.FromStream(fs);
            }
        }

        pictureBox1.Invalidate(); // Refreshes picturebox image.
    }

    public Image CaptureScreen()
    {
        GetImage gi = new GetImage();

        return gi.CaptureWindow(GetImage.User32.GetDesktopWindow());
    }

    private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        if (is_mouse_down == true) // Check to see if the mouse button is down while moving over the form.
        {
            Points.Add(new Point(e.X, e.Y));

            pictureBox1.Invalidate(); // Refreshes picturebox image.
        }
    }

Here are a couple of photos I'm talking about:

Usage System.Drawing.Graphics: Using <code> System.Drawing.Graphics </code>

Usage gdi32.dll: Using <code> gdi32.dll </code>

UPDATE

After testing some of your code ... I have weird stuff.

enter image description here

+4
source share
1 answer

This is a way to draw several independent strokes of a translucent color without accumulating alpha:

enter image description here

, :

List<List<Point>> strokes = new List<List<Point>>();
List<Point> currentStroke = new List<Point>();

private void canvas_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button.HasFlag(MouseButtons.Left))
    {
        currentStroke.Add(e.Location);
        if (currentStroke.Count == 1)
            currentStroke.Add(new Point(currentStroke[0].X + 1, 
                                        currentStroke[0].Y));
        canvasInvalidate();

    }
}

private void canvas_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button.HasFlag(MouseButtons.Left))
    {
        currentStroke.Add(e.Location);
        canvas.Invalidate();
    }
}

private void canvas_MouseUp(object sender, MouseEventArgs e)
{
    if (currentStroke.Count > 1)
    {
        strokes.Add(currentStroke.ToList());
        currentStroke.Clear();
    }
    canvas.Invalidate();
}

, . , GraphicsPath :

private void canvas_Paint(object sender, PaintEventArgs e)
{
    if (strokes.Count > 0 || currentStroke.Count > 0)
    {
        GraphicsPath gp = new GraphicsPath();
        gp.FillMode = FillMode.Winding;
        if (currentStroke.Count > 0)
        {
            gp.AddCurve(currentStroke.ToArray());
            gp.CloseFigure();
        }

        foreach (var stroke in strokes)
        {
            gp.AddCurve(stroke.ToArray());
            gp.CloseFigure();
        }
        using (SolidBrush b = new SolidBrush(Color.FromArgb(77, 177, 99, 22)))
        {
            e.Graphics.FillPath(b, gp);
        }
    }
}

, , , !

A Clear Save Button , Clears , DrawToBitmap .

. , canval DoubleBuffered!

Update:

, Pen . ( PixelFormat), :

- . Paint :

private void canvas_Paint(object sender, PaintEventArgs e)
{
    using (Bitmap bmp = new Bitmap(canvas.ClientSize.Width, 
                                   canvas.ClientSize.Height, PixelFormat.Format32bppPArgb))
    {
        PaintToBitmap(bmp);
        e.Graphics.DrawImage(bmp, 0, 0);
    }

, , :

private void PaintToBitmap(Bitmap bmp)
{
    Color overlayColor = Color.FromArgb(77, 22, 99, 99);
    using (Graphics g = Graphics.FromImage(bmp))
    using (Pen p = new Pen(overlayColor, 15f))
    {
        p.MiterLimit = p.Width / 2;
        p.EndCap = LineCap.Round;
        p.StartCap = LineCap.Round;
        p.LineJoin = LineJoin.Round;
        g.SmoothingMode = SmoothingMode.AntiAlias;
        if (currentStroke.Count > 0)
        {
            g.DrawCurve(p, currentStroke.ToArray());
        }

        foreach (var stroke in strokes)
            g.DrawCurve(p, stroke.ToArray());
    }
    SetAlphaOverlay(bmp, overlayColor);
}

, "" :

void SetAlphaOverlay(Bitmap bmp, Color col)
{
    Size s = bmp.Size;
    PixelFormat fmt = bmp.PixelFormat;
    Rectangle rect = new Rectangle(Point.Empty, s);
    BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, fmt);
    int size1 = bmpData.Stride * bmpData.Height;
    byte[] data = new byte[size1];
    System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, data, 0, size1);
    for (int y = 0; y < s.Height; y++)
    {
        for (int x = 0; x < s.Width; x++)
        {
            int index = y * bmpData.Stride + x * 4;
            if (data[index + 0] + data[index + 1] + data[index + 2] > 0)
            {

                data[index + 0] = col.B;
                data[index + 1] = col.G;
                data[index + 2] = col.R;
                data[index + 3] = col.A;
            }
        }
    }
    System.Runtime.InteropServices.Marshal.Copy(data, 0, bmpData.Scan0, data.Length);
    bmp.UnlockBits(bmpData);
}

LockBits, .

:

enter image description here

2:

, :

, 1- . :

MouseDown:

        currentStroke.Add(e.Location);
        if (cbx_Fill.Checked) 
            currentStroke.Add(e.Location);

PaintToBitmap:

        g.SmoothingMode = SmoothingMode.AntiAlias;
        if (currentStroke.Count > 0)
        {
            if (cbx_Fill.Checked)
                g.FillClosedCurve(b,  currentStroke.ToArray());
            else
                g.DrawCurve(p, currentStroke.ToArray());
        }

        foreach (var stroke in strokes)
            if (stroke[0]==stroke[1])
                g.FillClosedCurve(b,  stroke.ToArray());
            else
                g.DrawCurve(p, stroke.ToArray());

:

enter image description here

+6

Source: https://habr.com/ru/post/1685635/


All Articles