如何重画Windows控件

http://www.uncj.net/bbs/index.asp 2003-1-17 ;程序员大联盟

概述

当你在全新体验Windows XP令人赏心悦目的界面的时候,你一定在想"如果我的程序界面也都能这么漂亮,那该多好啊"。那就让我们来看看到底应该如何通过.NET类库来重画Windows标准控件。

本文通过两个例子来阐述如何通过程序编码来有效的改变Windows标准控件外观。

平台需求

Visual Studio .NET
Visual C# .NET

例1:改变控件属性

使用Visual Studio .NET来开发软件时,可以利用其强大的IDE环境来手工设定界面控件的属性。但是如果你要使你整个程序上的控件风格都是某种特定属性的话,那最好的方法就是自己重载控件类。

让我们从最简单的System.Windows.Forms.Button类开始尝试,按钮有如下的常用属性:

BackColor--按钮的背景颜色

Cursor--鼠标状态

Enabled--是否启用按钮

FlatStyle--按钮的扁平风格

Font--按钮上的字体

ForeColor--按钮的前景颜色

Height--按钮的高度

Image--按钮上的图片

Location--按钮上的位置

Text--按钮上的文字

Visible--按钮是否可见

Width--按钮的宽度

在下面的这个例子里面,我们得到一个蓝底白字的扁平按钮:

1、在Visual C# .NET中新建一个Windows Application项目,命名为OwnDrawButton1;

2、往项目中添加一个MyButton类,将其改为继承System.Windows.Forms.Button,并在构造函数中添加修改属性的代码;

就像这样:

public class MyButton : System.Windows.Forms.Button
{
    public MyButton()
    {
        //set the back color to blue
        BackColor = System.Drawing.Color.Blue;
        //set the appearance style to flat
        FlatStyle = System.Windows.Forms.FlatStyle.Flat;
        //use system default font
        Font = System.Windows.Forms.Control.DefaultFont;
        //use white color to write text and draw the border
        ForeColor = System.Drawing.Color.White;
    }
}

3、拖一个按钮到Form1上,右击鼠标,单击"View Code",在代码中用"MyButton"替换掉"System.Windows.Forms.Button";

4、编译执行。

现在,你就能在你的界面上看到自定义的控件了(如图1)。

img_1
图1 通过代码修改控件属性的按钮

例2:重画简单控件

仅通过改变控件的属性值来自定义控件,在很多情况下是不能令人满意的。例如如果想把Windows XP里那种风格的按钮放到Windows 98/2000下,你就得自己来画那些按钮了。

在这种情况下,你可以通过重载OnPaint()等事件来重画按钮。你也可以通过EventHandler来让控件响应更多的事件,例如,我们可以给按钮添加鼠标悬停效果,给MouseEnter和MouseLeave分别加上EeventHandler,这样,你在事件响应函数里写的代码就会被调用。

下面是一个例子,这个例子编写了一个类似Windows XP中按钮风格的控件:

1、在Visual C# .NET中新建一个Windows Application项目,命名为OwnDrawButton2;

2、往项目中添加一个MyButton类,将其改为继承System.Windows.Forms.Button,在构造函数中添加修改属性的代码和事件响应关联代码,并编写各函数代码,如下所列:

using System;
using System.Drawing;
using System.Windows;
using System.Windows.Forms;

namespace OwnDrawButton2
{
    public class MyButton : System.Windows.Forms.Button
    {
        //state variable for mouse down
        private bool mouseDown = false;

        //state variable for mouse hover
        private bool mouseHover = false;

