using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing; using ICSharpCode.Core; using System.Text.RegularExpressions; using Mesnac.Controls.Base; namespace Mesnac.Controls.Default { [ToolboxBitmap(typeof(System.Windows.Forms.TextBox))] public partial class MCTextBox : TextBox, IBaseControl { #region 类型定义 /// /// 正则表达是验证类型 /// public enum RegexType { Default, Number, ChineseCharacters, PostCode, Email, Tel, ChinaTel, Mobile, Integer, NegativeInteger, Float, NonnegativeFloat, PositiveFloat, NonpositiveFloat, NegativeFloat, EnglishCharacters, UpperCaseEnglishCharacters, LowerCaseEnglishCharacters, NumbersAndEnglishLetters, NumberOrEnglishLetterOrUnderline, URL, QQ, SID, IP, DateTime, Date, Year, Month, Day, Time, ChineseDate } #endregion #region 命令定义 private const int WM_ERASEBKGND = 0x0014; private const int WM_PAINT = 0xF; private const uint WM_NCPAINT = 0x0085; #endregion #region 字段定义 private Color _borderColor = Color.FromArgb(107, 191, 111); private string _waterMarkText; private Color _waterMarkTextColor = Color.DarkGray; private float _borderWeight = 1; private RegexType _controlType = RegexType.Default; private string _controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_Default")); // "默认"; private int _maxValue; private int _minValue; private bool _isEmpty = true;//允许 private bool _isValid = true;//保存有效性 private bool _isEventValid = true; //保存事件有效性 private bool _mcVisible = true; //保存可见性 private bool _mcEnabled = true; //保存可用性 private Color r = Color.FromArgb(107, 191, 111); private List _keyDownActionList = new List(); #endregion #region 构造方法 public MCTextBox() { InitializeComponent(); } public MCTextBox(IContainer container) { container.Add(this); InitializeComponent(); } #endregion #region 事件定义 public List KeyDownActionList { get { return _keyDownActionList; } set { _keyDownActionList = value; } } #endregion #region 属性定义 [Description("水印文字"), Category("Appearance")] public string WaterMarkText { get { return _waterMarkText; } set { _waterMarkText = value; base.Invalidate(); } } [DefaultValue(typeof(Color), "DarkGray"), Description("水印文字颜色"), Category("Appearance")] public Color WaterMarkTextColor { get { return _waterMarkTextColor; } set { _waterMarkTextColor = value; base.Invalidate(); } } [DefaultValue(typeof(Color), "107, 191, 111"), Description("边框颜色"), Category("Appearance")] public Color BorderColor { get { return _borderColor; } set { _borderColor = value; base.Invalidate(); } } [DefaultValue(typeof(float), "1"), Description("边框粗细"), Category("Appearance")] public float BorderWeight { get { return _borderWeight; } set { _borderWeight = value; base.Invalidate(); } } [DefaultValue(RegexType.Default), Description("文本框类型"), Category("Appearance")] public RegexType ControlType { get { return _controlType; } set { _controlType = value; this.ShowDescription(value); base.Invalidate(); } } [DefaultValue("默认"), Description("控件验证描述"), Category("Behavior")] public string ControlTypeText { get { return _controlTypeText; } } [DefaultValue(null), Description("最大值"), Category("Data")] public int MaxValue { get { return _maxValue; } set { _maxValue = value; } } [DefaultValue(null), Description("最小值"), Category("Data")] public int MinValue { get { return _minValue; } set { _minValue = value; } } [DefaultValue(true), Description("验证是否通过"), Category("Behavior")] public bool InvalidPass { get { return _isValid; } } [Description("是否允许为空"), Category("Behavior")] public bool IsEmpty { get { return _isEmpty; } set { _isEmpty = value; } } #endregion #region 方法定义 protected override Control.ControlCollection CreateControlsInstance() { r = this.BorderColor; this.BorderStyle = BorderStyle.FixedSingle; return base.CreateControlsInstance(); } #region 验证业务处理 private void ShowDescription(RegexType value) { switch (value) { case RegexType.Default: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_Default")); //"默认"; break; case RegexType.Number: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_Number")); //"数字"; break; case RegexType.ChineseCharacters: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_ChineseCharacters")); //"汉字"; break; case RegexType.PostCode: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_PostCode")); //"邮政编码"; break; case RegexType.Email: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_Email")); //"电子邮件"; break; case RegexType.Tel: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_Tel")); //"座机电话号码"; break; case RegexType.ChinaTel: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_ChinaTel")); //"中国电话号码"; break; case RegexType.Mobile: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_Mobile")); //"手机号码"; break; case RegexType.Integer: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_Integer")); //"整数"; break; case RegexType.NegativeInteger: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_NegativeInteger")); //"负整数"; break; case RegexType.Float: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_Float")); //"浮点数"; break; case RegexType.NonnegativeFloat: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_NonnegativeFloat")); //"非负浮点数"; break; case RegexType.PositiveFloat: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_PositiveFloat")); //"正浮点数"; break; case RegexType.NonpositiveFloat: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_NonpositiveFloat")); //"非正浮点数"; break; case RegexType.NegativeFloat: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_NegativeFloat")); //"负浮点数"; break; case RegexType.EnglishCharacters: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_EnglishCharacters")); //"英文字符"; break; case RegexType.UpperCaseEnglishCharacters: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_UpperCaseEnglishCharacters")); //"大写英文字符"; break; case RegexType.LowerCaseEnglishCharacters: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_LowerCaseEnglishCharacters")); //"小写英文字符"; break; case RegexType.NumbersAndEnglishLetters: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_NumbersAndEnglishLetters")); //"数字和英文字母"; break; case RegexType.NumberOrEnglishLetterOrUnderline: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_NumberOrEnglishLetterOrUnderline")); //"数字、英文字母或下划线"; break; case RegexType.URL: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_URL")); //"URL"; break; case RegexType.QQ: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_QQ")); //"QQ"; break; case RegexType.SID: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_SID")); //"身份证"; break; case RegexType.IP: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_IP")); //"IP"; break; case RegexType.DateTime: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_DateTime")); //"2000-2-28 23:29:59"; break; case RegexType.Date: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_Date")); //"2000-2-28"; break; case RegexType.Year: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_Year")); //"年份"; break; case RegexType.Month: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_Month")); //"月份"; break; case RegexType.Day: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_Day")); //"日"; break; case RegexType.Time: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_Time")); //"23:29:59"; break; case RegexType.ChineseDate: this._controlTypeText = StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_RegexType_ChineseDate")); //"2009年2月28日"; break; } } protected override void OnTextChanged(System.EventArgs e) { bool b = Invalid(this.ControlType, this.Text); if (!b) { this.BorderColor = Color.Red; this.errorProvider1.SetIconAlignment((Control)this, ErrorIconAlignment.MiddleRight); this.errorProvider1.SetError((Control)this, _waterMarkText == null ? _controlTypeText : _waterMarkText); this._isValid = false; //this.errorProvider1.Tag = false; } else { this.BorderColor = r; errorProvider1.SetError((Control)this, ""); this._isValid = true; //this.errorProvider1.Tag = true; base.Invalidate(); } base.Invalidate(); } protected override void OnLostFocus(EventArgs e) { if (!this._isValid) { return; } //WmPaint(); if (!_isEmpty) { if (this.Text == string.Empty) { this.BorderColor = Color.Red; using (Graphics g = Graphics.FromHwnd(this.Handle)) { using (Pen pen = new Pen(this.BorderColor, this.BorderWeight)) { g.DrawRectangle(pen, 0, 0, Size.Width - 1, Size.Height - 1); } } this._isValid = false; errorProvider1.SetIconAlignment((Control)this, ErrorIconAlignment.MiddleRight); //errorProvider1.SetError((Control)this, "不允许为空!"); errorProvider1.SetError((Control)this, StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_errorProvider1_msg_notEmpty"))); return; } else { errorProvider1.SetIconAlignment((Control)this, ErrorIconAlignment.MiddleRight); errorProvider1.SetError((Control)this, String.Empty); this._isValid = true; } } if (!Invalid(this.ControlType)) { this.BorderColor = Color.Red; this._isValid = false; errorProvider1.SetIconAlignment((Control)this, ErrorIconAlignment.MiddleRight); //errorProvider1.SetError((Control)this, "数值超出指定范围!"); errorProvider1.SetError((Control)this, StringParser.Parse(ResourceService.GetString("Mesnac_Controls_Default_MCTextBox_errorProvider1_msg_ExceedRange"))); } else { this.BorderColor = r; this._isValid = true; errorProvider1.SetError((Control)this, String.Empty); base.Invalidate(); } base.Invalidate(); base.OnLostFocus(e); } private bool Invalid(RegexType value) { if (this._isEmpty && String.IsNullOrEmpty(this.Text)) { return true; } bool b = true; switch (value) { case RegexType.Integer: if (Convert.ToInt32(this._maxValue) >= Convert.ToInt32(this.Text) && Convert.ToInt32(this._minValue) <= Convert.ToInt32(this.Text)) b = true; else b = false; break; case RegexType.NegativeInteger: if (Convert.ToInt32(this._maxValue) >= Convert.ToInt32(this.Text) && Convert.ToInt32(this._minValue) <= Convert.ToInt32(this.Text)) b = true; else b = false; break; case RegexType.Float: if (Convert.ToDecimal(this._maxValue) >= Convert.ToDecimal(this.Text) && Convert.ToDecimal(this._minValue) <= Convert.ToDecimal(this.Text)) b = true; else b = false; break; case RegexType.NonnegativeFloat: if (Convert.ToDecimal(this._maxValue) >= Convert.ToDecimal(this.Text) && Convert.ToDecimal(this._minValue) <= Convert.ToDecimal(this.Text)) b = true; else b = false; break; case RegexType.PositiveFloat: if (Convert.ToDecimal(this._maxValue) >= Convert.ToDecimal(this.Text) && Convert.ToDecimal(this._minValue) <= Convert.ToDecimal(this.Text)) b = true; else b = false; break; case RegexType.NonpositiveFloat: if (Convert.ToDecimal(this._maxValue) >= Convert.ToDecimal(this.Text) && Convert.ToDecimal(this._minValue) <= Convert.ToDecimal(this.Text)) b = true; else b = false; break; default: break; } return b; } private bool Invalid(RegexType value, string text) { if (_isEmpty) { if (this.Text == string.Empty) return true; } bool b = false; switch (value) { case RegexType.Default: b = true; break; case RegexType.Number: b = Validation(text, @"^\d+$"); break; case RegexType.ChineseCharacters: b = Validation(text, @"^[\u4e00-\u9fa5]$"); break; case RegexType.PostCode: b = Validation(text, @"^[1-9]\d{5}$"); break; case RegexType.Email: b = Validation(text, @"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"); break; case RegexType.Tel: b = Validation(text, @"^((\(\d{2,3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$"); break; case RegexType.ChinaTel: b = Validation(text, @"^\d{3}-\d{8}|\d{4}-\d{7}$"); break; case RegexType.Mobile: b = Validation(text, @"^((\(\d{2,3}\))|(\d{3}\-))?13\d{9}$"); break; case RegexType.Integer: b = Validation(text, @"^-?\d+$"); break; case RegexType.NegativeInteger: b = Validation(text, @"^-[0-9]*[1-9][0-9]*$"); break; case RegexType.Float: b = Validation(text, @"^(-?\d+)(\.\d+)?$"); break; case RegexType.NonnegativeFloat: b = Validation(text, @"^\d+(\.\d+)?$"); break; case RegexType.PositiveFloat: b = Validation(text, @"^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$"); break; case RegexType.NonpositiveFloat: b = Validation(text, @"^((-\d+(\.\d+)?)|(0+(\.0+)?))$"); break; case RegexType.NegativeFloat: b = Validation(text, @"^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$"); break; case RegexType.EnglishCharacters: b = Validation(text, @"^[A-Za-z]+$"); break; case RegexType.UpperCaseEnglishCharacters: b = Validation(text, @"^[A-Z]+$"); break; case RegexType.LowerCaseEnglishCharacters: b = Validation(text, @"^[a-z]+$"); break; case RegexType.NumbersAndEnglishLetters: b = Validation(text, @"^[A-Za-z0-9]+$"); break; case RegexType.NumberOrEnglishLetterOrUnderline: b = Validation(text, @"^\w+$"); break; case RegexType.URL: b = Validation(text, @"^(?:https?|ftp)\:\/\/(?:(?:[a-z0-9\-\._~\!\$\&\'\(\)\*\+\,\;\=:]|%[0-9a-f]{2,2})*\@)?(?:((?:(?:[a-z0-9][a-z0-9\-]*[a-z0-9]|[a-z0-9])\.)*(?:[a-z][a-z0-9\-]*[a-z0-9]|[a-z])|(?:\[[^\]]*\]))(?:\:[0-9]*)?)(?:\/(?:[a-z0-9\-\._~\!\$\&\'\(\)\*\+\,\;\=\:\@]|%[0-9a-f]{2,2})*)*(?:\?(?:[a-z0-9\-\._~\!\$\&\'\(\)\*\+\,\;\=\:\@\/\?]|%[0-9a-f]{2,2})*)?(?:\#(?:[a-z0-9\-\._~\!\$\&\'\(\)\*\+\,\;\=\:\@\/\?]|%[0-9a-f]{2,2})*)?$"); break; case RegexType.QQ: b = Validation(text, @"^[1-9][0-9]{4,}$"); break; case RegexType.SID: b = Validation(text, @"^((1[1-5])|(2[1-3])|(3[1-7])|(4[1-6])|(5[0-4])|(6[1-5])|71|(8[12])|91)\d{4}((19\d{2}(0[13-9]|1[012])(0[1-9]|[12]\d|30))|(19\d{2}(0[13578]|1[02])31)|(19\d{2}02(0[1-9]|1\d|2[0-8]))|(19([13579][26]|[2468][048]|0[48])0229))\d{3}(\d|X|x)?$"); break; case RegexType.IP: b = Validation(text, @"^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$"); break; case RegexType.DateTime: b = Validation(text, @"^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-)) (20|21|22|23|[0-1]?\d):[0-5]?\d:[0-5]?\d$"); break; case RegexType.Date: b = Validation(text, @"^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-))$"); break; case RegexType.Year: b = Validation(text, @"^((1[6-9]|[2-9]\d)\d{2})$"); break; case RegexType.Month: b = Validation(text, @"^(0?[123456789]|1[012])$"); break; case RegexType.Day: b = Validation(text, @"^(0?[1-9]|[12]\d|3[01])$"); break; case RegexType.Time: b = Validation(text, @"^(20|21|22|23|[0-1]?\d):[0-5]?\d:[0-5]?\d$"); break; case RegexType.ChineseDate: b = Validation(text, @"^((((1[6-9]|[2-9]\d)\d{2})年(0?[13578]|1[02])月(0?[1-9]|[12]\d|3[01])日)|(((1[6-9]|[2-9]\d)\d{2})年(0?[13456789]|1[012])月(0?[1-9]|[12]\d|30)日)|(((1[6-9]|[2-9]\d)\d{2})年0?2月(0?[1-9]|1\d|2[0-8])日)|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))年0?2月29日))$"); break; } return b; } private bool Validation(string validValue, string regularExpression) { Regex regex; try { regex = new Regex(regularExpression); } catch { return false; } if (regex.IsMatch(validValue)) { return true; } else { return false; } } protected override void OnPaint(PaintEventArgs pe) { this.BorderStyle = BorderStyle.FixedSingle; //if (m.Msg == WM_PAINT || m.Msg == WM_NCPAINT) //{ if (this.BorderWeight % 2 == 0) { this.BorderWeight -= 1; } using (Graphics g = Graphics.FromHwnd(this.Handle)) { using (Pen pen = new Pen(this.BorderColor, this.BorderWeight)) { g.DrawRectangle(pen, 0, 0, Size.Width - 1, Size.Height - 1); } } WmPaint(); //} base.OnPaint(pe); } private void WmPaint() { using (Graphics graphics = Graphics.FromHwnd(base.Handle)) { if (Text.Length == 0 && !string.IsNullOrEmpty(_waterMarkText) && !Focused) { TextFormatFlags format = TextFormatFlags.EndEllipsis | TextFormatFlags.VerticalCenter; if (RightToLeft == RightToLeft.Yes) { format |= TextFormatFlags.RightToLeft | TextFormatFlags.Right; } TextRenderer.DrawText(graphics, _waterMarkText, Font, base.ClientRectangle, _waterMarkTextColor, format); } } } #endregion #endregion #region 接口成员实现 public string MCKey { get; set; } public object MCValue { get { return this.Text; } set { this.Text = value == null ? string.Empty : value.ToString(); } } public IBaseControl MCRoot { get { return null; } set { ; } } [TypeConverter(typeof(DataSourceConverter))] [Description("数据连接"), Category("数据")] public string MCDataSourceID { get; set; } public MCDataSource MCDataSource { get; set; } [Description("是否为数据库控件"), Category("数据")] public bool IsDbControl { get; set; } [Description("初始化SQL"), Category("数据")] public string InitDataSource { get; set; } [Description("执行SQL"), Category("数据")] public string ActionDataSource { get; set; } [Description("绑定数据源"), Category("数据")] public object BindDataSource { get; set; } [Description("操作类型"), Category("数据")] public DbOptionTypes DbOptionType { get; set; } [Description("是否可见"), Category("行为")] public bool MCVisible { get { return this._mcVisible; } set { this._mcVisible = value == null ? true : value; if (this.Site.DesignMode) { this.Visible = true; } else { this.Visible = this._mcVisible; } } } [Description("是否可用"), Category("行为")] public bool MCEnabled { get { return this._mcEnabled; } set { this._mcEnabled = value == null ? true : value; if (this.Site.DesignMode) { this.Enabled = true; } else { this.Enabled = this._mcEnabled; } } } public bool IsValid { get { return _isValid; } set { _isValid = value; } } public bool IsEventValid { get { return this._isEventValid; } set { this._isEventValid = value; } } #endregion } }