2

I'm trying to make a little graphics program that has a circle of diameter 100 on the screen and from the center of it, a line is coming out of it that is always attached to the mouse pointer until such time that the user does a click, and then the line is permanently drawn. It's exactly like MSPaint's line, except that starting point is always the center of the circle.

I tried a few things that DON'T work.

  1. I can get the line to appear only after a mouse-click. That's not what I want. I want the line to always be present and pivoting from the circle-center until the mouse is clicked and then it's then permanently on the screen.

  2. I can get a smeary thing where the line is always being drawn. It makes a sort of star shape, but that's not what I want either.

Basically, I want the same functionality that you have in MSPaint when you draw a line. What am I supposed to do? Draw the line and then erase it a second later, and then draw it again when the mouse is in a new position? I tried something like that, but it does a thing where it erases the background a little bit, and then the line is only drawn when the mouse is in motion, but not when the mouse is stationary.

If anyone can provide a code snippet, that'd be great. Or just some pseudo-code.

Is this the right pseudo code? Start: Left click and a line appears from center of circle to mouse tip Line stays there until a new mouse coordinate is made (how do I keep track)? Line from center of circle to original location gets erased New line is made to new location of mouse coordinates.

I think this something of a state-machine to use what I learned in digital class. How are states implemented in C#?

Any help would be appreciated, and thanks to everyone that can understand my question even though I'm probably not using the proper terminology.

user3832863
  • 97
  • 1
  • 12
  • 2
    The first thing you should do is think further. what you describe is very easy, but I don't think that you will want to stop there. Better plan for all you want to do! The 2nd thing is to understand the GDI+ graphics model, that is if you want to use Winforms.. Key here are the Paint event of the control or form you want to draw on and the MouseMove event.. - [Here is an example](http://stackoverflow.com/questions/28403514/drawing-a-moving-line-in-a-transparent-panel-in-c-sharp/28405275?s=11|0.0567#28405275) (Ignore the start of the answer, dealing with layering controls..!) – TaW Mar 06 '15 at 21:00
  • Any advice on where I can learn a bunch about low level graphics and GDI+? I want to do something that basically demonstrates principles from geometry textbooks. – user3832863 Mar 07 '15 at 06:30
  • 2
    Winforms and GDI+ are rather old/dated/mature technology. But still by far the most popular. There still are lots of tutorials out there. Additionally you may want to look over a few of my posts here, where I explain the basic ways to newbies like (this one about the difference between drawing onto the surface or into a bitmap)[http://stackoverflow.com/questions/27337825/picturebox-paintevent-with-other-method/27341797#27341797], [this one about hot to persist drawing](http://stackoverflow.com/questions/23701175/how-to-draw-static-or-dynamic-graphs-like-those/23779813#23779813) .. – TaW Mar 07 '15 at 09:24
  • 2
    ..(ignore the malicious downvote from a WPF fanatic!), or [this one](http://stackoverflow.com/questions/28403514/drawing-a-moving-line-in-a-transparent-panel-in-c-sharp/28405275#28405275) which details what you need to do to create a layered graphics program. - You also may want to check out [Bob Powell's site](http://bobpowell.net/beginnersgdi.aspx) which is a good mix of basics and advanced techniques. I still like [this book](http://www.amazon.co.uk/User-Interfaces-Windows-Controls-Developer/dp/1590590457) by Matthew MacDonald, which is about customizing your own controls.. – TaW Mar 07 '15 at 09:30

1 Answers1

4

So short answer is you will need some custom painting. The longer answer involves custom drawing, and event handling.

The other piece of code you need is a list of some sort to hold all of the lines. The code below creates a user control and does the custom painting without relying on a state machine. To test it, create a new project add a user control called UserControl1, and add it to a form. Make sure you tie into the listed events.

I tried to comment the relevant sections and this shows a quick and dirty way to do what you appear to be trying to do.

using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace CustomDrawingAndEvents
{
public partial class UserControl1 : UserControl
{
    private struct MyLine
    {
        public Point mStart;
        public Point mEnd;
        public MyLine(Point xStart, Point xEnd)
        {
            mStart = xStart;
            mEnd = xEnd;
        }
    }

    private List<MyLine> mLines;
    private Point mCircleCenter;
    private Point mMousePosition;

    public UserControl1()
    {
        InitializeComponent();
        mLines = new List<MyLine>();

        //Double Buffer to prevent flicker
        DoubleBuffered = true;
        //Create the center for our circle. For this just put it in the center of 
        //the control.
        mCircleCenter = new Point(this.Width / 2, this.Height / 2);
    }

    private void UserControl1_MouseClick(object sender, MouseEventArgs e)
    {
        //User clicked create a new line to add to the list.
        mLines.Add(new MyLine(mCircleCenter, e.Location));
    }

    private void UserControl1_MouseMove(object sender, MouseEventArgs e)
    {
        //Update mouse position
        mMousePosition = e.Location;
        //Make the control redraw itself
        Invalidate();
    }

    private void UserControl1_Paint(object sender, PaintEventArgs e)
    {
        //Create the rect with 100 width/height (subtract half the diameter to center the rect over the circle)
        Rectangle lCenterRect = new Rectangle(mCircleCenter.X - 50, mCircleCenter.Y - 50, 100, 100);

        //Draw our circle in the center of the control with a diameter of 100 
        e.Graphics.DrawEllipse(new Pen(Brushes.Black), lCenterRect);

        //Draw all of our saved lines
        foreach (MyLine lLine in mLines) 
            e.Graphics.DrawLine(new Pen(Brushes.Red), lLine.mStart, lLine.mEnd);            

        //Draw our active line from the center of the circle to
        //our mouse location
        e.Graphics.DrawLine(new Pen(Brushes.Blue), mCircleCenter, mMousePosition);
    }
}

}

  • Thank you it totally worked. I'm not supposed to say thank you in the comments, because it supposedly adds clutter to the discussion, but obviously you spent some time in your response. The least I can say is "Thank you". – user3832863 Mar 07 '15 at 16:33