        public MyButton()
        {
            //set the control UserPaint
            SetStyle(ControlStyles.UserPaint, true);

            //EventHandler for MouseDown
            MouseDown += new MouseEventHandler(OnMouseDown);

            //EventHandler for MouseUp
            MouseUp += new MouseEventHandler(OnMouseUp);

            //EventHandler for MouseEnter
            MouseEnter += new EventHandler(OnMouseEnter);

            //EventHandler for MouseLeave
            MouseLeave += new EventHandler(OnMouseLeave);

            Height = 23;//Default Height
            Width = 75;//Default Width
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            //first, paint the control with parent form's background color
            pe.Graphics.FillRectangle(new SolidBrush(Parent.BackColor),
            pe.ClipRectangle);

            //if the button is disabled, draw the disable style
            if (Enabled == false)
            {
                DrawDisableButton(pe.Graphics);
            }
            else if (mouseDown)
            {
                //when mouse down, draw the mouse down style
                DrawMouseDownButton(pe.Graphics);
            }
            else if (mouseHover)
            {
                //when mouse hover, draw the mouse hover style
                DrawMouseHoverButton(pe.Graphics);
            }
            else if (Focused)
            {
                //when mouse is focused but not mouse hover,
                //draw the focus style
                DrawContainFocusButton(pe.Graphics);
            }
            else//else, draw the normal style
            {
                DrawNormalButton(pe.Graphics);
            }
            WriteText(pe.Graphics);//write text
        }

        private void OnMouseDown(object sender, MouseEventArgs e)
        {
            mouseDown = true; //mouse is down now
        }

        private void OnMouseUp(object sender, MouseEventArgs e)
        {
            mouseDown = false; //mouse is up now

            //call paint action
            PaintEventArgs pe =
            new PaintEventArgs(CreateGraphics(), ClientRectangle);

            OnPaint(pe);
        }

        private void OnMouseEnter(object sender, EventArgs e)
        {
            mouseHover = true; //mouse hover on

            //call paint action
            PaintEventArgs pe =
            new PaintEventArgs(CreateGraphics(), ClientRectangle);

            OnPaint(pe);
        }

        private void OnMouseLeave(object sender, EventArgs e)
        {
            mouseHover = false; //mouse is not hover on

            //call paint action
            PaintEventArgs pe =
            new PaintEventArgs(CreateGraphics(), ClientRectangle);

            OnPaint(pe);
        }

        private void DrawBorder(Graphics g, int state)
        {
            if (state == 1)//draw normal style broder
            {
                Pen p = new Pen(SystemColors.ControlLightLight, 2);
                g.DrawLine(p, 1, 1, 1, Height - 2);
                g.DrawLine(p, 1, 1, Width - 2, 1);
                g.DrawLine(p, Width - 1, 2, Width - 1, Height - 2);
                g.DrawLine(p, 2, Height - 1, Width - 2, Height - 1);
            }
            else if (state == 2)//draw hover style border
            {
                Pen p = new Pen(Color.Yellow, 2);
                g.DrawLine(p, 1, 1, 1, Height - 2);
                g.DrawLine(p, 1, 1, Width - 2, 1);
                g.DrawLine(p, Width - 1, 2, Width - 1, Height - 2);
                g.DrawLine(p, 2, Height - 1, Width - 2, Height - 1);
            }
            else if (state == 3)//draw pressed style border
            {
                Pen p = new Pen(SystemColors.ControlDark, 2);
                g.DrawLine(p, 1, 1, 1, Height - 2);
                g.DrawLine(p, 1, 1, Width - 2, 1);
                g.DrawLine(p, Width - 1, 2, Width - 1, Height - 2);
                g.DrawLine(p, 2, Height - 1, Width - 2, Height - 1);
            }
            else if (state == 4)//draw disabled style border
            {
                Pen p = new Pen(SystemColors.ControlLight, 2);
                g.DrawLine(p, 1, 1, 1, Height - 2);
                g.DrawLine(p, 1, 1, Width - 2, 1);
                g.DrawLine(p, Width - 1, 2, Width - 1, Height - 2);
                g.DrawLine(p, 2, Height - 1, Width - 2, Height - 1);
            }
            else if (state == 5)//draw default style border
            {
                Pen p = new Pen(Color.SkyBlue, 2);
                g.DrawLine(p, 1, 1, 1, Height - 2);
                g.DrawLine(p, 1, 1, Width - 2, 1);
                g.DrawLine(p, Width - 1, 2, Width - 1, Height - 2);
                g.DrawLine(p, 2, Height - 1, Width - 2, Height - 1);
            }
            if (state == 4)//draw disable style border
            {
                Pen p = new Pen(Color.FromArgb(161, 161, 146), 1);
                g.DrawLine(p, 0, 2, 0, Height - 3);
                g.DrawLine(p, 2, 0, Width - 3, 0);
                g.DrawLine(p, Width - 1, 2, Width - 1, Height - 3);
                g.DrawLine(p, 2, Height - 1, Width - 3, Height - 1);
                g.DrawLine(p, 0, 2, 2, 0);
                g.DrawLine(p, 0, Height - 3, 2, Height - 1);
                g.DrawLine(p, Width - 3, 0, Width - 1, 2);
                g.DrawLine(p, Width - 3, Height - 1, Width - 1, Height - 3);
            }
            else//draw normal style border
            {
                g.DrawLine(Pens.Black, 0, 2, 0, Height - 3);
                g.DrawLine(Pens.Black, 2, 0, Width - 3, 0);
                g.DrawLine(Pens.Black, Width - 1, 2, Width - 1, Height - 3);
                g.DrawLine(Pens.Black, 2, Height - 1, Width - 3, Height - 1);
                g.DrawLine(Pens.Black, 0, 2, 2, 0);
                g.DrawLine(Pens.Black, 0, Height - 3, 2, Height - 1);
                g.DrawLine(Pens.Black, Width - 3, 0, Width - 1, 2);
                g.DrawLine(Pens.Black, Width - 3, Height - 1,
                Width - 1, Height - 3);
            }
        }

