C# 控件自绘

本文详细介绍了如何在.NET中使用Button控件设置动态显示图片,以及如何自定义组合框的样式,包括不同状态下的图片和文本显示。通过自绘功能和事件处理,开发者可以创建具有丰富外观的控件。
摘要由CSDN通过智能技术生成

按钮控件Button

button类里的Image属性成员可以指定按钮显示的图片,相比MFC,.net里的控件可设置的属性多了许多,这样一般不需要自绘就能使控件

的外观变得丰富多彩起来。随便设置几张图片就可以了,只要在图片上下功夫就行了。

看一个示例吧,首先准备一张按钮显示的图片:

 button.jpg 125x33大小

然后往Form窗体里添加一个按钮控件,记住按钮控件要跟图片一样大小,因为Button类是不会自动缩放或者放大图片的。

示例代码如下:

        public Form1()
        {
            InitializeComponent();
            //按钮大小
            button1.Width = 125;
            button1.Height = 33;
            //按钮显示的文本
            button1.Text = "确 定";
            //按钮文本的字体
            button1.Font = new Font("宋体", 15f);
            //文本的颜色
            button1.ForeColor = Color.White;
            //按钮显示的图片
            button1.Image= Image.FromFile("d:\\Image\\button.jpg");
        }

效果图:

如果想要不同状态显示不同的图片的话,那就添加按钮事件处理函数:MouseEnter鼠标进入控件,MouseLeave鼠标离开控件,

MouseDown在控件里按下了鼠标键,MouseUp在控件里松开了鼠标键。在这些事件里更改Image属性。

完成上面的功能,需要准备三张图片。

 buttonNor.jpg 按钮正常状态下显示的图片

 buttonDown.jpg 按钮按下时显示的图片

 buttonHov.jpg 鼠标停留在按钮上显示的图片

代码如下:

public partial class Form1 : Form
    {
        //三张不同状态的图片
        public Image imgNormal = Image.FromFile("d:\\Image\\buttonNor.jpg");
        public Image imgDown = Image.FromFile("d:\\Image\\buttonDown.jpg");
        public Image imgHover = Image.FromFile("d:\\Image\\buttonHov.jpg");
        public Form1()
        {
            InitializeComponent();
            //按钮大小
            button1.Width = 125;
            button1.Height = 33;
            //按钮显示的文本
            button1.Text = "确 定";
            //按钮文本的字体
            button1.Font = new Font("宋体", 15f);
            //文本的颜色
            button1.ForeColor = Color.White;
            //按钮显示的图片
            //添加四个事件处理函数
            button1.Image= imgNormal;
            button1.MouseEnter+=btnMouseEnter;
            button1.MouseLeave+=btnMouseLeave;
            button1.MouseDown+=btnMouseDown;
            button1.MouseUp += btnMouseUp;
        }
        //四个事件处理函数
        private void btnMouseEnter(object sender, EventArgs e)
        {
            button1.Image = imgHover;
        }
        private void btnMouseLeave(object sender, EventArgs e)
        {
            button1.Image = imgNormal;
        }
        private void btnMouseDown(object sender, MouseEventArgs e)
        {
            button1.Image = imgDown;
        }
        private void btnMouseUp(object sender, MouseEventArgs e)
        {  
            button1.Image = imgHover;
        } 
    }

按钮控件自绘:

如果需要自绘按钮控件,就不能通过添加事件的方式了,因为这样虽然也可以参与绘制,但Button类默认也绘制了,这样就不可避免的会起冲突。而且影响效率,比如按钮按下,系统默认绘制其状态,然后你又重新绘制。那么默认的绘制完全没必要。

所以我们不让能基类来处理某些事件,要怎么实现呢,重写基类的事件处理函数就可以了。

这个在《GDI+编程(一)》里的绘制背景中已经说明过了。

看例子吧,我省了很多事,只把关键点说出来。连按钮的文本都没绘制,只是简单的绘制几张图片。

