1. 首页
  2. 程序生涯
  3. .NET

C#制作高仿360安全卫士窗体(三)- 文本框

距上篇C#制作高仿360安全卫士窗体(二)也将近一个多月了,这个月事情还是像往常一样的多。不多我也乐在其中,毕竟我做的是我喜欢做的东西。今天特地抽空把怎么制作文本框写一下。同时也希望有爱好这些玩意的同仁和我进行交流…
文本框的开发比起按钮开发还是有一点不同,因为我这里主要是给文本框做美化,所以不需要完完全全的进行自己开发。只是重写它的某些事件,然后展现不同的效果。下面是运行后的效果。
20130911154725
这个文本框实现了多行以及鼠标进入移出等事件的效果,那么开发这个素材只有一个也是从之前360皮肤包里面提取出来进行修改的:
Textbox
一、嵌入资源
将以上素材另存为,在解决方案中Images目录里面建立一个TextBoxImages文件夹,将图片素材拷贝进去,并设置图片属性中生成操作选择为“嵌入的资源”。

二、添加控件
资源嵌入之后再在ControlEx目录中建立一个TextBoxEx文件夹,在该文件夹下创建一个名为TextBoxEx的用户控件。该用户控件是用来实现皮肤变化,而真正的TextBox需要再从工具栏中拖一个到用户控件中。调整用户控件的宽高为为160*22,TextBox的宽高为154*16,TextBox的Margin属性为3,3,3,3,TextBox的BorderStyle属性值为None,将属性都调整完毕之后就可以开始进行代码的处理了。
20130911160133

三、编码
该控件的主要处理方法都比较简单,主要思路是重写TextBox的状态,然后再在用户控件上根据状态绘制不同的样式。
1、变量声明

#region 声明
private Bitmap _TextBoxBackImg = ImageObject.GetResBitmap("FANGSI.UI.Images.TextBoxImages.Textbox.png");
private State state = State.Normal;
private bool _Isico = false;
private Bitmap _Ico;
private Padding _IcoPadding = new Padding(3, 3, 0, 0);
//枚鼠标状态
private enum State
{
    Normal = 1,
    MouseOver = 2,
    MouseDown = 3,
    Disable = 4,
    Default = 5
}
#endregion

2、构造参数处理,初始化控件的属性

#region 构造
public TextBoxEx()
{
    InitializeComponent();
    this.SetStyle(ControlStyles.UserPaint, true);
    this.SetStyle(ControlStyles.DoubleBuffer, true);
    this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
    this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
    this.SetStyle(ControlStyles.StandardDoubleClick, false);
    this.SetStyle(ControlStyles.Selectable, true);
    this.BackColor = Color.Transparent;
}
#endregion

3、属性定义,其中可以加入自己想要功能的特殊字段再根据自己的需要进行处理

#region 属性

[Category("放肆雷特扩展属性"), Description("输入最大字符数")]
public int MaxLength
{
    get { return BaseText.MaxLength; }
    set { BaseText.MaxLength = value; }

}

[Category("放肆雷特扩展属性"), Description("与控件关联的文本")]
public new string Text
{
    get
    {
        return BaseText.Text;
    }
    set
    {
        BaseText.Text = value;
    }
}

[Category("放肆雷特扩展属性"), Description("将控件设为密码显示")]
public bool IsPass
{
    get
    {
        return BaseText.UseSystemPasswordChar;
    }
    set
    {
        BaseText.UseSystemPasswordChar = value;
    }
}

[Category("放肆雷特扩展属性"), Description("密码显示字符")]
public char PassChar
{
    get
    {
        return BaseText.PasswordChar;
    }
    set
    {
        BaseText.PasswordChar = value;
    }
}

[Category("放肆雷特扩展属性"), Description("将控件设为多行文本显示")]
public bool Multiline
{
    get
    {
        return BaseText.Multiline;
    }
    set
    {
        BaseText.Multiline = value;
        if (value)
        { 
            BaseText.Height = this.Height - 6; 
        }
        else
        {
            base.Height = 22;
            BaseText.Height = 16;
            this.Invalidate();
        }

    }
}

