0

i have a problem.

I'm writing a program that writes on it with a stylus.

First, i create a windows form with a panel.

enter image description here

second, this code:

using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;
using System.Diagnostics;
using System.Drawing.Drawing2D;

namespace testWrite
{
    public partial class Form1 : Form
    {
        Graphics g;
        int x = -1;
        int y = -1;
        bool moving = false;
        Pen pen;

        public Form1()
        {
            InitializeComponent();
            g = panel1.CreateGraphics();
            pen = new Pen(Color.Black, 5);
            pen.SetLineCap(System.Drawing.Drawing2D.LineCap.Round, System.Drawing.Drawing2D.LineCap.Round, System.Drawing.Drawing2D.DashCap.Round);
            pen.StartCap = System.Drawing.Drawing2D.LineCap.Round;
            pen.EndCap = System.Drawing.Drawing2D.LineCap.Round;
        }

        private void panel1_MouseMove(object sender, MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Left)
            {
                g.DrawLine(pen, new Point(x, y), e.Location);
                x = e.X;
                y = e.Y;
            }
        }

        private void panel1_MouseUp(object sender, MouseEventArgs e)
        {
            x = -1;
            y = -1;
            moving = false;
        }

        private void panel1_MouseDown(object sender, MouseEventArgs e)
        {
            x = e.X;
            y = e.Y;
            moving = true;
        }
    }
}

I use this app with a Wacom intuos

enter image description here

But the result is not so good because a few words are lost...haizzz

toi tên la trần

quang hieu

hello heloo

enter image description here

especially, when i write fast or the text is small.

when i write in Microsoft Paint, it is very good

enter image description here What is best way to to write in windows forms with pen-tablet like wacom intuos?

UPDATE 1: With cmt from TaW.

enter image description here

Thanks for your help. But, that's not what I need...

i was change my code to:

public partial class Form1 : Form
{
    List<Point> curPoints = new List<Point>();
    List<List<Point>> allPoints = new List<List<Point>>();

    public Form1()
    {
        InitializeComponent();
    }

    private void panel1_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button != MouseButtons.Left) return;
        // here we should check if the distance is more than a minimum!
        curPoints.Add(e.Location);
        // let it show
        panel1.Invalidate();
    }

    private void panel1_MouseUp(object sender, MouseEventArgs e)
    {
        if (curPoints.Count > 1)
        {
            // ToList creates a copy
            allPoints.Add(curPoints.ToList());
            curPoints.Clear();
        }
    }

    private void panel1_MouseDown(object sender, MouseEventArgs e)
    {
        if (curPoints.Count > 1)
        {
            // begin fresh line or curve
            curPoints.Clear();
            // startpoint
            curPoints.Add(e.Location);
        }
    }

    private void panel1_Paint(object sender, PaintEventArgs e)
    {
        // here you can use DrawLines or DrawCurve
        // current line
        if (curPoints.Count > 1) e.Graphics.DrawCurve(Pens.Red, curPoints.ToArray());
        // other lines or curves
        foreach (List<Point> points in allPoints)
            if (points.Count > 1) e.Graphics.DrawCurve(Pens.Red, points.ToArray());
    }
}

But nothing better. The result is worse...

enter image description here

I tried to write: "Hello my name is Hieu", but is not run...

Looks like a pen-tablet differs from a mouse when use to write. Because, with mouse i feel that is better in this code...

UPDATE 2:

With code by Idle_Mind. It will be fine if i set pen-tablet:

enter image description here

With setting "Click", it is not OK

enter image description here

How to fix it, i don't want to set "Double Click" to my pen !

