using System; using System.ComponentModel; using System.Drawing; using System.Text.RegularExpressions; using System.Windows.Forms; using Dongke.WinForm.Utilities; namespace Dongke.WinForm.Controls { /// /// 限制输入文本框控件 /// public abstract class TextBoxRejected : TextBox, IDKControl, IDataVerifiable, IAsyncControl { #region 事件声明 /* #region TextPaste /// /// 当输入文本粘贴后发生 /// private static readonly object EventTextPaste = new object(); /// /// TextPaste 事件 /// public event TextPasteEventHandler TextPaste { add { base.Events.AddHandler(TextBoxRejected.EventTextPaste, value); } remove { base.Events.RemoveHandler(TextBoxRejected.EventTextPaste, value); } } #endregion #region EditReadOnlyChanged /// /// 当 EditReadOnly 属性的值更改时发生。 /// private static readonly object EventEditReadOnlyChanged = new object(); /// /// 当 EditReadOnly 属性的值更改时发生 /// [Description("当 EditReadOnly 属性的值更改时发生。"), Category("CustomerEx")] public event EventHandler EditReadOnlyChanged { add { base.Events.AddHandler(EventEditReadOnlyChanged, value); } remove { base.Events.RemoveHandler(EventEditReadOnlyChanged, value); } } /// /// 引发 EditReadOnlyChanged 事件 /// /// protected virtual void OnEditReadOnlyChanged(EventArgs e) { EventHandler eventHandler = base.Events[EventEditReadOnlyChanged] as EventHandler; if (eventHandler != null) { eventHandler(this, e); } } #endregion */ #region HasErrorChanged /// /// 当 HasError 属性的值更改时发生。 /// private static readonly object EventHasErrorChanged = new object(); /// /// 当 HasError 属性的值更改时发生。 /// [Description("当 HasError 属性的值更改时发生。"), Category("CustomerEx")] public event EventHandler HasErrorChanged { add { base.Events.AddHandler(EventHasErrorChanged, value); } remove { base.Events.RemoveHandler(EventHasErrorChanged, value); } } #endregion #endregion #region 成员变量 ///// ///// 指示控件中的文本是否为只读 ///// //private bool _editReadOnly = true; /// /// 验证不通过,焦点不离开 /// private bool _validatingCancel = false; /// /// 焦点是否进入控件 /// private bool _entered = false; /// /// 鼠标是否进入控件 /// private bool _mouseOver = false; /// /// 边框颜色 /// private Color? _borderColor = null; /// /// 拒绝输入的字符 /// private string _rejected = null; /// /// 限定正则表达式 /// private string _regular = null; /// /// 限制最小长度 /// private int _minLength = 0; /// /// Unicode 填充字符,来达到指定的允许输入的最小长度 /// private char? _paddingChar = null; /// /// 填充指定的 Unicode 字符来达到指定的总长度,从而使这些字符对齐方式。 /// private TextPadStyle _textPad = TextPadStyle.Left; /// /// 控件在获得焦点时,文本内容的选择方式。 /// private EnteredSelectTextStyle _enteredSelectTextStyle = EnteredSelectTextStyle.None; /// /// 符合规则的文本 /// protected string _textValue = null; /// /// 正在设置文本 /// protected bool _isSettingText = false; #endregion #region 构造函数 /// /// 标准复选框列表控件 /// public TextBoxRejected() { CommonSetting.InitControls(this); base.MaxLength = 1000; } #endregion #region 属性 ///// ///// 获取或设置一个值,该值指示文本框中的文本是否为只读。 ///// //[Description("获取或设置一个值,该值指示文本框中的文本是否为只读。"), Category("CustomerEx")] //[DefaultValue(true)] //public virtual bool EditReadOnly //{ // get // { // return this._editReadOnly; // } // set // { // if (this._editReadOnly != value) // { // this._editReadOnly = value; // this.OnEditReadOnlyChanged(EventArgs.Empty); // } // } //} /// /// 获取一个值,该值指示控件是否有输入焦点。 /// [DefaultValue(false)] [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [EditorBrowsable(EditorBrowsableState.Advanced)] public virtual bool Entered { get { return this._entered; } protected set { if (this._entered != value) { this._entered = value; this.InvalidateBorder(); } } } /// /// 获取一个值,该值指示鼠标是否在控件上方。 /// [DefaultValue(false)] [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [EditorBrowsable(EditorBrowsableState.Advanced)] public virtual bool MouseOver { get { return this._mouseOver; } protected set { if (this._mouseOver != value) { this._mouseOver = value; this.InvalidateBorder(); } } } /// /// 获取或设置允许输入的最小长度。 /// [Description("获取或设置允许输入的最小长度。"), Category("CustomerEx")] [DefaultValue(0)] public virtual int MinLength { get { return Math.Min(this._minLength, this.MaxLength); } set { if (value < 0 || value > this.MaxLength) { return; } if (this._minLength != value) { if (value > this.MinLength) { this._minLength = value; this.SetTextValue(); } else { this._minLength = value; } } } } /// /// 获取或设置Unicode 填充字符,来达到指定的允许输入的最小长度。填充字符不受过滤限制。 /// [Description("获取或设置Unicode 填充字符,来达到指定的允许输入的最小长度。填充字符不受过滤限制。"), Category("CustomerEx")] [DefaultValue(null)] public virtual char? PaddingChar { get { return this._paddingChar; } set { if (this._paddingChar != value) { if (!this._paddingChar.HasValue && value.HasValue) { this._paddingChar = value; this.SetTextValue(); } else { this._paddingChar = value; } } } } /// /// 获取或设置填充指定的 Unicode 字符来达到指定的总长度的对齐方式。 /// [Description("获取或设置填充指定的 Unicode 字符来达到指定的总长度的对齐方式。"), Category("CustomerEx")] [DefaultValue(typeof(TextPadStyle), "Left")] public virtual TextPadStyle TextPad { get { return this._textPad; } set { if (this._textPad != value) { this._textPad = value; } } } /// /// 获取符合规则的文本 /// [Description("获取符合规则的文本,未通过校验时为string.Empty"), Category("CustomerEx")] [DefaultValue((string)null)] public virtual string TextValue { get { return this._textValue; } } /// /// 获取或设置限制输入的字符。填充字符不受过滤限制。 /// [Description("获取或设置限制输入的字符。填充字符不受过滤限制。"), Category("CustomerEx")] [DefaultValue((string)null)] protected virtual string Rejected { get { return this._rejected; } set { if (this._rejected != value) { this._rejected = value; this.SetTextValue(); } } } /// /// 获取或设置输入内容应该符合的正则表达式 /// [Description("获取或设置输入内容应该符合的正则表达式"), Category("CustomerEx")] [DefaultValue((string)null)] protected virtual string Regular { get { return this._regular; } set { if (this._regular != value) { this._regular = value; this.ValidateData(); } } } ///// ///// ///// //protected virtual bool BeginWithZero //{ //} #endregion #region 重写属性 /// /// 获取或设置用户可在文本框控件中键入或粘贴的最大字符数 /// [DefaultValue(1000)] public override int MaxLength { get { return base.MaxLength; } set { base.MaxLength = value; if (value < this._minLength) { this.MinLength = value; } } } /// /// 获取或设置当前文本。 /// public override string Text { get { return base.Text; } set { this.SetTextValue(value); } } /// /// 获取或设置一个值,该值指示控件中当前选定的文本。 /// public override string SelectedText { get { return base.SelectedText; } set { this.PasteChars(value); } } #endregion #region 重写事件 #region 属性改变 /// /// 引发 HasErrorChanged 事件 /// /// 包含事件数据的 EventArgs protected virtual void OnHasErrorChanged(EventArgs e) { EventHandler eventHandler = (EventHandler)base.Events[EventHasErrorChanged]; if (eventHandler != null) { eventHandler(this, e); } } /// /// 文本改变事件 /// /// protected override void OnTextChanged(EventArgs e) { if (!this._isSettingText) { this.SetTextValue(); return; } this._isSettingText = false; base.OnTextChanged(EventArgs.Empty); // TODO 实时验证? if (true) { this.ValidateData(); } } #endregion #region 行为事件 /// /// 引发 TextPaste 事件 /// /// 包含事件数据的 TextPasteEventArgs protected virtual void OnPaste(TextPasteEventArgs e) { //TextPasteEventHandler eventHandler = (TextPasteEventHandler)base.Events[EventTextPaste]; //if (eventHandler != null) //{ // eventHandler(this, e); //} } #endregion #region 键盘事件 /// /// 键盘输入 /// /// protected override void OnKeyPress(KeyPressEventArgs e) { if (!this.Enabled || this.ReadOnly || char.IsControl(e.KeyChar)) { base.OnKeyPress(e); if (e.KeyChar == (char)8)//WindowsAPI.KeysToChar(Keys.Back)) { this._isSettingText = true; } return; } //if (this._editReadOnly) //{ // if (e.KeyChar == (char)8) // { // this.Text = string.Empty; // } // e.Handled = true; // return; //} base.OnKeyPress(e); if (e.Handled) { return; } string chars = this.RejectChars(e.KeyChar.ToString()); //chars = this.LimitLength(chars); if (chars.Length > 0) { this._isSettingText = true; } else { WindowsAPI.MessageBeep(BeepType.MB_OK); e.Handled = true; } } /// /// 键盘点击 /// /// protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); if (e.Handled) { return; } if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete) { //if (this._editReadOnly) //{ // this.Text = string.Empty; // e.Handled = true; // return; //} this._isSettingText = true; } } #endregion #region 焦点事件 /// /// 输入焦点进入控件 /// /// protected override void OnEnter(EventArgs e) { this.Entered = true; base.OnEnter(e); } /// /// 获得焦点 /// /// protected override void OnGotFocus(EventArgs e) { base.OnGotFocus(e); if (this._validatingCancel) { this._validatingCancel = false; return; } int textLength = base.Text.Length; if (textLength > 0) { switch (this._enteredSelectTextStyle) { case EnteredSelectTextStyle.Left: this.Select(0, 0); break; case EnteredSelectTextStyle.Right: this.Select(textLength, 0); break; case EnteredSelectTextStyle.All: this.SelectAll(); break; default: break; } } } /// /// 失去焦点 /// /// protected override void OnLostFocus(EventArgs e) { base.OnLostFocus(e); } /// /// 输入焦点离开控件 /// /// protected override void OnLeave(EventArgs e) { base.OnLeave(e); //this.Entered = false; } /// /// 控件正在验证 /// /// protected override void OnValidating(CancelEventArgs e) { base.OnValidating(e); if (this.HasError && !this._canLostFocusOnError) { e.Cancel = true; } this._validatingCancel = e.Cancel; } /// /// 控件完成验证 /// /// protected override void OnValidated(EventArgs e) { this.Entered = false; this.SetText(this.FormatText(base.Text)); this._validatingCancel = false; base.OnValidated(e); } #endregion #region 鼠标事件 /// /// 鼠标进入控件 /// /// protected override void OnMouseEnter(EventArgs e) { this.MouseOver = true; base.OnMouseEnter(e); } /// /// 鼠标离开控件 /// /// protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); this.MouseOver = false; } /// /// 鼠标移动 /// /// protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); } /// /// 鼠标按下 /// /// protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); } /// /// 鼠标抬起 /// /// protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); } #endregion #endregion #region 重写方法 /// /// 处理 Windows 消息 /// /// 要处理的 Windows System.Windows.Forms.Message protected override void WndProc(ref Message m) { switch (m.Msg) { case (int)WindowsMessage.WM_PASTE: // 粘贴 //if (this._editReadOnly) //{ // WindowsAPI.MessageBeep(BeepType.MB_OK); // return; //} this.PasteChars(); return; case (int)WindowsMessage.WM_CUT: // 右键菜单 剪切 //if (this._editReadOnly) //{ // WindowsAPI.MessageBeep(BeepType.MB_OK); // return; //} this._isSettingText = true; break; case (int)WindowsMessage.WM_CHAR: if (m.WParam.ToInt32() == 18) { // Ctrl + X 18 //if (this._editReadOnly) //{ // WindowsAPI.MessageBeep(BeepType.MB_OK); // return; //} this._isSettingText = true; } break; default: break; } base.WndProc(ref m); if ((int)m.Result == 1) { // 剪切、back、delete 等操作没有改变Text时,设置 _isSettingText = false。 switch (m.Msg) { case (int)WindowsMessage.WM_CUT: // 剪切空白 case (int)WindowsMessage.WM_CHAR: // 输入达到最大长度,back 8 this._isSettingText = false; break; case (int)WindowsMessage.WM_KEYDOWN: if (m.WParam.ToInt32() == 46) { // delete 46 this._isSettingText = false; } break; default: break; } } if (m.Msg == (int)WindowsMessage.WM_PAINT || m.Msg == (int)WindowsMessage.WM_NCPAINT || m.Msg == (int)WindowsMessage.WM_CTLCOLOREDIT) { BorderColorPaint.WmBorderPaint(this._borderColor, this.Width, this.Height, ref m); } } #endregion #region 公有方法 #endregion #region 保护方法 #endregion #region 私有方法 /// /// 使父控件的指定区域无效(将其添加到控件的更新区域,下次绘制操作时将重新绘制更新区域),并向父控件发送绘制消息。 /// private void InvalidateBorder() { Color? borderColor = BorderColorPaint.GetBorderColor(this as IDataVerifiable, this._entered, this._mouseOver); if (borderColor != this._borderColor) { this._borderColor = borderColor; if (this.Parent == null) { this.Invalidate(); } else { this.Parent.Invalidate(this.Bounds, true); } } } /// /// 设置文本(过滤限制输入字符,并验证是否符合正则表达式) /// private void SetTextValue() { this.SetTextValue(base.Text); } /// /// 设置文本(过滤限制输入字符,并验证是否符合正则表达式) /// /// 文本 private void SetTextValue(string text) { // TODO 先过滤还是先补齐? // 过滤输入字符 text = this.RejectChars(text); // 限制输入长度 text = this.LimitLength(text, true); // 格式化显示文本 text = this.FormatText(text); this.SetText(text); } /// /// 设置文本(修改base.Text属性) /// /// 文本 private bool SetText(string text) { string baseText = base.Text; if (baseText != text) { this._isSettingText = true; base.Text = text; this._isSettingText = false; return true; } return false; } /// /// 过滤限制输入的字符(OnKeyPress or 属性改变) /// /// 文本 /// 过滤后的文本 private string RejectChars(string chars) { if (string.IsNullOrEmpty(chars)) { return chars; } if (!this.Multiline) { int indexNewLine = chars.IndexOf(Environment.NewLine); if (indexNewLine > -1) { chars = chars.Remove(indexNewLine); } } if (string.IsNullOrEmpty(this._rejected)) { return chars; } chars = Regex.Replace(chars, this._rejected, string.Empty); return chars; } /// /// 格式化显示文本 /// /// 文本 /// 格式化后的文本 private string FormatText(string text) { //if (string.IsNullOrEmpty(text)) //{ // return text; //} // 填充字符,使文本对齐。 if (!this._entered && this._paddingChar.HasValue) { int textLength = (text != null) ? text.Length : 0; int minLength = this.MinLength; if ((this._mustInput && minLength > 0 && textLength == 0) || (textLength > 0 && minLength > textLength)) { minLength = Math.Max(this._mustInput ? 1 : 0, minLength); if (text == null) { text = string.Empty; } if (this._textPad == TextPadStyle.Left) { text = text.PadLeft(minLength, this._paddingChar.Value); } else { text = text.PadRight(minLength, this._paddingChar.Value); } } } return text; } /// /// 限制文本长度 /// /// /// /// private string LimitLength(string input, bool ignoreText = false) { if (this.MaxLength == 0 || string.IsNullOrEmpty(input)) { return input; } int inputCount = input.Length; int remainCount = this.MaxLength; if (!ignoreText) { remainCount = remainCount - (base.Text.Length - this.SelectionLength); } if (remainCount <= 0) { return string.Empty; } if (inputCount <= remainCount) { return input; } else { return input.Substring(0, remainCount); } } /// /// 粘贴文本 /// private void PasteChars() { if (!this.Enabled || this.ReadOnly) { return; } object clipboardChars = Clipboard.GetDataObject().GetData(DataFormats.UnicodeText); if (clipboardChars == null) { clipboardChars = Clipboard.GetDataObject().GetData(DataFormats.Text); if (clipboardChars == null) { return; } } this.PasteChars(clipboardChars.ToString()); } /// /// 粘贴文本 /// /// private void PasteChars(string chars) { if (string.IsNullOrEmpty(chars)) { WindowsAPI.MessageBeep(BeepType.MB_OK); return; } chars = this.RejectChars(chars); chars = this.LimitLength(chars); if (chars.Length > 0) { TextPasteEventArgs pasteEventArgs = new TextPasteEventArgs(chars); this.OnPaste(pasteEventArgs); if (pasteEventArgs.Cancel) { return; } this._isSettingText = true; base.SelectedText = chars; this._isSettingText = false; } else { WindowsAPI.MessageBeep(BeepType.MB_OK); } } #endregion #region IDataVerifiable 成员 #region 成员变量 /// /// 显示边框颜色 /// private bool _showBorderColor = true; /// /// 控件的项目名 /// private string _itemName = null; /// /// 控件是否是必须输入项目 /// private bool _mustInput = false; /// /// 控件在验证输入错误时,如何提示 /// private InputErrorAlert _errorAlert = InputErrorAlert.Validated; /// /// 是否显示必须输入项目的提示 /// private bool _showMustInputAlert = true; /// /// 验证不通过时,焦点能否离开 /// private bool _canLostFocusOnError = true; /// /// 验证是否有错误 /// private bool _hasError = false; /// /// 是否自定义错误 /// private bool _hasCustomerError = false; /// /// 错误编码 /// private ControlErrorCode _errorCode = ControlErrorCode.DKC_0000; /// /// 错误消息 /// private string _errorMessage = null; /// /// 自定义错误消息 /// private string _customerErrorMessage = null; #endregion #region 属性 /// /// 获取或设置控件是否显示边框颜色。 /// [Description("获取或设置控件是否显示边框颜色。"), Category("IDataVerifiable")] [DefaultValue(true)] public bool ShowBorderColor { get { return this._showBorderColor; } set { if (this._showBorderColor != value) { this._showBorderColor = value; this.InvalidateBorder(); } } } /// /// 获取或设置控件的项目名 /// [Description("获取或设置控件的项目名。"), Category("IDataVerifiable")] [DefaultValue(null)] public string CDItemName { get { return this._itemName; } set { this._itemName = value; } } /// /// 获取或设置控件是否必须选中项目。 /// [Description("获取或设置控件是否必须选中项目。"), Category("IDataVerifiable")] [DefaultValue(false)] public bool MustInput { get { return this._mustInput; } set { if (this._mustInput != value) { if (!this._mustInput && value) { this._mustInput = value; this.SetTextValue(); } else { this._mustInput = value; } this.ValidateData(); if (value && this._showMustInputAlert) { this.InvalidateBorder(); } } } } /// /// 获取或设置控件是否必须选中项目。 /// [Description("获取或设置控件在验证输入错误时,如何提示。"), Category("IDataVerifiable")] [DefaultValue(typeof(InputErrorAlert), "Validated")] public InputErrorAlert InputErrorAlert { get { return this._errorAlert; } set { if (this._errorAlert != value) { this._errorAlert = value; this.InvalidateBorder(); } } } /// /// 获取或设置控件是否显示必须输入项目提示 /// [Description("获取或设置控件是否显示必须输入项目提示。"), Category("IDataVerifiable")] [DefaultValue(true)] public bool ShowMustInputAlert { get { return this._showMustInputAlert; } set { if (this._showMustInputAlert != value) { this._showMustInputAlert = value; this.InvalidateBorder(); } } } /// /// 获取或设置当验证不通过时,控件是否可以失去焦点 /// [Description("获取或设置当验证不通过时,控件是否可以失去焦点。"), Category("IDataVerifiable")] [DefaultValue(true)] public bool CanLostFocusOnError { get { return this._canLostFocusOnError; } set { this._canLostFocusOnError = value; } } /// /// 获取控件校验时是否有错误 /// [Description("获取控件校验时是否有错误。"), Category("IDataVerifiable")] [DefaultValue(false)] public bool HasError { get { return this._hasCustomerError || this._hasError; } } /// /// 获取控件校验时的错误编码 /// [Description("获取控件校验时的错误编码。"), Category("IDataVerifiable")] [DefaultValue(typeof(ControlErrorCode), "DKC_0000")] public ControlErrorCode ErrorCode { get { return this._hasCustomerError ? ControlErrorCode.DKC_C001 : this._errorCode; } } /// /// 获取控件校验时的错误消息 /// [Description("获取控件校验时的错误编码。"), Category("IDataVerifiable")] [DefaultValue(null)] public string ErrorMessage { get { return this._hasCustomerError ? this._customerErrorMessage : this._errorMessage; } } #endregion #region 公有方法 /// /// 设置自定义错误 /// /// 输入是否有错误 /// 错误消息 public virtual void SetCustomerError(bool hasError, string errorMessage) { if (this._hasCustomerError != hasError || this._customerErrorMessage != errorMessage) { this._hasCustomerError = hasError; this._customerErrorMessage = errorMessage; this.OnHasErrorChanged(EventArgs.Empty); this.InvalidateBorder(); } } /// /// 清除自定义错误 /// public virtual void ClearCustomerError() { this.SetCustomerError(false, null); } /// /// 验证输入内容 /// /// 验证结果 public virtual bool ValidateData() { string text = base.Text; if (this._mustInput && text.Length == 0) { this.SetError(true, ControlErrorCode.DKC_0001, this._itemName); return true; } if (this._minLength >0 && text.Length > 0 && this._minLength > text.Length) { this.SetError(true, ControlErrorCode.DKC_0002, this._itemName, this._minLength); return true; } if (text.Length > 0 && this._regular != null && this._regular.Length > 0) { if (!Regex.IsMatch(text, this._regular)) { this.SetError(true, ControlErrorCode.DKC_0004, this._itemName); return true; } } this.ClearError(); return false; } /// /// 清除输入项 /// public virtual void ClearValue() { this.Clear(); } #endregion #region 保护方法 /// /// 设置验证不通过错误 /// /// 是否有错误 /// 错误编码 /// 设置格式的对象 protected void SetError(bool hasError, ControlErrorCode code, params object[] args) { if (this._hasError != hasError || this._errorCode != code) { this._hasError = hasError; this._errorCode = code; if (args != null && args.Length > 0) { this._errorMessage = string.Format(code.GetDescription(), args); } else { this._errorMessage = code.GetDescription(); } this.OnHasErrorChanged(EventArgs.Empty); this.InvalidateBorder(); } } /// /// 清除验证不通过错误 /// protected void ClearError() { this.SetError(false, ControlErrorCode.DKC_0000); } #endregion #endregion #region IAsyncControl 成员 #region 成员变量 /// /// 异步处理开始时,控件状态 /// private bool _asyncBeginStatus = false; private bool _asyncBeginFocused = false; #endregion #region 公有方法 /// /// 开始异步处理 /// /// 是否处理焦点 public virtual void BeginAsync(ref bool doFocus) { this._asyncBeginFocused = false; if (doFocus && this.Focused) { this._asyncBeginFocused = true; doFocus = false; } this._asyncBeginStatus = this.ReadOnly; this.ReadOnly = true; } /// /// 结束异步处理 /// public virtual void EndAsync() { this.ReadOnly = this._asyncBeginStatus; if (this._asyncBeginFocused) { this.Focus(); } } #endregion #endregion } }