在C#中制作组合控件
丽水市汽车运输集团有限公司信息中心 苟安廷
我们通常通过文本框、组合框等控件获取用户的数据输入,为告诉用户当前需要输入的内容,通常还要在上面加一个提示用的标签,如:
姓名
张三 |
如果窗体上待输入的内容很多,则要同时放大量标签,不仅工作量大,还不易于排版,本文介绍如何制作一个组合控件以简化操作,也就是将上面的标签和文本框做成一个整体,文本框移动时标签跟着移动,还可以设置提示用标签的位置、内容、字体、颜色等。
打开VS2003,新建一个windows控件库(不是windows项目),不妨取名为MultiControls吧。
将下面的代码:
public class UserControl1 : System.Windows.Forms.UserControl
{
private System.ComponentModel.Container components = null;
public UserControl1()
{
修改为:
public class TextBoxExt : System.Windows.Forms.TextBox
{
private System.ComponentModel.Container components = null;
public TextBoxExt()
{
也就是将默认的控件名称UserControl1修改为TextBoxExt,同时将基类修改为TextBox,表示该控件继承自TextBox。
单击菜单“项目”→“属性”,在“配置”后的组合框中选择“所有配置”,点“配置属性”下的“生成”,为输出路径指定一个目录,也就是无论是Debug版还是Release版,都输出到同一个目录中,便于后面的引用,如下图所示:
编译一下,保证程序没有错误。Windows控件是无法直接调试的,为了调试方便,我们要新建一个windows项目。
单击菜单“文件”→“添加项目”→“新建项目”,选择“Windows 应用程序”,不妨取名为TestTextBox,并将该项目设为启动项目。单击菜单“项目”→“项目依赖项”,设置项目TestTextBox依赖于Multicontrols,如下图:
切换到工具箱面板的“常规”选项卡中,点鼠标右键,选择“添加/移除项”,打开自定义工具箱对话框,切换到“.Net FrameWork组件”,点“浏览”按钮,找到刚才编译生成的MultiControls.dll,选择后点“确定”按钮,此时工具箱中就有了自定义控件“TextBoxExt”,切换到TestTextBox项目的Form1窗口,随便拖几个放到窗口上,可以看到,目前的TextBoxExt同标准的TextBox控件没有什么区别,因为我们还没有开始编写代码。
切换到TextBoxExt的代码窗口中(以下大部分代码均指该窗口中的代码,特殊说明除外)。
先创建一个提示用的标签(Label),由于需要一些初始信息,我们先将创建过程空着。
private System.Windows.Forms.Label m_lblPrompt=null;
private System.Windows.Forms.Label myPrompt
{
get
{
//如果提示用的标签,没有则创建一个
if((m_lblPrompt==null) && this.Parent!=null)
{
//创建过程就在后面的补上
}
return m_lblPrompt;
}
}
添加一个变量,表示文本框和Label之间的位置关系。
private System.Drawing.ContentAlignment m_lblPromptAlignment=System.Drawing.ContentAlignment.TopLeft;
public System.Drawing.ContentAlignment LabelAlignment
{
get
{
return m_lblPromptAlignment;
}
set
{
m_lblPromptAlignment=value;
this.LayoutCtrls();
}
}
上面代码中用到了一个函数this.LayoutCtrls(),表示如何具体实现文本框和标签的位置关系,代码如下:
private void LayoutCtrls()
{
//根据提示文本的排列位置设置提示文本的位置
Label lbl=myPrompt;
if(lbl!=null)
{
switch(m_lblPromptAlignment)
{
case System.Drawing.ContentAlignment.BottomCenter:
lbl.Top=this.Bottom;
lbl.Left=this.Left+(this.Width-lbl.Width)/2;
break;
case System.Drawing.ContentAlignment.BottomLeft:
lbl.Top=this.Bottom;
lbl.Left=this.Left;
break;
case System.Drawing.ContentAlignment.BottomRight:
lbl.Top=this.Bottom;
lbl.Left=this.Right-lbl.Width;
break;
case System.Drawing.ContentAlignment.MiddleCenter:
case System.Drawing.ContentAlignment.TopCenter:
lbl.Top=this.Top-lbl.Height;
lbl.Left=this.Left+(this.Width-lbl.Width)/2;
break;
case System.Drawing.ContentAlignment.TopLeft:
lbl.Top=this.Top-lbl.Height;
lbl.Left=this.Left;
break;
case System.Drawing.ContentAlignment.TopRight:
lbl.Top=this.Top-lbl.Height;
lbl.Left=this.Right-lbl.Width;
break;
case System.Drawing.ContentAlignment.MiddleLeft:
lbl.Left=this.Left-lbl.Width;
lbl.Top=this.Top+(this.Height-lbl.Height)/2;
break;
case System.Drawing.ContentAlignment.MiddleRight:
lbl.Left=this.Right;
lbl.Top=this.Top+(this.Height-lbl.Height)/2;
break;
}
}
}
设置标签的内容:
private string m_lblText="";
public string LabelText
{
get
{
return this.m_lblText;
}
set
{
m_lblText=value;
Label lbl=myPrompt;
if(lbl!=null )
{
lbl.Text=m_lblText;
LayoutCtrls();
}
}
}
有了上面的准备,接下来我们来完成前面空着的创建Label的具体过程:
private System.Windows.Forms.Label myPrompt
{
get
{
//如果提示用的标签,则创建一个
if((m_lblPrompt==null) && this.Parent!=null)
{
m_lblPrompt=new Label();
m_lblPrompt.Visible=true;
m_lblPrompt.AutoSize=true;
m_lblPrompt.BackColor= System.Drawing.Color.Transparent;
m_lblPrompt.Text=this.LabelText;
this.Parent.Controls.Add(m_lblPrompt);
this.Parent.ResumeLayout(false);
}
return m_lblPrompt;
}
}
可以参照LabelText的方法为标签设置前景、背景、字体等等。
重新编译一下解决方案,切换到TestTextBox项目的Form1窗口上,选中一个刚才添加的控件,在属性窗口中应该有LabelText属性了,如果没有找到,关闭解决方案后再重新打开一次,在属性窗口中修改一下LabelText属性的内容,看看窗口上的文本框上面是不是自动出现了提示?
同样,你还可以设置LabelAligment,调整提示标签和文本框之间的排列关系,如果移动文本框,发现标签不会跟着移动,下面我们来实现该功能。
切换到TextBoxExt的设计窗口,在属性窗口中切换到“事件”选项,双击LocationChanged事件,自动会在代码窗口中添加响应代码,为保证文本框大小改变后,不影响标签和文本框的排列,在属性窗口中找到Resize事件,此时不要双击,而是从右边的下拉框中选择刚才添加的LocationChanged事件,这样,两个事件对应同一段代码,编写的代码如下:
private void TextBoxExt_LocationChanged(object sender, System.EventArgs e)
{
this.LayoutCtrls();
}
添加文本框的Visablechanged事件如下:
private void TextBoxExt_VisibleChanged(object sender, System.EventArgs e)
{
Label lbl=myPrompt;
if(lbl!=null)
{
lbl.Visible=this.Visible;
this.LayoutCtrls();
}
}
在设计时,如果一个文本框多余了,需要删除,此时,应该同时删除对应的标签,因此,修改Dispose函数如下:
protected override void Dispose( bool disposing )
{
if( disposing )
{
//释放提示标签
Label lbl=myPrompt;
if(lbl!=null)
lbl.Dispose();
if( components != null )
components.Dispose();
}
base.Dispose( disposing );
}
到此为止,一个组合控件就完成了,你还可以根据需要制作ComboBoxExt等,也可以将更多的控件组合成一个。
本文的代码可以到ftp://202.107.251.26/下“苟安廷”文件夹中下载,文件名为“组合控件.rar”。