C # star rating Control

Source: Internet
Author: User
ArticleDirectory
    • Constructor
    • Testing and using the control

This article from http://www.codeproject.com/KB/miscctrl/cs_star_rating_control.aspx

 

A c # star rating control.

 

    • Download Demo project-13.3 KB
    • Download source-5.03 KB

Introduction

This is a control similar to one used on the Netflix movie website, and one used by the iTunes and Microsoft Media Player to rate the songs in the song library.

Background

There is an implementation of such a control in C ++, which can be found here: starcontrol.

This article and code were influenced by a recently published msdn magazine article by Duncan macenzie, which is available here: creating a five-star rating control. His implementation is in Visual Basic. net.

This control is implemented in C #.

The Code
    • Create a class library project.
    • Inherit fromSystem. Windows. Forms. Control.
    • Add a project reference toSystem. Windows. Forms. dll.

This is not done automatically, and can be done by Right clicking on "references" in the Solution Explorer and choosing the wanted DLL.

Constructor Collapse | Copy code
PublicStarratingcontrol () {setstyle (controlstyles. allpaintinginwmpaint,True); Setstyle (controlstyles. userpaint,True); Setstyle (controlstyles. doublebuffer,True); Setstyle (controlstyles. resizeredraw,True); Width =120; Height =18; M_starareas =NewRectangle [starcount];}
Collapse | Copy code
 
>>> Setstyle (controlstyles. allpaintinginwmpaint,True);

This lowers the flickering during background painting by telling the control to ignoreWm_erasebkgndMessage. This only works however whenControlstyles. userpaintControl style is set.

Collapse | Copy code
 
>>> Setstyle (controlstyle. userpaint,True);

This indicates that the control is going to paint itself.

Collapse | Copy code
 
>>> Setstyle (controlstyles. doublebuffer,True);

This indicates that the control will use double buffering to draw itself. This will also reduce flicker.Controlstyle. userpaintAndControlstyle. allpaintinwmpaintShocould be set in conjunction with this bit.

Collapse | Copy code
 
>>> Setstyle (controlstyles. resizeredraw,True);

This indicates that the control is to redraw itself upon being resized.

Leftmargin,Rightmargin,Topmargin, AndBottommarginAre properties exposing the following private data members:

Collapse | Copy code
 
Private IntM_leftmargin =2;Private IntM_rightmargin =2;Private IntM_topmargin =2;Private IntM_bottommargin =2;

The public properties are mostly of the form:

Collapse | Copy code
Public IntLeftmargin {Get{ReturnM_leftmargin ;}Set{If(M_leftmargin! = Value) {m_leftmargin = value; invalidate ();}}}

Please notice that setting the property forces a redraw of the control if the value of the margin changes. this logic also holds for some of the other properties dealing with modifiable Visual Properties of the control, such as the property exposing the number of stars to draw.

