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:
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
lineclass 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
grahicsobject. in fact shouldn't ever usecreategraphicsin first place,graphicsobject never stay in scope , graphics produces not persist (i.e. survive minimize-maximize sequence)..also note how pass out
e.graphicsobject ofpaintevent's parameterslineinstances can draw currentgraphicsobject!to select thinner lines may modify distance check little..
the math taken directly form wikipedia.

Comments
Post a Comment