0

I am having the user click a point on screen, and until they choose the second point, the line will follow the cursor. Once the second point is drawn it will stay. I am using a double buffer like so:

public void EnableDoubleBuffering()
{
    this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
}

I will call that function in the Form_Load();

I am doing the draw like so:

void draw(int x1, int y1, int x2, int y2)
{
    Graphics formGraphics = pictureEdit1.CreateGraphics();
    Pen myPen = new Pen(Color.Red, 3);
    formGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
    formGraphics.DrawLine(myPen, x1, y1, x2, y2);
    myPen.Dispose();
    formGraphics.Dispose();
 }

I repetatively call that function from the MouseMove event;

void pictureEdit1_MouseMove(object sender, MouseEventArgs e)
{
    if (click == 1 && !rightClicked)
    {
        pictureEdit1.Invalidate();
        trail.X = e.X;
        trail.Y = e.Y;
        draw(p1.X, p1.Y, trail.X, trail.Y);
    }
    else if (click != 1)
    {
        draw(p1.X, p1.Y, trail.X, trail.Y);
    }
}

There is a very slight flicker that occurs and it is driving me insane! Please help, thanks.

aguertin
  • 496
  • 4
  • 18
  • How about storing the points as fields of your form and drawing the line in `pictureEdit1`'s `OnPaint` method? – Jashaszun Jul 10 '14 at 22:25
  • 2
    Attack of the CreateGraphics! Use the paint event. Call the control's Invalidate method to get it to paint. – LarsTech Jul 10 '14 at 22:29
  • Thank you very much, it helped with the flicker. I have one last problem and that is once I invalidate(), but the user stops moving the mouse. When this happens it doesn't draw anymore. Should I use a System.Timer.Timer ? Once the timer elapses I draw again? What is the best approach? – aguertin Jul 10 '14 at 22:37
  • `System.Windows.Forms.Timer` – LarsTech Jul 10 '14 at 22:41
  • @user3781235 - What exactly are you trying to do? Are you trying to make it so that when they click a spot, a line follows their mouse until they click again? – Icemanind Jul 10 '14 at 22:41
  • _the user stops moving the mouse. When this happens it doesn't draw anymore._ ??? What should happen? When the user doesn't move the mouse - what do you expect?? – TaW Jul 10 '14 at 22:46
  • Are you trying to make it so that when they click a spot, a line follows their mouse until they click again? YES – aguertin Jul 10 '14 at 22:56
  • I don't know where people get the idea to use `CreateGraphics` for this. The documentation even contains [an example](http://msdn.microsoft.com/en-us/library/cyh3c8h8.aspx) that instructs otherwise. Also, unless you're on a very old version of C#, **please use `using` blocks**. – Cody Gray - on strike Jul 10 '14 at 23:01
  • BTW, *unless you're on a very old version of C#*, you might consider leaving archaic winforms behind and using [Current Technology](http://msdn.microsoft.com/en-us/library/ms754130(v=vs.110).aspx) instead. [Here](http://stackoverflow.com/questions/15469283/how-do-you-animate-a-line-on-a-canvas-in-c/15469477#15469477) is an example that shows how easy this is in relevant technologies without resorting to any of these horrible hacks ;) – Federico Berasategui Jul 10 '14 at 23:11
  • 1
    @HighCore - My code below looks simpler than your example you linked. – Icemanind Jul 10 '14 at 23:13
  • @icemanind try to do the `opacity` and `Bring to Front` and `Move the Line Randomly` things in my example using crappy useless winforms. Let's see then who's code is "simpler" ;) – Federico Berasategui Jul 10 '14 at 23:14
  • @icemanind please don't forget to create a separate data model totally independent from the UI implementation which can be perfectly `serialized` to, say an XML file ;) – Federico Berasategui Jul 10 '14 at 23:16
  • @HighCore - Opacity is simply one extra line: `var pen = new Pen(Color.FromArgb(128, 255, 255, 255), 10);`. Creating a custom class of line coordinates and a z-index, I could draw the lines in order of the z-index and do a bring-to-front easily. – Icemanind Jul 10 '14 at 23:16
  • @icemanind too much talking. I want to see your actual code. No retarded winforms flickering, please. – Federico Berasategui Jul 10 '14 at 23:17
  • @HighCore - If I add the `[Serializable]` tag to my custom class, I could make it easily serializable too. – Icemanind Jul 10 '14 at 23:18
  • @HighCore - Challenge Accepted! Give me a few minutes! – Icemanind Jul 10 '14 at 23:18
  • Fighting over which technology is better. I love it! There are reasons for using WinForms. i.e that is what you are told to use. – aguertin Jul 11 '14 at 03:04
  • @AnthonyGuertin you're *"told"*? by whom? why a manager who's got no idea about technologies and must be instructed properly by a developer?... I guess you may also like to be "told" to use COBOL then... – Federico Berasategui Jul 11 '14 at 03:13
  • Huh, you have no idea dude. We still use Pascal... – aguertin Jul 11 '14 at 03:18
  • @HighCore - You can see my final product by [clicking here](http://snk.to/f-ct9lrlik). Let me know what you think! – Icemanind Jul 11 '14 at 17:18
  • @Icemanind your selection adorner breaks badly if I set a line thickness of, say, 40. BTW I don't see the "move line randomly" feature anywhere in your code. and If you look at my code, the lines are painted by a (alpha blended) LinearGradientBrush consisting of 2 colors, rather than a single solid color. And no, your code isn't any "simpler" than mine, not to mention the horrible procedural "painting" stuff that looks like the stuff I used to do in QuickBasic when I was 10. – Federico Berasategui Jul 11 '14 at 18:44
  • @icemanind Pretty awesome man! Good job, I think it is funny that when you change the thickness of the line, the square containing it gets bigger to lol. – aguertin Jul 11 '14 at 19:08
  • @HighCore not sure why you insist on beating fellow developers down on their creations but I assure you it doesn't help our community of expanding knowledge with that attitude. – aguertin Jul 11 '14 at 19:10
  • @AnthonyGuertin I'm not "beating down" anyone. He stated that he could achieve the same thing I did in WPF, with "simpler" code in winforms, and that is really far from being true. winforms is a retarded useless technology, not sure why people insist in using that dinosaur crap. – Federico Berasategui Jul 11 '14 at 19:14
  • @HighCore - There probably is bugs. I couldn't possibly have tested for every possible thing. Adding a random move is simple. If you want, I could add that pretty easily, along with a save and load function. – Icemanind Jul 11 '14 at 19:17
  • @AnthonyGuertin - Thank you for the positive feedback! – Icemanind Jul 11 '14 at 19:18
  • @icemanind `I couldn't possibly have tested for every possible thing` - No, because you're too busy fighting against retarded useless winforms' incapabilities. I understand that, however that reinforces my point that people should be using current technology instead of insisting on using dinosaur crap and trying to hack stuff together and "hoping" that it will work. – Federico Berasategui Jul 11 '14 at 19:19
  • @HighCore I think saying it is useless is a bit exaggerated... Either way thank you for encouraging me to move away from WinForms into wpf. I am going to start teaching myself how to use it. – aguertin Jul 11 '14 at 19:21
  • @HighCore - All languages and all programming models are susceptible to bugs. There is no such thing as a perfect language and technology. WPF programs can have bugs just as easily as a WinForms application. – Icemanind Jul 11 '14 at 19:23
  • @AnthonyGuertin I seem to be the most exaggerated person in the history of mankind. winforms is useless. And retarded. – Federico Berasategui Jul 11 '14 at 19:24

1 Answers1

0

This code will do what you want, without any flicker. Keep in mind, I don't know what you want to do after the line is drawn, so it will vanish. But this should give you a pretty good idea of how to do this:

public partial class Form1 : Form
{
    private Point _firstPoint;
    private Point _secondPoint;
    private bool _hasClicked;

    public Form1()
    {
        InitializeComponent();

        _hasClicked = false;
        _firstPoint = new Point();
        _secondPoint = new Point();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private void pictureEdit1_MouseMove(object sender, MouseEventArgs e)
    {
        _secondPoint.X = e.X;
        _secondPoint.Y = e.Y;
        pictureEdit1.Refresh();
    }

    private void pictureEdit1_MouseUp(object sender, MouseEventArgs e)
    {
        if (!_hasClicked)
        {
            _firstPoint.X = e.X;
            _firstPoint.Y = e.Y;
        }


        _hasClicked = !_hasClicked;
        pictureEdit1.Refresh();
    }

    private void pictureEdit1_Paint(object sender, PaintEventArgs e)
    {
        if (_hasClicked)
            e.Graphics.DrawLine(Pens.Red, _firstPoint, _secondPoint);
    }
Icemanind
  • 47,519
  • 50
  • 171
  • 296