Roundbutton Windows Control-ever decreasing circles

Source: Internet
Author: User
Tags drawtext

This article from http://www.codeproject.com/KB/buttons/RoundButton.aspx

 

A Windows round button control in C # With designer support.

    • Download Demo project and source-83.4 KB

Introduction

Some time ago, I tried to find a nice round-button control. I couldn't find one, so in the time-honored tradition, I decided to write my own. I "almost" finished it, but for various reasons, it was consigned to the "come back to it later" category. in its inimitable style, "later" finally arrived, and armed with my shiny newMicrosoft Visual C #2005 express Edition, I decided to have a crack at finishing it.

Though I say it myself, I think the buttons look nice-you'll have to judge for yourself! They look even better "in the flesh", rather than as the seconds in this article.

Background

In my quest for a round button control, I came authentication ss a couple of articles (including one by the great man Chris Maunder himself !) Which seemed to me and my very small brain to have far too much complicated mathematics involved. also, I 'd been learning about graphics in C #, and doing a lot of experimenting with groovy things likePathgradientbrush, Taking much inspiration from the very excellent Bob Powell site. Probably, by chance, I forget exactly how, I stumbled upon the idea of layering ever decreasing circles filledLineargradientbrushEs andPathgradientbrushEs one abve the other to build up a passable 3-D button. The following images implements strate this:

Hover your cursor For a description

How it works

Well, putting lots of circles one on top of anotherIsHow it works, in essence. The control is derived fromButtonClass, andOverrideSOnpaintMethod, where all the drawing is done. I 've added some new properties:

    • Recessdepth-How far the button is set back into the containing surface.
    • Bevelheight-The size of the "outer" bevel of the button top.
    • Beveldepth-The size of the "inner" bevel.
    • Dome-Whether or not the button has a "rounded" Top.

These have all been added toButton appearanceCategory of the properties panel by decorating them with the appropriate attributes. In addition, I wrote a custom drop-down uitypeeditor forRecessdepthProperty. I wocould never have managed this without Chris sells 'excellent book Windows Forms programming in C #, and I recommend it highly-I won't attempt to explain how the uitypeeditor works, as it's covered in a sample online chapter which discusses all aspects of design time ide integration (although I do own the actual book too !).

NBTo getToolboxbitmapAttribute to work properly, I had to add this dummy class, as suggested by that man Bob Powell, again in this article: toolboxbitmap.