给项目工程添加一个MyButton.cs文件,这个文件里的代码如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace WindowsApplication2
{
    public class MyButton:Button
    {
        //按钮三种状态的图片
        public Image imgNormal = Image.FromFile("d:\\Image\\buttonNor.jpg");
        public Image imgDown = Image.FromFile("d:\\Image\\buttonDown.jpg");
        public Image imgHover = Image.FromFile("d:\\Image\\buttonHov.jpg");
        //全部禁止默认处理函数处理这些事件
        protected override void OnMouseEnter(EventArgs e)
        {
            //base.OnMouseEnter(e);
            CreateGraphics().DrawImage(imgHover, new Rectangle(0, 0, Width, Height));
        }
        protected override void OnMouseLeave(EventArgs e)
        {
            //base.OnMouseLeave(e);
            CreateGraphics().DrawImage(imgNormal, new Rectangle(0, 0, Width, Height));
        }
        protected override void OnMouseDown(MouseEventArgs mevent)
        {
           // base.OnMouseDown(mevent);
            CreateGraphics().DrawImage(imgDown, new Rectangle(0, 0, Width, Height));
        }
        protected override void OnMouseUp(MouseEventArgs mevent)
        {
           // base.OnMouseUp(mevent);
            CreateGraphics().DrawImage(imgHover, new Rectangle(0, 0, Width, Height));
            EventArgs e = new EventArgs();
            base.OnClick(e);
        }
        protected override void OnPaint(PaintEventArgs pevent)
        {
            //base.OnPaint(pevent);
            //只绘制一个正常状态,其它状态就不绘制了
            pevent.Graphics.DrawImage(imgNormal, new Rectangle(0, 0, Width, Height));
           }
    }

}

在OnMouseUp调用了OnClick,是因为禁止了基类处理MouseUp事件,那么它就监测不到单击的事件,这样通过Click添加的处理函数,都不会被执行。

所以在这里调用OnClick。另外Paint事件也是一样的。
Form1类的部分代码:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            //创建按钮
            button1 = new MyButton();
            button1.Location = new Point(50, 50);
            button1.Size = new Size(90, 35);
            this.Controls.Add(button1);
        }
        public MyButton button1;
    }

自绘组合框

给组合框添加DrawItem事件处理函数,就可以自绘组合框,这个DrawItem事件跟MFC里的WM_DRAWITEM消息有点类似,它们的绘制方式都没相差多少。

DrawItem事件处理函数的定义:

private void ComboBox1_DrawItem(object sender, DrawItemEventArgs e)

参数e存储有项各的信息,比如e.State项的状态,e.Bounds一个项的矩形区域。

这个自绘组框要实现项对应的图片绘制,也就是实现可以给一个项关联图片的功能,那么就要给每一个项自定义数据了。但不像MFC组合框

的类,可以调用SetItemData函数给一个项关联自定义数据。.net里面的ComboBox可没类似的功能。

但是我们在添加项的时候发现,comboBox1.Items.Add函数的参数都是Object类型,这样我们就可以自定义一个类,描述项的信息。

这个类对象当然也可以转换成Object类型,因为所有的类都是从Object派生出来的。