Quang
  • 183
  • 2
  • 10
  • Step 1: Do not use wrong graphics methods, like CreateGraphics. Instead collect the points in the MOuseMove and Invalidate the Panel. Use DrawLines or DrawCurve in the Paint event. Also make the Panel DoubleBuffered. Also hold a List> for the collected Paoints and a Listy for the current line. [Example](https://stackoverflow.com/questions/26936109/how-do-i-save-a-winforms-panels-drawing-content-to-a-file/26938635#26938635) – TaW Jun 24 '20 at 09:39
  • Step 2: Plan for growth! If all you want to add is color, width and other Pen properties you can do it all by adding a currentPaen and an List allPens. But if you consider other tools, like brushes, shapes, text etc.. You should create a [DrawAction](https://stackoverflow.com/search?q=user%3A3152130+DrawAction+) class to hold all params and methods needed.. – TaW Jun 24 '20 at 11:59
  • Oh and don't forget to set the LineJoin to Round and the Miterlimit to Pen.Width/2 +1 as a rule of thumb – TaW Jun 24 '20 at 12:44
  • TaW, thank you. But, I was update my ask. Please look up again. – Quang Jun 24 '20 at 13:33
  • My example works fine here using either mouse or an Intuos4. - Make sur to [doublebuffer](https://stackoverflow.com/questions/44185298/update-datagridview-very-frequently/44188565#44188565) the Panel or, better yet, use a PictureBox. (Panels are containers and not really meant to draw on). PBox is doublebuffered out of the box. – TaW Jun 24 '20 at 13:50
  • Note that a single mousedown/Click will not work yet. One could easily add a little check in the mouseUp to either add a 2nd point 1-2 pixels off or to the Paint event to fill a circle at a single point.. – TaW Jun 24 '20 at 13:54
  • I have Update 2. This app run perfect if i set pen to Double click. – Quang Jun 25 '20 at 05:32
  • I can't confirm that either setting makes any difference at all! – TaW Jun 25 '20 at 07:47

1 Answers1

1

Here's my version...worked great for me. You might need to adjust your tablet settings so that it picks up everything correctly:

public partial class FormTablet : Form
{

    private Point lastPoint;
    private GraphicsPath GP = null;
    private List<GraphicsPath> GPs = new List<GraphicsPath>();

    public FormTablet()
    {
        InitializeComponent();
    }

    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
        pictureBox1.Invalidate();
    }

    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            lastPoint = new Point(e.X, e.Y);
            GP = new GraphicsPath();
            GP.AddLine(lastPoint, lastPoint);
            GPs.Add(GP);
        }
    }

    private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            Point pt = new Point(e.X, e.Y);
            GP.AddLine(lastPoint, pt);
            lastPoint = pt;
            pictureBox1.Invalidate();
        }
    }

    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        GP = null;
        pictureBox1.Invalidate();
    }

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        if (checkBox1.Checked)
        {
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        }
        using(Pen p = new Pen(Color.Black, (int)numericUpDown1.Value))
        {
            p.LineJoin = LineJoin.Round;
            p.MiterLimit = p.Width / 2;
            foreach (GraphicsPath path in GPs)
            {
                if (path.PathPoints.Count() > 2)
                {
                    // draw the path
                    e.Graphics.DrawPath(p, path);
                }
                else
                {
                    // just draw a single dot
                    Rectangle rc = new Rectangle(Point.Round(path.PathPoints[0]), new Size(1, 1));
                    rc.Inflate((int)numericUpDown1.Value, (int)numericUpDown1.Value);
                    e.Graphics.FillEllipse(Brushes.Black, rc);
                }
            }
        }            
    }

    private void numericUpDown1_ValueChanged(object sender, EventArgs e)
    {
        pictureBox1.Invalidate();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        GPs.Clear();
        pictureBox1.Invalidate();
    }

}
Idle_Mind
  • 38,363
  • 3
  • 29
  • 40
  • Hey @Idle_Mind, i was use your code, it better than my code. But, i do not know why some lines is lost when i move my stylus. It is diffirent with mouse. Please look in my Update... – Quang Jun 24 '20 at 15:20
  • Tablet pens are finicky sometimes. You may need to adjust its settings, or simply write SLOWER with the pen. – Idle_Mind Jun 24 '20 at 15:22
  • that code worked great if i set my pen to "Double Click", but if i set pen touch to tablet is "click" so it not work. Why is that??? – Quang Jun 24 '20 at 15:39
  • I have no idea; never used that particular tablet/pen combo. Try setting that "Tip Double Click Distance" to OFF? – Idle_Mind Jun 24 '20 at 15:48
  • Hi, is there a way the strokes painted in the picture box in above example can be saved as a picture? I tried using pictureBox1.Image.Save(). However, the pictureBox1.Image is null. The idea is to then pass it to an OCR for text recognition. Thank you. – user2039804 Oct 13 '22 at 11:52
  • @user2039804 My code draws to `e.Graphics` supplied in the Paint() event. You can use very similar code in a different method that instead uses a Graphics obtained from a Bitmap. See [Graphics.FromImage()](https://learn.microsoft.com/en-us/dotnet/api/system.drawing.graphics.fromimage?view=dotnet-plat-ext-6.0). – Idle_Mind Oct 15 '22 at 23:37