Collapse | Copy code
Internal ClassResfinder {//Trick from Bob Powell}... [Description ("Round (elliptical) button control"), Toolboxbitmap (Typeof(Resfinder ),"Roundbutton.images.roundbutton.bmp")]Public ClassRoundbutton: system. Windows. Forms. Button
Noteworthy sections of code

This is the overriddenOnpaintMethod. Nothing too exciting, but I 've got it for reference.

Collapse | Copy code
 Protected   Override   Void   Onpaint (Painteventargs e) {buttoncolor = This . Backcolor; edgecolor1 = controlpaint. Light (buttoncolor); edgecolor2 = controlpaint. Dark (buttoncolor); graphics G = E. graphics; G. smoothingmode = smoothingmode. antialias; rectangle buttonrect This . Clientrectangle; edgewidth = getedgewidth (buttonrect); fillbackground (G, buttonrect );If (Recessdepth> 0 ) {Drawrecess ( Ref G, Ref Buttonrect);} drawedges (G, Ref Buttonrect); shrinkshape ( Ref G, Ref Buttonrect, edgewidth); drawbutton (G, buttonrect); drawtext (G, buttonrect); setclickableregion ();}

next is the drawrecess method, which creates the definition of the button being set into the form surface. the blend object allows you to specify at which points within ss the rectangle, and by how much, the two colours in the lineargradientbrush are blended. I arrived at these parameters by trial and error until it looked right to me, so they are purely subjective. controlpaint. dark and controlpaint. light are extremely useful here, because they create lighter and darker shades of the parent background color. this, of course, assumes that the plugin sion we want to create is that of a form made of a solid piece of colored material, rather than one which is still gray but has been painted a different color. if that's what you 'd prefer, then simply change parent. backcolor to color. fromknowncolor (knowncolor. control) .

The interesting thing I found here was the "using this second smaller rectangle..." part. I use the same technique again inBuildgraphicspathMethod, and although it creates much smoother curves, I have no idea how or why it actually works. But then, how much of us really know how TV works ...?

Collapse | Copy code
 Protected   Virtual   Void Drawrecess ( Ref Graphics G, Ref Rectangle recessrect) {lineargradientbrush recessbrush = New Lineargradientbrush (recessrect, controlpaint. Dark (parent. backcolor), controlpaint. lightlight (parent. backcolor), getlightangle (angle. Up )); //  Blend colours for realism Blend recessblend = New Blend (); recessblend. Positions = New   Float [] { 0 . 0f,. 2f,. 4f,. 6f,. 8f, 1 . 0f}; recessblend. Factors = New   Float [] {. 2f,. 2f,. 4f,. 4f, 1f, 1f}; recessbrush. Blend = recessblend; //  Using this second smaller rectangle      //  Smooths the edges-don't know why ...? Rectangle rect2 = recessrect; shrinkshape ( Ref G, Ref Rect2, 1 ); Fillshape (G, recessbrush, rect2); shrinkshape ( Ref G, Ref Recessrect, recessdepth ); //  Orig }

You'll notice a copious amountShrinkshape (RefG,RefEdgerect,1);Statements in the source. This is the method by which the "ever decreasing circles" are created. I useRefParameter so that the rectangle in question just keeps getting smaller.

To draw the domed top, I simply use this bit of code inDrawbuttonMethod. The default valueCcolorIsWhite, So if we want a domed top, we setCentercolorTo White, and calculateCenterpointBased on the size of the button.

Collapse | Copy code
 pgb. centercolor = buttoncolor;  If  (dome) {pgb. centercolor = ccolor; pgb. centerpoint =  New  pointf (buttonrect. X + buttonrect. width/ 8  + buttonpressoffset, buttonrect. Y + buttonrect. height/ 8  + buttonpressoffset);} fillshape (G, pgb, buttonrect); 

Drawing the text on the button is accomplished withDrawtextMethod, shown below. It usesFontAndForecolorProperties inherited from the baseButtonClass. I used myVerticalstringClass to write upright text if the button's height is more than twice its width.VerticalstringWas the subject of a previous codeproject article here, and I 've got the source in the project download for completeness. I also had to ensure that where possible, the button text stays within the bounds of the button. as part of this process, I had to convert the alignment of the text fromContentalignmentToStringalignment. Finally, I check to see if the button is disabled, and if so, I "gray out" the text.

Collapse | Copy code
Protected   Void Drawtext (Graphics g, rectangle textrect) {labelstrfmt = New Stringformat (); lablabelbrush = New Solidbrush ( This . Forecolor); labelfont = This . Font; //  Get the caller-specified font Vs = New Verticalstring (); vs. textspread =. 75 ; // Check for tall button, and write text vertically if necessary      Bool Verticaltext = False ; If (Textrect. Height> textrect. Width * 2 ) {Verticaltext = True ;} //  Convert the text alignment from      //  Contentalignment to stringalignment Labelstrfmt. Alignment = converttohoralign ( This . Textalign); labelstrfmt. linealignment = converttovertalign ( This . Textalign ); //  If horizontal text is not horizontally centred,      //  Or vertical text is not vertically centred,      //  Shrink the rectangle so that the text doesn't stray outside the ellipse      If ((! Verticaltext & (labelstrfmt. linealignment! = Stringalignment. Center) | (verticaltext & (labelstrfmt. Alignment! = Stringalignment. Center) {textrect. Inflate (-( Int ) (Textrect. width/7. 5 ),-( Int ) (Textrect. Height/7. 5 );} Textrect. offset (buttonpressoffset, buttonpressoffset ); //  Apply the offset if we 've been clicked      //  If button is not enabled, "Gray out" the text.      If (! This. enabled ){ //  Write the White "embossing effect" text at an offset Textrect. offset (1 , 1 ); Labelbrush. Color = controlpaint. lightlight (buttoncolor); writestring (verticaltext, G, textrect ); //  Restore original text POs, and set text color to Gray. Textrect. offset (-1,-1); labelbrush. Color = color. Gray ;} //  Write the text Writestring (verticaltext, G, textrect );}

The specified sion of the button being pressed is achieved in the two small methods below. When the user presses the button,ButtonpressoffsetVariable is set to 1, and the virtual light angle is altered so that the top left of the button becomes dark, and the bottom right becomes light, creating the impression that the button has receded into the form surface. when the button is released, the values revert to normal.

Collapse | Copy code
Protected VoidButtondown () {lightangle = angle. Down; buttonpressoffset =1;This. Invalidate ();}Protected VoidButtonup () {lightangle = angle. up; buttonpressoffset =0;This. Invalidate ();}
Finally, a couple of points...

TheRoundbuttonControl only supportsFlatstyle. Standard. I wrote some codeFlatstyle. FlatAndFlatstyle. Popup, Which worked OK, but I wasn't completely happy with either the Code or the results, so I took it out.

If you look at the source, you might notice a region calledOverrideAble shape-specific methods, Containing uninspiring methods like these:

Collapse | Copy code
 
Protected Virtual VoidAddshape (graphicspath gpath, rectangle rect) {gpath. addellipse (rect );}Protected Virtual VoidDrawshape (Graphics g, Pen, rectangle rect) {G. drawellipse (pen, rect );}

Why not just callAddellipse, RatherAddshape? Well, I 've also written some other classes suchTrianglebuttonAndDiamondbuttonWhich obviusly don't useAddellipse, Or anything else to do with ellipses, so I wanted to be ableOverrideThe methods in the Code for the other shapes. I didn't include the other shapes here, partly because I decided that some of the Code had got a bit messy, and needed more reworking than I had time to do now, and because frankly they didn't look as good as the round ones!

To use the buttons in another project, just add a referenceRoundbutton. dll, AndRoundbuttonIcon shoshould appear in the toolbox. (You might have to do tools-> choose toolbox items to add it manually .)

That's the end of the article. I hope you found it interesting, and like the buttons!

License

This article has no explicit license attached to it but may contain in usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.