关键代码如下:(记得准备五张图片,用于项图片显示)

    //自定义组合框项
    public class MyItem
    {
        //项文本内容
        private String Text;
        //项图片
        public Image Img;
        public MyItem(String text, Image img)
        {
            Text = text;
            Img = img;
        }
        //重写ToString函数,返回项文本
        public override string ToString()
        {
            return Text;
        }
    }
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            //添加项
            comboBox1.Items.Add(new MyItem("1111111", Image.FromFile("d:\\Image\\qq1.jpg")));
            comboBox1.Items.Add(new MyItem("2222222", Image.FromFile("d:\\Image\\qq2.jpg")));
            comboBox1.Items.Add(new MyItem("3333333", Image.FromFile("d:\\Image\\qq3.jpg")));
            comboBox1.Items.Add(new MyItem("4444444", Image.FromFile("d:\\Image\\qq4.jpg")));
            comboBox1.Items.Add(new MyItem("5555555", Image.FromFile("d:\\Image\\qq5.jpg"))); 
            //默认选中项索引
            comboBox1.SelectedIndex = 0;
            //自绘组合框需要设置的一些属性
            comboBox1.DrawMode = DrawMode.OwnerDrawVariable;
            comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
            comboBox1.ItemHeight = 30;
            comboBox1.Width = 200;
            //添加DrawItem事件处理函数
            comboBox1.DrawItem += ComboBox1_DrawItem;
         
        }

        private void ComboBox1_DrawItem(object sender, DrawItemEventArgs e)
        {
            if ((e.State & DrawItemState.Selected) != 0)//鼠标选中在这个项上
            {
                //渐变画刷
                LinearGradientBrush brush = new LinearGradientBrush(e.Bounds, Color.FromArgb(255, 251, 237),
                                                 Color.FromArgb(255, 236, 181),LinearGradientMode.Vertical);
                //填充区域
                Rectangle borderRect = new Rectangle(3, e.Bounds.Y + 1, e.Bounds.Width - 5, e.Bounds.Height - 2);

                e.Graphics.FillRectangle(brush, borderRect);
                //画边框
                Pen pen = new Pen(Color.FromArgb(229, 195, 101));
                e.Graphics.DrawRectangle(pen, borderRect);
            }
            else
            {
                SolidBrush brush = new SolidBrush(Color.FromArgb(217,223,230));
                e.Graphics.FillRectangle(brush, e.Bounds);
            }
            //获得项图片,绘制图片
            MyItem item=(MyItem)comboBox1.Items[e.Index];
            Image img = item.Img;
            //图片绘制的区域
            Rectangle imgRect = new Rectangle(6, e.Bounds.Y+3, 25, 25);
            e.Graphics.DrawImage(img, imgRect);
            //文本内容显示区域
            Rectangle textRect =
                new Rectangle(imgRect.Right + 2, imgRect.Y, e.Bounds.Width - imgRect.Width, e.Bounds.Height-2);
            //获得项文本内容,绘制文本
            String itemText = comboBox1.Items[e.Index].ToString();
            //文本格式垂直居中
            StringFormat strFormat=new StringFormat();
            strFormat.LineAlignment=StringAlignment.Center;
            e.Graphics.DrawString(itemText, new Font("宋体", 12), Brushes.Black, textRect, strFormat);
        }
    }

效果图:


上面的只是简单的自绘了下,如果要好好自绘一下ComboBox类,可以从ComboBox类派生出一个新类自绘。

  • 17
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
如果您要在C#中创建自绘的ListView控件,可以使用以下步骤: 1. 创建一个新的Windows窗体应用程序项目。 2. 在工具箱中找到ListView控件并将其拖放到窗体上。 3. 在窗体的代码文件中添加以下命名空间: ```csharp using System.Runtime.InteropServices; ``` 4. 在窗体的代码文件中添加以下常量和结构体: ```csharp private const int LVM_FIRST = 0x1000; private const int LVM_SETBKCOLOR = LVM_FIRST + 1; private const int LVM_SETTEXTBKCOLOR = LVM_FIRST + 38; private const int LVM_SETTEXTCOLOR = LVM_FIRST + 36; [StructLayout(LayoutKind.Sequential)] public struct LVITEM { public int mask; public int iItem; public int iSubItem; public int state; public int stateMask; public IntPtr pszText; public int cchTextMax; public int iImage; public IntPtr lParam; public int iIndent; public int iGroupId; public int cColumns; public IntPtr puColumns; } [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); ``` 5. 在窗体的代码文件中添加以下方法: ```csharp private void SetListViewProperties() { // 设置背景颜色 SendMessage(listView1.Handle, LVM_SETBKCOLOR, 0, SystemColors.Window.ToArgb()); // 设置文本背景颜色 SendMessage(listView1.Handle, LVM_SETTEXTBKCOLOR, 0, SystemColors.Window.ToArgb()); // 设置文本颜色 SendMessage(listView1.Handle, LVM_SETTEXTCOLOR, 0, SystemColors.ControlText.ToArgb()); } private void DrawListViewItem(DrawListViewItemEventArgs e) { // 自定义项的绘制方式 // ... } ``` 6. 在窗体的代码文件中添加以下事件处理程序: ```csharp private void Form1_Load(object sender, EventArgs e) { SetListViewProperties(); } private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e) { DrawListViewItem(e); } ``` 7. 在DrawListViewItem方法中实现您自己的绘制逻辑。在这个方法中,您可以使用GDI+绘制ListView控件的项。 以上就是创建自绘的ListView控件的基本步骤。请注意,您需要在DrawListViewItem方法中实现自定义的绘制逻辑以达到您想要的外观效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bczheng1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值