一个良好的基类能决定这个控件能走多远,那么下面来定义一些事情。
定义状态,表示控件当前处于哪种状态,用来区别对同一事件作出不同的响应
[Flags] public enum CDControlState { None = 0, SkinLoaded = 1, MouseEnter = 2, MouseDown = 4, Resizing = 8, }
定义事件,用来定制需求,忽略无用的代码,以免造成过多响应或是窗口重绘
[Flags] public enum CDControlEvent { None = 0, MouseMove = 1, MouseClick = 2, BackImage = 4, BackColor = 8, Text = 0x10, Icon = 0x20, }
再来定义一个接口,这是为了实现一键换肤功能,把装载素材和重定位控件内结构分别对待,同时还要在设计时把素材装填到控件相对应的属性并显示在IDE中
public interface ICDSkin { void SkinLoad(); void DesigntimeSkinLoad(string name); void CaculateLocation(); }
回到正题,来说说基类吧,基本雏形代码是下面这样的
namespace CDTheme { [ToolboxItem(false)] public abstract partial class CDBase : UserControl, ICDSkin { private bool _isLoaded; private CDControlState _cdState; private CDControlEvent _cdEvent; protected bool IsLoaded { get { return _isLoaded; } } protected CDControlState CDState { get { return _cdState; } } protected CDControlEvent CDEvent { get { return _cdEvent; } } private void SetCDControlState(CDControlState state, bool allow) { if (allow) _cdState |= state; else _cdState &= ~state; } protected void SetCDControlEvent(CDControlEvent style, bool allow) { if (allow) _cdEvent |= style; else _cdEvent &= ~style; } public void DesigntimeSkinLoad(string name) { CDSkinManager.DesigntimeSkinLoad(this, name); } public virtual void SkinLoad() { SetCDControlState(CDControlState.SkinLoaded, true); } public virtual void CaculateLocation() { } protected virtual void StateChanged(CDControlState changedState, bool allow) { SetCDControlState(changedState, allow); } public CDBase() { SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true); InitializeComponent(); } [Browsable(false)] public new BorderStyle BorderStyle { get { return base.BorderStyle; } set { base.BorderStyle = value; } } protected override void OnLoad(EventArgs e) { _isLoaded = true; base.OnLoad(e); } protected override void OnSizeChanged(EventArgs e) { base.OnSizeChanged(e); if (CDState.HasFlag(CDControlState.SkinLoaded)) CaculateLocation(); } protected override void OnEnabledChanged(EventArgs e) { base.OnEnabledChanged(e); StateChanged(CDControlState.None, true); } protected override void OnMouseEnter(EventArgs e) { base.OnMouseEnter(e); if (CDEvent.HasFlag(CDControlEvent.MouseMove)) StateChanged(CDControlState.MouseEnter, true); } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); if (CDEvent.HasFlag(CDControlEvent.MouseMove)) StateChanged(CDControlState.MouseEnter, false); } protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); if (e.Button == MouseButtons.Left) if (CDEvent.HasFlag(CDControlEvent.MouseClick)) StateChanged(CDControlState.MouseDown, false); } protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); if (e.Button == MouseButtons.Left) if (CDEvent.HasFlag(CDControlEvent.MouseClick)) StateChanged(CDControlState.MouseDown, true); } } }
虽然没有注释,但通过名称大家也能明白意思,封装了常用的事件并统一到StateChanged方法中,让派生类通过重写此方法来作出独立的响应
那么如何使用这个基类?
一、在每个在有实际代码派生类的构造函数中使用SetCDControlEvent来决定当些事件会被响应
二、通过重写SkinLoad、CaculateLocation与StateChanged三个方法,来达到装载素材、重新定位与事件响应的效果
三、根据需求定义属性与实现界面的逻辑
说得很抽象,在下一篇将会给出一个简单的实例来说明
时间: 2024-11-09 02:51:41