[Category("放肆雷特扩展属性"), Description("设置控件中文本字体")]
public Font font
{
    get
    {
        return BaseText.Font;
    }
    set
    {
        BaseText.Font = value;
    }
}

[Category("放肆雷特扩展属性"), Description("将控件设为只读")]
public bool ReadOnly
{
    get
    {
        return BaseText.ReadOnly;
    }
    set
    {
        BaseText.ReadOnly = value;
    }
}

[Category("放肆雷特扩展属性"), Description("多行文本的编辑行")]
public String[] lines
{
    get
    {
        return BaseText.Lines;
    }
    set
    {
        BaseText.Lines = value;
    }
}

[Category("放肆雷特扩展属性"), Description("是否显示图标")]
public bool Isico
{
    get
    {
        return _Isico;
    }
    set
    {
        _Isico = value;
        if (value)
        {
            if (_Ico != null)
            {
                BaseText.Location = new Point(_IcoPadding.Left + _Ico.Width, 3);
                BaseText.Width = BaseText.Width - _IcoPadding.Left - _Ico.Width;
            }
            else
            {
                BaseText.Location = new Point(25, 3);
                BaseText.Width = BaseText.Width - 25;
            }
        }
        this.Invalidate();
    }
}

[Category("放肆雷特扩展属性"), Description("图标文件")]
public Bitmap Ico
{
    get
    {
        return _Ico;
    }
    set
    {
        _Ico = value;
    }
}

[Category("放肆雷特扩展属性"), Description("控件内部间距,图标文件")]
public Padding IcoPadding
{
    get { return _IcoPadding; }
    set
    {
        _IcoPadding = value;
        this.Invalidate();
    }
}
#endregion

4、委托,委托图标点击事件

#region 委托
public event EventHandler IcoOnclick;
#endregion

5、方法处理

#region 方法
protected override void OnPaint(PaintEventArgs e)
{
    Rectangle rc = this.ClientRectangle;
    Graphics g = e.Graphics;
    ImageDrawRect.DrawRect(g, _TextBoxBackImg, rc, Rectangle.FromLTRB(10, 10, 10, 10), (int)state, 5);
    if (_Isico)
    {
        if (_Ico != null)
        {
            g.DrawImage(_Ico, new Point(_IcoPadding.Left, _IcoPadding.Top));
        }
    }
    base.OnPaint(e);
}

private void TextBoxEx_Resize(object sender, EventArgs e)
{
    if (this.Height > 22)
    {
        Multiline = true;
    }
    else
    {
        this.Height = 22;
        Multiline = false;
    }
}

private void NotifyIcoOnclick()
{
    if (IcoOnclick != null)
    {
        IcoOnclick(this, EventArgs.Empty);
    }
}

public void AppendText(string ss)
{
    BaseText.AppendText(ss);
}

private void BaseText_MouseEnter(object sender, EventArgs e)
{
    state = State.MouseOver;
    this.Invalidate();
}

private void BaseText_MouseLeave(object sender, EventArgs e)
{
    state = State.Normal;
    this.Invalidate();
}

private void TextBoxEx_MouseUp(object sender, MouseEventArgs e)
{
    if (_Ico != null)
    {
        if (new Rectangle(_IcoPadding.Left, _IcoPadding.Top, _Ico.Width, _Ico.Height).Contains(e.X, e.Y))
        {
            NotifyIcoOnclick();
        }
    }
}

private void TextBoxEx_MouseEnter(object sender, EventArgs e)
{
    state = State.MouseOver;
    this.Invalidate();
}

private void TextBoxEx_MouseLeave(object sender, EventArgs e)
{
    state = State.Normal;
    this.Invalidate();
}
#endregion

OK,写完收工…这个控件功力强大,使用简单很符合中国程序猿的使用习惯直接从工具栏拖放即可..如果还有不懂的欢迎进行留言。下一篇就开始讲360安全卫士最上面一排的水晶按钮的制作敬请期待喔。。

原创文章,作者:锋哥,如若转载,请注明出处:https://www.fangsi.net/519.html

发表评论