Collapse | Copy code
 Protected  Override   Void   Onpaint (Painteventargs PE) {PE. Graphics. Clear (backcolor ); Int Starwidth = (width-(leftmargin + rightmargin + (starspacing * (starcount- 1 )/Starcount; Int Starheight = (height-(topmargin + bottommargin); rectangle drawarea = New Rectangle (leftmargin, topmargin, starwidth, starheight ); For (Int I = 0 ; I <starcount; ++ I) {m_starareas [I]. x = drawarea. X-starspacing/ 2 ; M_starareas [I]. Y = drawarea. Y; m_starareas [I]. width = drawarea. Width + starspacing/ 2 ; M_starareas [I]. Height = drawarea. height; drawstar (PE. Graphics, drawarea, I); drawarea. x + = drawarea. Width + starspacing ;} Base . Onpaint (PE );}

All of the drawing is done in this method. For the implementation of this method, we will need to add a referenceSystem. Drawing. dll.

Collapse | Copy code
 
>>> PE. Graphics. Clear (This. Backcolor)

This erases the background.

Collapse | Copy code
 
IntStarwidth = (width-(leftmargin + rightmargin + (m_starspacing * (m_starcount-1)/m_starcount;IntStarheight = (height-(topmargin + bottommargin ));

This calculates the width and height of the stars given the control width and height and the inner margins.

Then we draw each of the stars.

Collapse | Copy code
 Protected   Void Drawstar (Graphics g, rectangle rect, Int Starareaindex) {brush fillbrush; pen outlinepen = New Pen (outlinecolor, outlinethickness ); If (M_hovering & m_hoverstar> starareaindex) {fillbrush = New Lineargradientbrush (rect, hovercolor, backcolor, lineargradientmode. forwarddiagonal );} Else  If ((! M_hovering) & m_selectedstar> starareaindex) {fillbrush = New Lineargradientbrush (rect, selectedcolor, backcolor, lineargradientmode. forwarddiagonal );} Else {Fillbrush = New Solidbrush (backcolor);} pointf [] P = New Pointf [ 10 ]; P [ 0 ]. X = rect. x + (rect. width/ 2 ); P [ 0 ]. Y = rect. Y; P [ 1 ]. X = rect. x + ( 42 * Rect. width/ 64 ); P [ 1 ]. Y = rect. Y + ( 19 * Rect. Height/ 64 ); P [ 2 ]. X = rect. x + rect. width; P [ 2 ]. Y = rect. Y + ( 22 * Rect. Height/ 64 ); P [ 3 ]. X = rect. x + ( 48 * Rect. width/ 64 ); P [3 ]. Y = rect. Y + ( 38 * Rect. Height/ 64 ); P [ 4 ]. X = rect. x + ( 52 * Rect. width/ 64 ); P [ 4 ]. Y = rect. Y + rect. height; P [ 5 ]. X = rect. x + (rect. width/ 2 ); P [ 5 ]. Y = rect. Y + ( 52 * Rect. Height/ 64 ); P [ 6 ]. X = rect. x + ( 12 * Rect. width/ 64 ); P [ 6 ]. Y = rect. Y + rect. height; P [ 7 ]. X = rect. x + rect. width/ 4 ; P [ 7 ]. Y = rect. Y + ( 38 * Rect. Height/ 64 ); P [ 8 ]. X = rect. X; P [ 8 ]. Y = rect. Y + ( 22 * Rect. Height/ 64 ); P [9 ]. X = rect. x + ( 22 * Rect. width/ 64 ); P [ 9 ]. Y = rect. Y + ( 19 * Rect. Height/ 64 ); G. fillpolygon (fillbrush, P); G. drawpolygon (outlinepen, P );}

The areas in which the stars are to be drawn are contained in an array System: Drawing: rectangle Objects. This array is of the same size as the number of stars and is resized whenever the Count of stars changes through Starcount Property. each of the stars is filled with a gradient brush. this is an arbitrary demo-, but one which I hope wowould yield more pleasing results than a solid color wowould. the 10 points of each star are then calculated. I found it easiest to implement the star by dividing the drawing area into 64 logical partitions and placing the horizontal and vertical points as the offset into the 64 segment space. finally, we fill the polygon specified by these ten points with the forward-diagonal, gradient brush, and outline the polygon with the outline pen. lastly, we implement the event handlers dealing with varous mouse functions. when the mouse enters the control, we set the hovering flag True And force a repaint of the control:

Collapse | Copy code
Protected Override VoidOnmouseenter (system. eventargs EA) {m_hovering =True; Invalidate ();Base. Onmouseenter (EA );}

When the mouse leaves the control, we clear that flag and once again force a repaint of the control:

Collapse | Copy code
Protected Override VoidOnmouseleave (system. eventargs EA) {m_hovering =False; Invalidate ();Base. Onmouseleave (EA );}

Whenever the mouse moves, we check each of the stars in order to see over which, if any, the mouse is hovering. We record this information and force a repaint of the control.

Collapse | Copy code
Protected Override VoidOnmousemove (mouseeventargs ARGs ){For(IntI =0; I <starcount; ++ I ){If(M_starareas [I]. Contains (ARGs. X, argS. y) {m_hoverstar = I +1; Invalidate ();Break;}}Base. Onmousemove (ARGs );}

The logic is similar whenever a user clicks on the control. we iterate over each of the stars to see which, if any, was clicked on, and record this information. we then force a repaint of the control.

Invalidate ()Eventually turns into a callOnpaintWhich CILSDrawstar ().Drawstar (), In turn, will check our recorded hover and click information to figure out how to render the control.

Testing and using the control

Any project using the control must first Add a reference just like we added a reference toSystem. Drawing. dll. Add"Usingratingcontrols"ToUsingDeclarations.

The sample application does little else than depend on the default properties provided by the control, which include 5 stars with a dark gray outline, a yellow hover color, and a royal blue selected color. the control also has a default width and height of 120 and 18 pixels respectively. I found that this ratio produced the most pleasing looking image. the height and width are, of course, modifiable, and your stars can thus look as tall or as wide as you please.

Really, the only mildly-interesting piece of code in the sample application is in the constructor. The following is the piece of code, in its entirety:

Collapse | Copy code
PublicMainform () {initializecomponent (); m_starratingcontrol.top =45; M_starratingcontrol.left =85; Controls. Add (m_starratingcontrol );}
Possible improvements

The control cocould benefit from more publicly exposed properties such as fill brush style, so that forward-diagonal gradient is not the only implementation.

If speed optimization is a priority over size, one can rewriteOnpaint()Method so that it uses cached pre-calculated points to draw each of the stars instead of calculating the points on the fly. this wowould necessitate a few more data members to store the cached data, but wowould greatly improve the rendering speed of the control. this will probably be one of my own improvements of this control.

If you are really ambitious, you can follow the example of the msdn magazine article and implement functionality to render a user-supplied image rather than a star. this wowould, of course, necessitate a name change, as it wowould no longer technically be a * star * rating control.

PleaseSend meAny comments/questions/suggestions. I will strive to implement any valid suggestions for improvements and answer all of your questions.

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

About the author

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.