        private void DrawNormalButton(Graphics g)//draw normal style button
        {
            //draw normal style border
            DrawBorder(g, 1);

            //paint background
            PaintBack(g, SystemColors.ControlLightLight);
        }

        private void DrawMouseHoverButton(Graphics g)
        {
            //draw mouse hover style border
            DrawBorder(g, 2);

            //paint background
            PaintBack(g, SystemColors.ControlLightLight);
        }

        private void DrawMouseDownButton(Graphics g)
        {
            //draw mouse down style border
            DrawBorder(g, 3);

            //paint background
            PaintBack(g, SystemColors.ControlLight);
        }

        private void DrawDisableButton(Graphics g)
        {
            //draw disable style border
            DrawBorder(g, 4);

            //paint background
            PaintBack(g, SystemColors.ControlLight);
        }

        private void DrawContainFocusButton(Graphics g)
        {
            //draw contain focuse style border
            DrawBorder(g, 5);

            //paint background
            PaintBack(g, SystemColors.ControlLightLight);
        }

        //paint background area of the button
        private void PaintBack(Graphics g, Color c)
        {
            g.FillRectangle(new SolidBrush(c), 3, 3,
            Width - 6, Height - 6);
        }

        private void WriteText(Graphics g)
        {
            //calculate the text position
            int x = 0, y = 0;
            Size s = g.MeasureString(Text, Font).ToSize();
            x = (Width - s.Width) / 2;
            y = (Height - s.Height) / 2;

            //draw text
            if (Enabled) //is enabled, draw black text
                g.DrawString(Text, Font, Brushes.Black, x, y);
            else //not enabled, draw gray text
                g.DrawString(Text, Font, Brushes.Gray, x, y);
        }
    }
}

3、在新控件的构造函数中添加:拖3个按钮到Form1上,将其中一个的"Enable"设为"false",右击鼠标,单击"View Code",在代码中用"MyButton"替换掉"System.Windows.Forms.Button";

4、编译执行。

最终,我们就得到了如图2所示的按钮控件。它可以在任何版本的windows操作系统上都保持一个样子。

img_2
图2 一个类似于Windows XP样式的按钮控件

原作者:痕迹
来 源:本站
共有561位读者阅读过此文
Contributors: FHL