c# - Allow custom control to correctly scroll out of view -
i have custom control consists of filled rounded rectangle text. (the actual control more complicated code shown here has sames symptoms.) attached instances of control panel, , made panel child of panel autoscroll = true. thought enough correct scroll behavior, if scroll such left side of control should go off left side of panel sticks , control shrinks. same scrolling such control should go off @ top. (bottom , right seem not problem.) here sample code (requires reference system.windows.forms , system.drawing.) using visual studio 2010 .net 4 client on windows.
using system; using system.drawing; using system.drawing.drawing2d; using system.windows.forms; namespace customcontrolscrolltest { static class program { [stathread] static void main() { application.enablevisualstyles(); application.setcompatibletextrenderingdefault(false); application.run(new form1()); } } // form dock = fill panel autoscroll turned on, , nested panel // few custom roundrectcontrols. public class form1 : form { panel autoscrollpanel; panel rectpanel; public form1() { size = new size(300, 200); autoscrollpanel = new panel(); autoscrollpanel.dock = dockstyle.fill; autoscrollpanel.autoscroll = true; autoscrollpanel.autoscrollminsize = new size(600, 450); autoscrollpanel.resize += autoscrollpanel_resize; autoscrollpanel.scroll += autoscrollpanel_scroll; controls.add(autoscrollpanel); rectpanel = new panel(); rectpanel.size = autoscrollpanel.autoscrollminsize; rectpanel.controls.addrange(new roundrectcontrol[] { new roundrectcontrol(), new roundrectcontrol(), new roundrectcontrol(), new roundrectcontrol(), new roundrectcontrol() }); foreach (control c in rectpanel.controls) { c.click += c_click; } autoscrollpanel.controls.add(rectpanel); placeboxes(); } // want able recalculate boxes position @ time // in real program occurs due model changes void c_click(object sender, eventargs e) { placeboxes(); } void autoscrollpanel_scroll(object sender, scrolleventargs e) { refresh(); } void autoscrollpanel_resize(object sender, eventargs e) { refresh(); } private void placeboxes() { (int = 0; < rectpanel.controls.count; ++i) { int j = + 1; var node = rectpanel.controls[i] roundrectcontrol; if (node != null) { node.title = "hello (" + j + ")"; node.location = new point(i * 100, j * 75); node.visible = true; } } } } // rounded rectangle filled blue black border , white text // size determined text public class roundrectcontrol : control { public roundrectcontrol() { var f = systemfonts.messageboxfont; titlefont = new font(f.name, f.sizeinpoints + 2, fontstyle.bold, graphicsunit.point); resizeredraw = true; } protected override void onpaint(painteventargs e) { base.onpaint(e); var g = e.graphics; var left = e.cliprectangle.x; var right = left + titlewidth + 2 * radius; var top = e.cliprectangle.y; var bottom = top + nodeheight + 2 * radius; var r2 = 2 * radius; using (var path = new graphicspath()) { path.addarc(left, bottom - r2, r2, r2, 90, 90); path.addarc(left, top, r2, r2, 180, 90); path.addarc(right - r2, top, r2, r2, 270, 90); path.addarc(right - r2, bottom - r2, r2, r2, 0, 90); path.closefigure(); g.fillpath(titlebrush, path); g.drawpath(borderpen, path); } g.drawstring(title, titlefont, titletextbrush, left + radius, top + radius); } private string title; public string title { { return title; } set { title = value; size = getsize(); invalidate(); } } private brush titlebrush = brushes.blue; private brush titletextbrush = brushes.white; private pen borderpen = pens.black; private size getsize() { var g = creategraphics(); var titlesize = g.measurestring(title, titlefont); titlewidth = (int)titlesize.width; nodeheight = (int)titlesize.height; return new size(titlewidth + 2 * radius + 1, nodeheight + 2 * radius + 1); } public override size getpreferredsize(size proposedsize) { return getsize(); } private int titlewidth; private int nodeheight; private font titlefont; private int radius = 5; } }
try this
protected override void onpaint(painteventargs e) { base.onpaint(e); var g = e.graphics; //total width , height of rounded rectangle var width = titlewidth + 2 * radius + 1; var height = nodeheight + 2 * radius + 1; var left = e.cliprectangle.x; var top = e.cliprectangle.y; //check if clipping occurs. if yes, set 0 if (width > e.cliprectangle.width) { left = 0; // *= -1; } //check if clipping occurs.if yes, set 0 if (height > e.cliprectangle.height) { top = 0; // *= -1 } var right = left + titlewidth + 2 * radius; var bottom = top + nodeheight + 2 * radius; var r2 = 2 * radius; using (var path = new graphicspath()) { path.addarc(left, bottom - r2, r2, r2, 90, 90); path.addarc(left, top, r2, r2, 180, 90); path.addarc(right - r2, top, r2, r2, 270, 90); path.addarc(right - r2, bottom - r2, r2, r2, 0, 90); path.closefigure(); g.fillpath(titlebrush, path); g.drawpath(borderpen, path); } g.drawstring(title, titlefont, titletextbrush, left + radius, top + radius); }
the problem when scrolling right(rects moving left, e.cliprectangle.width becomes smaller) , rectangle goes out of area, e.cliprectangle.x positive! in case set zero. e.cliprectangle.x can not negative, if invert it(solution before edit) becomes zero.
edit
you can do
var left = 0; var right = left + titlewidth + 2 * radius; var top = 0; var bottom = top + nodeheight + 2 * radius;
both working
you can use these styles
this.setstyle(controlstyles.doublebuffer, true); this.setstyle(controlstyles.userpaint, true); this.setstyle(controlstyles.allpaintinginwmpaint, true);
to avoid flickering
valter
Comments
Post a Comment