c# - How to draw line and select it in Panel -


my program can draw lines using canvas.drawline(). how click line , change color (select line)?

private list<point> coordfirst = new list<point>(); private list<point> coordlast = new list<point>(); public graphics canvas;          private void form1_load(object sender, eventargs e)         {             canvas=panel1.creategraphics();         } 

coordinate line stored in coordfirs & coodlast.

here suitable line class:

class line {     public color linecolor { get; set; }     public float linewidth { get; set; }     public bool selected { get; set; }     public point start { get; set; }     public point end { get; set; }      public line(color c, float w, point s, point e)     { linecolor = c; linewidth = w; start = s; end = e;    }      public void draw(graphics g)     { using (pen pen = new pen(linecolor, linewidth)) g.drawline(pen, start, end); }      public bool hittest(point pt)     {         // test if fall outside of bounding box:         if ((pt.x < start.x && pt.x < end.x) || (pt.x > start.x && pt.x > end.x) ||             (pt.y < start.y && pt.y < end.y) || (pt.y > start.y && pt.y > end.y))              return false;         // calculate distance:         float dy = end.y - start.y;         float dx = end.x - start.x;         float z = dy * pt.x - dx * pt.y + start.y * end.x - start.x * end.y;         float n = dy * dy + dx * dx;         float dist = (float)( math.abs(z) / math.sqrt(n));         // done:         return dist < linewidth / 2f;     }  } 

define list lines, @ class level:

    list<line> lines = new list<line>(); 

here how can initialize few lines:

for (int = 0; < 20; i++) lines.add(new line(color.black, 4f,      new point(r.next(panel1.width), r.next(panel1.height)),      new point(r.next(panel1.width), r.next(panel1.height)))); 

here result of clicking on crossing:

enter image description here

whenever add, change or remove line need make panel reflect news triggering paint event:

panel1.invalidate(); 

here paint event of panel:

private void panel1_paint(object sender, painteventargs e) {     e.graphics.smoothingmode = smoothingmode.antialias;     foreach (line l in lines) l.draw(e.graphics); } 

in mouseclick event test:

private void panel1_mouseclick(object sender, mouseeventargs e) {     foreach(line l in lines)              l.linecolor = l.hittest(e.location) ?  color.red : color.black;     panel1.invalidate(); } 

to avoid flicker don't use basic panel class isn't doublebuffered. instead use either picturebox or doublebuffered panel subclass:

class drawpanel : panel  {     public drawpanel ()   { doublebuffered = true; }   } 

notes:

  • there no such thing 'line' in winforms, pixels of various colors. select line need store it's 2 endpoints' coordinates , find out if have hit when clicking.

  • the above example shows how in math.

  • instead 1 test each line drawing onto bitmap , test pixel mouse has clicked. drawing bitmaps have math behind scenes , allocate space bitmaps, math more efficient..

  • yes line class looks little long such simple thing s line how short event codes are! that's because responsiblities belong!

  • also note the first rule of doing drawing in winforms is: never cache or store grahics object. in fact shouldn't ever use creategraphics in first place, graphics object never stay in scope , graphics produces not persist (i.e. survive minimize-maximize sequence)..

  • also note how pass out e.graphics object of paint event's parameters line instances can draw current graphics object!

  • to select thinner lines may modify distance check little..

  • the math taken directly form wikipedia.


Comments

Popular posts from this blog

resizing Telegram inline keyboard -

command line - How can a Python program background itself? -

php - "cURL error 28: Resolving timed out" on Wordpress on Azure App Service on Linux -