A good base class can determine how far this control can go, so here are some things to define.
Define state, which indicates what state the control is currently in, to distinguish between different responses to the same event
[Flags] publicenum cdcontrolstate { 0, 1, 2, 4, 8 , }
Define events to customize requirements and ignore useless code to avoid excessive response or window redraw
[Flags] publicenum cdcontrolevent { 0, 1, 2, 4, 8 , 0x10 , 0x20 , }
To define an interface, this is to achieve a one-button skin-changing function, the loading material and reposition the control inside the structure is treated separately, but also at design time to fill the material to the corresponding properties of the control and display in the IDE
Public Interface Icdskin { void skinload (); void Designtimeskinload (string name); void caculatelocation (); }
Back to the point, say the base class bar, the basic prototype code is the following
namespacecdtheme{[ToolboxItem (false)] Public Abstract Partial classCdbase:usercontrol, Icdskin {Private BOOL_isloaded; Privatecdcontrolstate _cdstate; Privatecdcontrolevent _cdevent; protected BOOLIsLoaded {Get { return_isloaded; } } protectedcdcontrolstate cdstate {Get { return_cdstate; } } protectedcdcontrolevent cdevent {Get { return_cdevent; } } Private voidSetcdcontrolstate (Cdcontrolstate State,BOOLAllow ) { if(allow) _cdstate|=State ; Else_cdstate&= ~State ; } protected voidSetcdcontrolevent (cdcontrolevent style,BOOLAllow ) { if(allow) _cdevent|=style; Else_cdevent&= ~style; } Public voidDesigntimeskinload (stringname) {Cdskinmanager.designtimeskinload ( This, name); } Public Virtual voidskinload () {setcdcontrolstate (cdcontrolstate.skinloaded,true); } Public Virtual voidcaculatelocation () {}protected Virtual voidStateChanged (Cdcontrolstate changedstate,BOOLAllow ) {setcdcontrolstate (changedstate, allow); } Publiccdbase () {SetStyle (Controlstyles.allpaintinginwmpaint| Controlstyles.optimizeddoublebuffer,true); InitializeComponent (); } [Browsable (false)] Public NewBorderStyle BorderStyle {Get { return Base. BorderStyle; } Set { Base. BorderStyle =value; } } protected Override voidOnLoad (EventArgs e) {_isloaded=true; Base. OnLoad (e); } protected Override voidonsizechanged (EventArgs e) {Base. Onsizechanged (e); if(Cdstate.hasflag (cdcontrolstate.skinloaded)) caculatelocation (); } protected Override voidonenabledchanged (EventArgs e) {Base. Onenabledchanged (e); StateChanged (Cdcontrolstate.none,true); } protected Override voidOnmouseenter (EventArgs e) {Base. Onmouseenter (e); if(Cdevent.hasflag (Cdcontrolevent.mousemove)) statechanged (Cdcontrolstate.mouseenter,true); } protected Override voidOnMouseLeave (EventArgs e) {Base. OnMouseLeave (e); if(Cdevent.hasflag (Cdcontrolevent.mousemove)) statechanged (Cdcontrolstate.mouseenter,false); } protected Override voidOnMouseUp (MouseEventArgs e) {Base. OnMouseUp (e); if(E.button = =mousebuttons.left)if(Cdevent.hasflag (Cdcontrolevent.mouseclick)) statechanged (Cdcontrolstate.mousedown,false); } protected Override voidOnMouseDown (MouseEventArgs e) {Base. OnMouseDown (e); if(E.button = =mousebuttons.left)if(Cdevent.hasflag (Cdcontrolevent.mouseclick)) statechanged (Cdcontrolstate.mousedown,true); } }}
Although there is no comment, but by name you can also understand the meaning of encapsulating common events and unified into the StateChanged method, let derived classes by overriding this method to make a separate response
So how do you use this base class?
One, use setcdcontrolevent in each constructor that has an actual code-derived class to determine when some events will be answered
Second, by rewriting the Skinload, Caculatelocation and statechanged three methods, to achieve loading material, repositioning and incident response effect
The logic of defining attribute and implementing interface according to requirement
Very abstract, the next article will give a simple example to illustrate
WinForm Component Class (iii) base class for making customizable styles