登录后才能评论

评论列表(10条)

  • 鲨鱼
    鲨鱼 2013年10月28日 10:28

    当文本框的长度过小的时候,左右边框不见了。BUG怎么解决?

    • 胖子
      锋哥 回复 鲨鱼 2013年10月28日 10:34

      文本框长度最少不能小于两边边框的长度。在改变大小时做下控制限制最小长度就没有问题了。

    • 鲨鱼
      鲨鱼 回复 锋哥 2013年10月28日 11:02

      两边边框的长度是什么?不是很理解,例如文本框长度是50,那么两边边框的长度应该是多少呢?
      另外,我想问的我的确不需要那么长的文本框怎么办呢?

    • 胖子
      锋哥 回复 鲨鱼 2013年10月28日 11:17

      这个长度和你在写控件的时候用的边距有关系,TextBox的Margin属性为3,3,3,3,那么再加上你的文本框长度。那就是56px,最小宽度不能低于8px文本框就算1像素的边框。

    • 鲨鱼
      鲨鱼 回复 锋哥 2013年10月28日 11:15

      好像,文本框的长度是没有小于两边边框的长度,如果文本框是20px,两边边框才6px,但是这时,已经消失了左边的边框。

    • 胖子
      锋哥 回复 鲨鱼 2013年10月28日 11:24

      你先要理解这个文本框是怎么出来的,是一个文本框和一个用户控件作为背景通过重写文本框的鼠标移出移入事件进行效果的处理。如果左边的边框消失了,是不是里面的文本框把左边的边框遮住了呢?你在缩小的时候控制一下文本框相对于用户控件的左边距呢看看可以不

    • 鲨鱼
      鲨鱼 回复 锋哥 2013年10月28日 11:51

      我将文本框的起点坐标设在X=25,左边框还是会消失。
      我尝试DrawRect方法测试。
      if (r.Height > img.Height && r.Width <= img.Width / Totalindex)
      {
      r1 = new Rectangle(x, y, img.Width / Totalindex, lr.Top);
      r2 = new Rectangle(x1, y1, r.Width, lr.Top);
      g.DrawImage(img, r2, r1, GraphicsUnit.Pixel);

      r1 = new Rectangle(x, y + lr.Top, img.Width / Totalindex, img.Height - lr.Top - lr.Bottom);
      r2 = new Rectangle(x1, y1 + lr.Top, r.Width, r.Height - lr.Top - lr.Bottom);
      if ((lr.Top + lr.Bottom) == 0) r1.Height = r1.Height - 1;
      g.DrawImage(img, r2, r1, GraphicsUnit.Pixel);

      r1 = new Rectangle(x, y + img.Height - lr.Bottom, img.Width / Totalindex, lr.Bottom);
      r2 = new Rectangle(x1, y1 + r.Height - lr.Bottom, r.Width, lr.Bottom);
      g.DrawImage(img, r2, r1, GraphicsUnit.Pixel);
      }

      这段代码,分别重绘了 上 、左右、下的边框。发现唯一的变量是控件本身的宽度(控制高度不变)
      也就是说边框消失和控件本身的长度变化有关。结果还是还没有搞懂!
      不过谢谢放肆大哥了。

    • 鲨鱼
      鲨鱼 回复 锋哥 2013年10月28日 11:56

      我想应该是 取出图品的上边框和左边框的比例问题。由于缩小,所以左边框变的极细,外观上好像消失了。
      做法有两个!
      1、缩小时,左边框的画法和放大时一样,分别左上,左,左下都重绘。
      2、改变原始图片的左边框宽度和上边框宽度的比例。 😮

    • 胖子
      锋哥 回复 鲨鱼 2013年10月28日 12:00

      绘制的图片是不会按照比例缩小的。你把图片放大就可以看出,并没有质量的损失。你说的这个bug主要得改变用户控件里面的那个文本框的大小来解决。

  • 1111
    1111 2013年10月20日 09:38

    😆

联系我们

在线咨询:点击这里给我发消息

邮件:service@fangsi.net

工作时间:周一至周五,9:30-18:30,节假日休息