Yesterday shared a circular scroll bar control that shares a Cue box style form today. The code is as follows:
/// <summary> ///inherit from form, but set FormBorderStyle to none/// </summary> Public Partial classTipform:form { PublicTipform () {InitializeComponent (); } /// <summary> ///mouse down position, easy to move the form/// </summary> PrivatePoint Ptmousedown; /// <summary> ///the coordinate position of the lower part of the form/// </summary> PrivatePoint position; PublicPoint Position {Get{returnposition;} Set{Position=value; SetPosition (position); } } /// <summary> ///set the corner radius of a window/// </summary> Private intRadius = -; Public intRadius {Get{returnradius;} Set{radius =value;} } /// <summary> ///overriding the OnPaint method to draw the form border/// </summary> /// <param name= "E" ></param> protected Override voidOnPaint (PaintEventArgs e) {Base. OnPaint (e); Graphics Graph=E.graphics; Graph. SmoothingMode=Smoothingmode.antialias; GraphicsPath Path=Gettippath (ClientRectangle); Rectangle rect=NewRectangle (clientrectangle.x, Clientrectangle.y, Clientrectangle.width, clientrectangle.height); Rect. Inflate (-1, -1); GraphicsPath Border=Gettippath (rect); GraphicsPath Curve=NewGraphicsPath (); Graph. DrawPath (NewPen (Color.Black,2), border); This. Region =NewRegion (path); } /// <summary> ///set the form position based on the vertex position in the lower part of the form/// </summary> /// <param name= "pos" >screen coordinate point</param> Public voidsetposition (Point pos) { This. Location =NewPoint (pos. X-size.width/2, Pos. Y-size.height); } /// <summary> ///Gets the tip style path based on the ClientRectangle property of the current form/// </summary> /// <param name= "rect" ></param> /// <returns></returns> PrivateGraphicsPath Gettippath (Rectangle rect) {GraphicsPath path=NewGraphicsPath (); intHeight = rect. Height-Radius; Path. Startfigure (); Path. AddArc (rect. X, Rect. Y, radius, radius, the, - -); Path. AddArc (rect. X, Rect. Y+ Height- radius, radius, radius, the, - -); Path. AddLine (NewPoint (rect. X + Radius/2, Rect. Y +height),NewPoint (rect. X + rect. Width/2-Radius/2, Rect. Y+height)); Path. AddLine (NewPoint (rect. X + rect. Width/2-Radius/2, Rect. Y+height),NewPoint (rect. X + rect. Width/2, Rect. Y + height +Radius)); Path. AddLine (NewPoint (rect. X + rect. Width/2, Rect. Y + height +Radius),NewPoint (rect. X + rect. Width/2+ Radius/2, Rect. Y+height)); Path. AddLine (NewPoint (rect. X + rect. Width/2+ Radius/2, Rect. Y+height),NewPoint (rect. X + rect. Width-radius/2, Rect. Y+height)); Path. AddArc (rect. X+ Rect. Width-radius, rect. Y+ Height-radius, radius, radius, -, - -); Path. AddArc (rect. X+ Rect. Width-Radius, Rect. Y, radius, radius,0, - -); Path. AddLine (NewPoint (rect. X + rect. Width-radius/2, Rect. Y),NewPoint (rect. X + Radius/2, Rect. Y)); Path. Closefigure (); returnpath; } Private voidButton1_Click (Objectsender, EventArgs e) {Close (); } /// <summary> ///Mouse Move Event/// </summary> /// <param name= "Sender" ></param> /// <param name= "E" ></param> Private voidTipform_mousemove (Objectsender, MouseEventArgs e) { if(E.button = =mousebuttons.left) {Point pt=e.location; Location=NewPoint (Location.x + pt. Xptmousedown.x, Location.y+ Pt. YPTMOUSEDOWN.Y); } } /// <summary> ///Mouse Down Events/// </summary> /// <param name= "Sender" ></param> /// <param name= "E" ></param> Private voidTipform_mousedown (Objectsender, MouseEventArgs e) { if(E.button = =mousebuttons.left) {Ptmousedown=e.location; } } Private voidbtnClose_Click (Objectsender, EventArgs e) {Close (); } Private voidTipform_sizechanged (Objectsender, EventArgs e) {Point pt=NewPoint (clientrectangle.x + Clientrectangle.width-radius/4- +, Clientrectangle.y+ Radius/4); Btnclose.location=pt; } }
This is done primarily by creating a path that represents the outline of the form, and then setting the region property of the form based on that path. Here are the effects:
WinForm the self-drawn cue box style form