自定义控件库(MaskEdit、带进度面板的状态栏等)






3.71/5 (13投票s)
2004年6月1日
5分钟阅读

87448

3176
自定义控件库(MaskEdit、带进度面板的状态栏等)。
引言
CustomControls.dll 中提供了两个控件。要使用它们,只需添加对 DLL 的引用,您应该会在工具箱中看到这两个控件(TextBoxEx
、StatusBarEx
)。
TextBoxEx
是标准 TextBox
的扩展。它支持
- 掩码、(掩码字符集中,# = 数字,A = 所有大写字母,a = 所有小写字母,$ = #,A,a,& = A,a)
- 正则表达式验证(自定义和一些内置的),
- 仅字母验证,
- 仅数字验证,
- 用户自定义字符/数字验证,
- 内置
ErrorProvider
, - 可以使用 ENTER 键代替 TAB。 (这对于数据录入类应用程序非常方便。)
StatusBarEx
是标准 StatusBar
的扩展。它支持 4 种面板类型。
- 日期面板,
- 时间面板,
- 平滑进度条面板,
- 图案进度条面板(这个只是一个花哨的)。
参考文献
我一直在寻找验证控件,找到了 Luis Alberto Ruiz Arauz 的 ValidText
控件(在 CodeProject 上发布)。因为我想要一个 C# 版本的,所以我打算将代码转换为 C# 并包含一些改进(下面讨论)。
平滑进度条的创意来自 Microsoft KB 文章 323116。
因此,也应该感谢那些与我们分享知识的人。同样,如果有人使用此代码并进行了任何修复/改进,请告知我。
我仅在 Windows 2000 上测试过此代码。但由于它仅依赖于 .NET 运行时,我认为它在其他操作系统上也能很好地工作。
TextBoxEx 的代码说明
TextBoxEx
控件的 MaskEdit 功能与 Luis 的 VB.NET 版本相比,采用了截然不同的方法。因此,我设法删减了大量代码,保留了相同的功能并修复了一些错误。
基类 TextBox
的 KeyPress
事件已被重写,所有掩码验证都在 PerformMaskValidation
方法中完成。在此方法中,对于每个掩码字符(#、A、a、%、$),将使用 IsValidInputForMask
检查有效数据。当 TextBoxEx
控件在 Mask
模式下工作时,您不能半填充掩码然后离开控件。如果您希望将其留空,可以通过不输入任何数据来实现。(但是,如果 IsRequired
属性设置为 true
,则在验证时会提示输入数据)。这意味着,对于像 (###)-AA-aa 这样的掩码
- 如果
IsRequired=true
,则掩码**必须**填写。 - 如果
IsRequired=false
,则掩码可以留空。但是,您不能半填充然后尝试离开控件。
TextBoxEx
在 Mask
模式下会捕获 SHIFT-INSERT、CTRL-V(粘贴)和上下文菜单等组合键,以便一旦设置了掩码,您将无法在运行时通过将任何值设置到 Text
属性来意外清除它。为了捕获此键盘输入,我重写了 ProcessCmdKey
事件。如果您尝试通过为 Text
属性分配某个值来覆盖掩码,它们仍然会被验证。例如,如果掩码是 (###)-AA,并且您分配 txtBoxEx.Text="AB12CDEF"
,Text
属性将仅包含 (12_)-__。(掩码从左到右填充。在这里,输入字符串只有 2 个数字,而掩码需要 3 个。因此,它接受 2 个数字并丢弃其余的。)通过这种方式,可以避免破坏掩码并抛出异常(这是其他控件会发生的情况)。因此,如果您需要在运行时重置掩码,您必须这样做
txtBoxEx.ValidationText="(###)-AA"; //your new mask string
txtBoxEx.Text="123AB"; //data
此外,如果您想一次性验证所有 TextBoxEx
控件(例如,在将数据添加到数据库之前验证整个窗体的 TextBoxEx
控件),您可以使用公共 Validate()
方法。在示例应用程序中,这在 btnValidateAll_Click()
方法中显示。
private void btnValidateAll_Click(object sender, System.EventArgs e)
{
bool allValid=true;
allValid = RecursiveControlValidation(this);
if (allValid)
MessageBox.Show(this,"All controls contain valid data");
else
MessageBox.Show(this,
"Indicated controls contain invalid/incomplete data");
}
private bool RecursiveControlValidation(Control ctl)
{
bool isValid=true;
if (ctl.HasChildren)
{
foreach(Control c in ctl.Controls)
{
isValid &=RecursiveControlValidation(c);
}
}
if(ctl.GetType()==typeof(CustomControls.TextBoxEx))
{
if ( !((CustomControls.TextBoxEx)ctl).Validate() )
{
isValid =false;
}
}
return isValid;
}
包含的另一个有用选项是按下 ENTER 键即可移动到下一个控件。这听起来可能不重要,但我在几个项目中遇到过,所有数据录入人员都坚持要求使用 ENTER 键来移动到下一个文本框。(实际上,对于数据录入来说,这比使用 TAB 容易。)在标准的 TextBox
中,您需要为此附加一个事件。但在 TestBoxEx
中,将属性 UseEnterAsTab
设置为 true
即可完成其余工作。我使用的代码是
protected override void OnKeyDown(System.Windows.Forms.KeyEventArgs e)
{
if (useEnterAsTab)
{
if (e.KeyCode == Keys.Enter)
{
SendKeys.Send("{Tab}");
e.Handled=true;
}
}
base.OnKeyDown(e);
}
代码本身包含一些其他有用的注释。如果您要修改代码,这些注释可能会对您有所帮助。
StatusBarEx 的代码说明
因为 StatusBarEx
应该支持带有进度条的面板,所以标准的 StatusBarPanel
已扩展为 StatusBarPanelEx
。为了能够在设计时将 StatusBarPanelEx
添加到 StatusBarEx
,已实现了一个设计时 CollectionEditor
。此代码位于 StatusBarPanelExCollectionEditor
类中。常规的 StatusBarPanelCollection
已被 StatusBarPanelExCollection
类覆盖。该类返回 StatusBarPanelEx
类型。StatusBarEx
中的 Panels
属性被定义为使用新的 StatusBarPanelExCollectionEditor
而不是标准的 CollectionEditor
。(否则,它在设计时只会添加 StatusBarPanel
类型。)使用哪种类型编辑器已通过以下属性进行设计
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Editor(typeof(System.ComponentModel.Design.CollectionEditor),
typeof(System.Drawing.Design.UITypeEditor))]
[Editor(typeof(StatusBarPanelExCollectionEditor),
typeof(System.Drawing.Design.UITypeEditor))]
public new StatusBarPanelExCollection Panels
{
}
待办事项
在 TextBoxEx
中,如果有人需要将掩码字符(A、a、$、&、#)保留为普通字符,则它们应该从掩码中转义。我将很快添加此功能。目前,如果您的掩码是 (###)-AA,它将被翻译为 (___)-__。但是,如果您想将上述任何掩码字符保留为普通字符呢?我将使用转义序列,因此如果您需要,可以指定像 (##\#)-A\A 这样的掩码,它将被翻译为 (__#)-_A。
此外,我将在库中添加几个我为我的项目开发的控件。目前,在获取自定义设计器正常工作方面遇到了一些麻烦。你们有人知道如何监控 Visual Studio 中的 Component Tray 以了解组件的添加/删除吗?如果知道,请告诉我。