显示渐变填充(摘自:msdn)

.NET Framework 开发人员指南
如何:显示渐变填充

 

通过显示渐变填充,可将鲜艳动人的图形添加到应用程序。下面的代码示例演示如何在自定义控件中作为窗体背景显示渐变填充。

过程

显示渐变填充

  1. 在 Microsoft Visual Studio 2005 中,创建一个智能设备 Pocket PC 项目。

  2. GradientfillGradientFilledButton 类添加到项目中。

    Visual Basic
    NotInheritable Public Class GradientFill
        
        ' This method wraps the PInvoke to GradientFill.
        ' Parmeters:
        '  gr - The Graphics object we are filling
        '  rc - The rectangle to fill
        '  startColor - The starting color for the fill
        '  endColor - The ending color for the fill
        '  fillDir - The direction to fill
        '
        ' Returns true if the call to GradientFill succeeded; false
        ' otherwise.
        Public Shared Function Fill(ByVal gr As Graphics, ByVal rc As Rectangle, ByVal startColor As Color, _
            ByVal endColor As Color, ByVal fillDir As FillDirection) As Boolean 
            
            ' Initialize the data to be used in the call to GradientFill.
            Dim tva(1) As Win32Helper.TRIVERTEX
            tva(0) = New Win32Helper.TRIVERTEX(rc.X, rc.Y, startColor)
            tva(1) = New Win32Helper.TRIVERTEX(rc.Right, rc.Bottom, endColor)
            Dim gra() As Win32Helper.GRADIENT_RECT = {New Win32Helper.GRADIENT_RECT(0, 1)}
            
            ' Get the hDC from the Graphics object.
            Dim hdc As IntPtr = gr.GetHdc()
            
            ' PInvoke to GradientFill.
            Dim b As Boolean
            
            b = Win32Helper.GradientFill(hdc, tva, CType(tva.Length, System.Int32), gra, CType(gra.Length, System.Int32), CType(fillDir, System.Int32))
            
            System.Diagnostics.Debug.Assert(b, String.Format("GradientFill failed: {0}", System.Runtime.InteropServices.Marshal.GetLastWin32Error()))
            
            ' Release the hDC from the Graphics object.
            gr.ReleaseHdc(hdc)
            
            Return b
        
        End Function
        
        ' The direction to the GradientFill will follow
        Public Enum FillDirection
    
            ' The fill goes horizontally
            LeftToRight = Win32Helper.GRADIENT_FILL_RECT_H
    
            ' The fill goes vertically
            TopToBottom = Win32Helper.GRADIENT_FILL_RECT_V
        End Enum
    End Class
    
    ' Extends the standard button control and performs
    ' custom drawing with a GradientFill background.
    Public Class GradientFilledButton
        Inherits Control
        Private components As System.ComponentModel.IContainer = Nothing
    
    
        Public Sub New()
            components = New System.ComponentModel.Container()
            Me.Font = New Font(Me.Font.Name, Me.Font.Size, FontStyle.Bold)
    
        End Sub
    
        ' Controls the direction in which the button is filled.
        Public Property FillDirection() As GradientFill.FillDirection
            Get
                Return fillDirectionValue
            End Get
            Set(ByVal value As GradientFill.FillDirection)
                fillDirectionValue = value
                Invalidate()
            End Set
        End Property
        Private fillDirectionValue As GradientFill.FillDirection
    
        ' The start color for the GradientFill. This is the color
        ' at the left or top of the control depeneding on the value
        ' of the FillDirection property.
        Public Property StartColor() As Color
            Get
                Return startColorValue
            End Get
            Set(ByVal value As Color)
                startColorValue = value
                Invalidate()
            End Set
        End Property
        Private startColorValue As Color = Color.Red
    
        ' The end color for the GradientFill. This is the color
        ' at the right or bottom of the control depending on the value
        ' of the FillDirection property
        Public Property EndColor() As Color
            Get
                Return endColorValue
            End Get
            Set(ByVal value As Color)
                endColorValue = value
                Invalidate()
            End Set
        End Property
        Private endColorValue As Color = Color.Blue
    
        ' This is the offset from the left or top edge
        '  of the button to start the gradient fill.
        Public Property StartOffset() As Integer
            Get
                Return startOffsetValue
            End Get
            Set(ByVal value As Integer)
                startOffsetValue = value
                Invalidate()
            End Set
        End Property
        Private startOffsetValue As Integer
    
        ' This is the offset from the right or bottom edge
        '  of the button to end the gradient fill.
        Public Property EndOffset() As Integer
            Get
                Return endOffsetValue
            End Get
            Set(ByVal value As Integer)
                endOffsetValue = value
                Invalidate()
            End Set
        End Property
        Private endOffsetValue As Integer
    
        ' Used to double-buffer our drawing to avoid flicker
        ' between painting the background, border, focus-rect
        ' and the text of the control.
        Private Property DoubleBufferImage() As Bitmap
            Get
                If bmDoubleBuffer Is Nothing Then
                    bmDoubleBuffer = New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height)
                End If
                Return bmDoubleBuffer
            End Get
            Set(ByVal value As Bitmap)
                If Not (bmDoubleBuffer Is Nothing) Then
                    bmDoubleBuffer.Dispose()
                End If
                bmDoubleBuffer = value
            End Set
        End Property
        Private bmDoubleBuffer As Bitmap
    
    
        ' Called when the control is resized. When that happens,
        ' recreate the bitmap used for double-buffering.
        Protected Overrides Sub OnResize(ByVal e As EventArgs)
            DoubleBufferImage = New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height)
            MyBase.OnResize(e)
        End Sub
    
    
        ' Called when the control gets focus. Need to repaint
        ' the control to ensure the focus rectangle is drawn correctly.
        Protected Overrides Sub OnGotFocus(ByVal e As EventArgs)
            MyBase.OnGotFocus(e)
            Me.Invalidate()
        End Sub
    
        ' Called when the control loses focus. Need to repaint
        ' the control to ensure the focus rectangle is removed.
        Protected Overrides Sub OnLostFocus(ByVal e As EventArgs)
            MyBase.OnLostFocus(e)
            Me.Invalidate()
        End Sub
    
    
        Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
            If Me.Capture Then
                Dim coord As New Point(e.X, e.Y)
                If Me.ClientRectangle.Contains(coord) <> Me.ClientRectangle.Contains(lastCursorCoordinates) Then
                    DrawButton(Me.ClientRectangle.Contains(coord))
                End If
                lastCursorCoordinates = coord
            End If
            MyBase.OnMouseMove(e)
    
        End Sub
    
        ' The coordinates of the cursor the last time
        ' there was a MouseUp or MouseDown message.
        Private lastCursorCoordinates As Point
    
    
        Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
            If e.Button = System.Windows.Forms.MouseButtons.Left Then
                ' Start capturing the mouse input
                Me.Capture = True
                ' Get the focus because button is clicked.
                Me.Focus()
    
                ' draw the button
                DrawButton(True)
            End If
    
            MyBase.OnMouseDown(e)
    
        End Sub
    
    
        Protected Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)
            Me.Capture = False
            DrawButton(False)
            MyBase.OnMouseUp(e)
        End Sub
    
        Private bGotKeyDown As Boolean = False
    
        Protected Overrides Sub OnKeyDown(ByVal e As KeyEventArgs)
            bGotKeyDown = True
            Select Case e.KeyCode
                Case Keys.Space, Keys.Enter
                    DrawButton(True)
                Case Keys.Up, Keys.Left
                    Me.Parent.SelectNextControl(Me, False, False, True, True)
                Case Keys.Down, Keys.Right
                    Me.Parent.SelectNextControl(Me, True, False, True, True)
                Case Else
                    bGotKeyDown = False
                    MyBase.OnKeyDown(e)
            End Select
    
        End Sub
    
    
        Protected Overrides Sub OnKeyUp(ByVal e As KeyEventArgs)
            Select Case e.KeyCode
                Case Keys.Space, Keys.Enter
                    If bGotKeyDown Then
                        DrawButton(False)
                        OnClick(EventArgs.Empty)
                        bGotKeyDown = False
                    End If
                Case Else
                    MyBase.OnKeyUp(e)
            End Select
    
        End Sub
    
    
        ' Override this method with no code to avoid flicker.
        Protected Overrides Sub OnPaintBackground(ByVal e As PaintEventArgs)
    
        End Sub
    
        Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
            DrawButton(e.Graphics, Me.Capture AndAlso Me.ClientRectangle.Contains(lastCursorCoordinates))
    
        End Sub
    
    
        ' Gets a Graphics object for the provided window handle
        '  and then calls DrawButton(Graphics, bool).
        ' If pressed is true, the button is drawn
        ' in the depressed state.
        Overloads Sub DrawButton(ByVal pressed As Boolean)
            Dim gr As Graphics = Me.CreateGraphics()
            DrawButton(gr, pressed)
            gr.Dispose()
        End Sub
    
    
        ' Draws the button on the specified Grapics
        ' in the specified state.
        '
        ' Parameters:
        '  gr - The Graphics object on which to draw the button.
        '  pressed - If true, the button is drawn in the depressed state.
        Overloads Sub DrawButton(ByVal gr As Graphics, ByVal pressed As Boolean)
            ' Get a Graphics object from the background image.
            Dim gr2 As Graphics = Graphics.FromImage(DoubleBufferImage)
    
            ' Fill solid up until where the gradient fill starts.
            If startOffsetValue > 0 Then
                If fillDirectionValue = GradientFill.FillDirection.LeftToRight Then
                    If pressed Then
                        gr2.FillRectangle(New SolidBrush(EndColor), 0, 0, startOffsetValue, Height)
                    Else
                        gr2.FillRectangle(New SolidBrush(StartColor), 0, 0, startOffsetValue, Height)
                    End If
                Else
                    If pressed Then
                        gr2.FillRectangle(New SolidBrush(EndColor), 0, 0, Width, startOffsetValue)
                    Else
                        gr2.FillRectangle(New SolidBrush(StartColor), 0, 0, Width, startOffsetValue)
                    End If
                End If
            End If
    
            ' Draw the gradient fill.
            Dim rc As Rectangle = Me.ClientRectangle
            If fillDirectionValue = GradientFill.FillDirection.LeftToRight Then
                rc.X = startOffsetValue
                rc.Width = rc.Width - startOffsetValue - endOffsetValue
            Else
                rc.Y = startOffsetValue
                rc.Height = rc.Height - startOffsetValue - endOffsetValue
            End If
    
            If pressed Then
                GradientFill.Fill(gr2, rc, endColorValue, startColorValue, fillDirectionValue)
            Else
                GradientFill.Fill(gr2, rc, startColorValue, endColorValue, fillDirectionValue)
            End If
    
            ' Fill solid from the end of the gradient fill
            ' to the edge of the button.
            If endOffsetValue > 0 Then
                If fillDirectionValue = GradientFill.FillDirection.LeftToRight Then
                    If pressed Then
                        gr2.FillRectangle(New SolidBrush(StartColor), rc.X + rc.Width, 0, endOffsetValue, Height)
                    Else
                        gr2.FillRectangle(New SolidBrush(EndColor), rc.X + rc.Width, 0, endOffsetValue, Height)
                    End If
                Else
                    If pressed Then
                        gr2.FillRectangle(New SolidBrush(StartColor), 0, rc.Y + rc.Height, Width, endOffsetValue)
                    Else
                        gr2.FillRectangle(New SolidBrush(StartColor), 0, rc.Y + rc.Height, Width, endOffsetValue)
                    End If
                End If
            End If
    
            ' Draw the text.
            Dim sf As New StringFormat()
            sf.Alignment = StringAlignment.Center
            sf.LineAlignment = StringAlignment.Center
            gr2.DrawString(Me.Text, Me.Font, New SolidBrush(Me.ForeColor), Me.ClientRectangle, sf)
    
            ' Draw the border.
            ' Need to shrink the width and height by 1 otherwise
            ' there will be no border on the right or bottom.
            rc = Me.ClientRectangle
            rc.Width -= 1
            rc.Height -= 1
            Dim pen As New Pen(SystemColors.WindowFrame)
    
            gr2.DrawRectangle(pen, rc)
    
            ' Draw from the background image onto the screen.
            gr.DrawImage(DoubleBufferImage, 0, 0)
            gr2.Dispose()
    
        End Sub
    
    
        Protected Overrides Sub Dispose(ByVal disposing As Boolean)
            If disposing AndAlso Not (components Is Nothing) Then
                components.Dispose()
            End If
            MyBase.Dispose(disposing)
    
        End Sub
    End Class
    
    
    public sealed class GradientFill
    {
        // This method wraps the PInvoke to GradientFill.
        // Parmeters:
        //  gr - The Graphics object we are filling
        //  rc - The rectangle to fill
        //  startColor - The starting color for the fill
        //  endColor - The ending color for the fill
        //  fillDir - The direction to fill
        //
        // Returns true if the call to GradientFill succeeded; false
        // otherwise.
        public static bool Fill(
            Graphics gr,
            Rectangle rc,
            Color startColor, Color endColor,
            FillDirection fillDir)
        {
    
            // Initialize the data to be used in the call to GradientFill.
            Win32Helper.TRIVERTEX[] tva = new Win32Helper.TRIVERTEX[2];
            tva[0] = new Win32Helper.TRIVERTEX(rc.X, rc.Y, startColor);
            tva[1] = new Win32Helper.TRIVERTEX(rc.Right, rc.Bottom, endColor);
            Win32Helper.GRADIENT_RECT[] gra = new Win32Helper.GRADIENT_RECT[] {
        new Win32Helper.GRADIENT_RECT(0, 1)};
    
            // Get the hDC from the Graphics object.
            IntPtr hdc = gr.GetHdc();
    
            // PInvoke to GradientFill.
            bool b;
    
            b = Win32Helper.GradientFill(
                    hdc,
                    tva,
                    (uint)tva.Length,
                    gra,
                    (uint)gra.Length,
                    (uint)fillDir);
            System.Diagnostics.Debug.Assert(b, string.Format(
                "GradientFill failed: {0}",
                System.Runtime.InteropServices.Marshal.GetLastWin32Error()));
    
            // Release the hDC from the Graphics object.
            gr.ReleaseHdc(hdc);
    
            return b;
        }
    
        // The direction to the GradientFill will follow
        public enum FillDirection
        {
            //
            // The fill goes horizontally
            //
            LeftToRight = Win32Helper.GRADIENT_FILL_RECT_H,
            //
            // The fill goes vertically
            //
            TopToBottom = Win32Helper.GRADIENT_FILL_RECT_V
        }
    }
    
    // Extends the standard button control and performs
    // custom drawing with a GradientFill background.
    
    public class GradientFilledButton : Control
    {
        private System.ComponentModel.IContainer components = null;
    
        public GradientFilledButton()
        {
            components = new System.ComponentModel.Container();
            this.Font = new Font(this.Font.Name, this.Font.Size, FontStyle.Bold);
        }
    
        // Controls the direction in which the button is filled.
        public GradientFill.FillDirection FillDirection
        {
            get
            {
                return fillDirectionValue;
            }
            set
            {
                fillDirectionValue = value;
                Invalidate();
            }
        }
        private GradientFill.FillDirection fillDirectionValue;
    
        // The start color for the GradientFill. This is the color
        // at the left or top of the control depeneding on the value
        // of the FillDirection property.
        public Color StartColor
        {
            get { return startColorValue; }
            set
            {
                startColorValue = value;
                Invalidate();
            }
        }
        private Color startColorValue = Color.Red;
    
        // The end color for the GradientFill. This is the color
        // at the right or bottom of the control depending on the value
        // of the FillDirection property
        public Color EndColor
        {
            get { return endColorValue; }
            set
            {
                endColorValue = value;
                Invalidate();
            }
        }
        private Color endColorValue = Color.Blue;
    
        // This is the offset from the left or top edge
        //  of the button to start the gradient fill.
        public int StartOffset
        {
            get { return startOffsetValue; }
            set
            {
                startOffsetValue = value;
                Invalidate();
            }
        }
        private int startOffsetValue;
    
        // This is the offset from the right or bottom edge
        //  of the button to end the gradient fill.
        public int EndOffset
        {
            get { return endOffsetValue; }
            set
            {
                endOffsetValue = value;
                Invalidate();
            }
        }
        private int endOffsetValue;
    
        // Used to double-buffer our drawing to avoid flicker
        // between painting the background, border, focus-rect
        // and the text of the control.
        private Bitmap DoubleBufferImage
        {
            get
            {
                if (bmDoubleBuffer == null)
                    bmDoubleBuffer = new Bitmap(
                        this.ClientSize.Width,
                        this.ClientSize.Height);
                return bmDoubleBuffer;
            }
            set
            {
                if (bmDoubleBuffer != null)
                    bmDoubleBuffer.Dispose();
                bmDoubleBuffer = value;
            }
        }
        private Bitmap bmDoubleBuffer;
    
        // Called when the control is resized. When that happens,
        // recreate the bitmap used for double-buffering.
        protected override void OnResize(EventArgs e)
        {
            DoubleBufferImage = new Bitmap(
                this.ClientSize.Width,
                this.ClientSize.Height);
            base.OnResize(e);
        }
    
        // Called when the control gets focus. Need to repaint
        // the control to ensure the focus rectangle is drawn correctly.
        protected override void OnGotFocus(EventArgs e)
        {
            base.OnGotFocus(e);
            this.Invalidate();
        }
        //
        // Called when the control loses focus. Need to repaint
        // the control to ensure the focus rectangle is removed.
        protected override void OnLostFocus(EventArgs e)
        {
            base.OnLostFocus(e);
            this.Invalidate();
        }
    
        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (this.Capture)
            {
                Point coord = new Point(e.X, e.Y);
                if (this.ClientRectangle.Contains(coord) !=
                    this.ClientRectangle.Contains(lastCursorCoordinates))
                {
                    DrawButton(this.ClientRectangle.Contains(coord));
                }
                lastCursorCoordinates = coord;
            }
            base.OnMouseMove(e);
        }
    
        // The coordinates of the cursor the last time
        // there was a MouseUp or MouseDown message.
        Point lastCursorCoordinates;
    
        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                // Start capturing the mouse input
                this.Capture = true;
                // Get the focus because button is clicked.
                this.Focus();
    
                // draw the button
                DrawButton(true);
            }
    
            base.OnMouseDown(e);
        }
    
        protected override void OnMouseUp(MouseEventArgs e)
        {
            this.Capture = false;
    
            DrawButton(false);
    
            base.OnMouseUp(e);
        }
    
        bool bGotKeyDown = false;
        protected override void OnKeyDown(KeyEventArgs e)
        {
            bGotKeyDown = true;
            switch (e.KeyCode)
            {
                case Keys.Space:
                case Keys.Enter:
                    DrawButton(true);
                    break;
                case Keys.Up:
                case Keys.Left:
                    this.Parent.SelectNextControl(this, false, false, true, true);
                    break;
                case Keys.Down:
                case Keys.Right:
                    this.Parent.SelectNextControl(this, true, false, true, true);
                    break;
                default:
                    bGotKeyDown = false;
                    base.OnKeyDown(e);
                    break;
            }
        }
    
        protected override void OnKeyUp(KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Space:
                case Keys.Enter:
                    if (bGotKeyDown)
                    {
                        DrawButton(false);
                        OnClick(EventArgs.Empty);
                        bGotKeyDown = false;
                    }
                    break;
                default:
                    base.OnKeyUp(e);
                    break;
            }
        }
    
        // Override this method with no code to avoid flicker.
        protected override void OnPaintBackground(PaintEventArgs e)
        {
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            DrawButton(e.Graphics, this.Capture &&
                (this.ClientRectangle.Contains(lastCursorCoordinates)));
        }
    
        //
        // Gets a Graphics object for the provided window handle
        //  and then calls DrawButton(Graphics, bool).
        //
        // If pressed is true, the button is drawn
        // in the depressed state.
        void DrawButton(bool pressed)
        {
            Graphics gr = this.CreateGraphics();
            DrawButton(gr, pressed);
            gr.Dispose();
        }
    
        // Draws the button on the specified Grapics
        // in the specified state.
        //
        // Parameters:
        //  gr - The Graphics object on which to draw the button.
        //  pressed - If true, the button is drawn in the depressed state.
        void DrawButton(Graphics gr, bool pressed)
        {
            // Get a Graphics object from the background image.
            Graphics gr2 = Graphics.FromImage(DoubleBufferImage);
    
            // Fill solid up until where the gradient fill starts.
            if (startOffsetValue > 0)
            {
                if (fillDirectionValue ==
                    GradientFill.FillDirection.LeftToRight)
                {
                    gr2.FillRectangle(
                        new SolidBrush(pressed ? EndColor : StartColor),
                        0, 0, startOffsetValue, Height);
                }
                else
                {
                    gr2.FillRectangle(
                        new SolidBrush(pressed ? EndColor : StartColor),
                        0, 0, Width, startOffsetValue);
                }
            }
    
            // Draw the gradient fill.
            Rectangle rc = this.ClientRectangle;
            if (fillDirectionValue == GradientFill.FillDirection.LeftToRight)
            {
                rc.X = startOffsetValue;
                rc.Width = rc.Width - startOffsetValue - endOffsetValue;
            }
            else
            {
                rc.Y = startOffsetValue;
                rc.Height = rc.Height - startOffsetValue - endOffsetValue;
            }
            GradientFill.Fill(
                gr2,
                rc,
                pressed ? endColorValue : startColorValue,
                pressed ? startColorValue : endColorValue,
                fillDirectionValue);
    
            // Fill solid from the end of the gradient fill
            // to the edge of the button.
            if (endOffsetValue > 0)
            {
                if (fillDirectionValue ==
                    GradientFill.FillDirection.LeftToRight)
                {
                    gr2.FillRectangle(
                        new SolidBrush(pressed ? StartColor : EndColor),
                        rc.X + rc.Width, 0, endOffsetValue, Height);
                }
                else
                {
                    gr2.FillRectangle(
                        new SolidBrush(pressed ? StartColor : EndColor),
                        0, rc.Y + rc.Height, Width, endOffsetValue);
                }
            }
    
            // Draw the text.
            StringFormat sf = new StringFormat();
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Center;
            gr2.DrawString(this.Text, this.Font,
                new SolidBrush(this.ForeColor),
                this.ClientRectangle, sf);
    
            // Draw the border.
            // Need to shrink the width and height by 1 otherwise
            // there will be no border on the right or bottom.
            rc = this.ClientRectangle;
            rc.Width--;
            rc.Height--;
            Pen pen = new Pen(SystemColors.WindowFrame);
    
            gr2.DrawRectangle(pen, rc);
    
            // Draw from the background image onto the screen.
            gr.DrawImage(DoubleBufferImage, 0, 0);
            gr2.Dispose();
        }
    
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
    
    }
    
    
  3. Win32Helper 类添加到项目中,该类包含用于本机代码互操作性的平台调用和结构。

    Visual Basic
    Public NotInheritable Class Win32Helper
    
        Public Structure TRIVERTEX
            Public x As Integer
            Public y As Integer
            Public Red As System.Int16
            Public Green As System.Int16
            Public Blue As System.Int16
            Public Alpha As System.Int16
    
            Public Sub New(ByVal x As Integer, ByVal y As Integer, ByVal color As Color)
                MyClass.New(x, y, color.R, color.G, color.B, color.A)
            End Sub
    
            Public Sub New(ByVal x As Integer, ByVal y As Integer, ByVal red As System.Int16, ByVal green As System.Int16, ByVal blue As System.Int16, ByVal alpha As System.Int16)
                Me.x = x
                Me.y = y
    
                Me.Red = CInt(red << 8)
                Me.Green = CInt(green << 8)
                Me.Blue = CInt(blue << 8)
                Me.Alpha = CInt(alpha << 8)
            End Sub
        End Structure
    
        Public Structure GRADIENT_RECT
            Public UpperLeft As System.Int32
            Public LowerRight As System.Int32
    
            Public Sub New(ByVal ul As System.Int32, ByVal lr As System.Int32)
                Me.UpperLeft = ul
                Me.LowerRight = lr
            End Sub
        End Structure
    
    
        Public Declare Function GradientFill Lib "coredll.dll" Alias "GradientFill" (ByVal hdc As IntPtr, _
         ByVal pVertex() As TRIVERTEX, ByVal dwNumVertex As Integer, _
         ByVal pMesh() As GRADIENT_RECT, ByVal dwNumMesh As Integer, _
         ByVal dwMode As Integer) As Boolean
    
        Public Const GRADIENT_FILL_RECT_H As Integer = &H0
        Public Const GRADIENT_FILL_RECT_V As Integer = &H1
    End Class
    
    public sealed class Win32Helper
    {
        public struct TRIVERTEX
        {
            public int x;
            public int y;
            public ushort Red;
            public ushort Green;
            public ushort Blue;
            public ushort Alpha;
            public TRIVERTEX(int x, int y, Color color)
                : this(x, y, color.R, color.G, color.B, color.A)
            {
            }
            public TRIVERTEX(
                int x, int y,
                ushort red, ushort green, ushort blue,
                ushort alpha)
            {
                this.x = x;
                this.y = y;
                this.Red = (ushort)(red << 8);
                this.Green = (ushort)(green << 8);
                this.Blue = (ushort)(blue << 8);
                this.Alpha = (ushort)(alpha << 8);
            }
        }
        public struct GRADIENT_RECT
        {
            public uint UpperLeft;
            public uint LowerRight;
            public GRADIENT_RECT(uint ul, uint lr)
            {
                this.UpperLeft = ul;
                this.LowerRight = lr;
            }
        }
    
    
        [DllImport("coredll.dll", SetLastError = true, EntryPoint = "GradientFill")]
        public extern static bool GradientFill(
            IntPtr hdc,
            TRIVERTEX[] pVertex,
            uint dwNumVertex,
            GRADIENT_RECT[] pMesh,
            uint dwNumMesh,
            uint dwMode);
    
        public const int GRADIENT_FILL_RECT_H = 0x00000000;
        public const int GRADIENT_FILL_RECT_V = 0x00000001;
    
    }
    
  4. 声明一个 GradientFilledButton 类型的名为 gfButton 的窗体变量。

    Visual Basic
    Private gfButton As GradientFilledButton
    
    
    private GradientFilledButton gfButton;
    
  5. 将下列代码添加到 Form1 类的构造函数中,该代码初始化渐变填充的按钮自定义控件。应该将该代码放在对 InitializeComponent 方法的调用之后。可以指定渐变填充的起始和结束颜色以及 TopToBottomLeftToRight 填充方向。

    Visual Basic
    InitializeComponent()
    Me.gfButton = New GradientFilledButton()
    Me.gfButton.Location = New System.Drawing.Point(71, 24)
    Me.gfButton.Name = "gfButton"
    Me.gfButton.Size = New System.Drawing.Size(100, 23)
    Me.gfButton.TabIndex = 1
    Me.gfButton.Text = "Button Test"
    AddHandler Me.gfButton.Click, AddressOf Me.gfButton_Click
    
    ' Select desired start color, end color, and fill direction.
    Me.gfButton.StartColor = System.Drawing.Color.SlateBlue
    Me.gfButton.EndColor = System.Drawing.Color.LightCyan
    gfButton.FillDirection = GradientFill.FillDirection.LeftToRight
    
    Me.Controls.Add(gfButton)
    
    InitializeComponent();
    this.gfButton = new GradientFilledButton();
    this.gfButton.Location = new System.Drawing.Point(71, 24);
    this.gfButton.Name = "gfButton";
    this.gfButton.Size = new System.Drawing.Size(100, 23);
    this.gfButton.TabIndex = 1;
    this.gfButton.Text = "Button Test";
    this.gfButton.Click += new System.EventHandler(this.gfButton_Click);
    
    // Select desired start color, end color, and fill direction.
    this.gfButton.StartColor = System.Drawing.Color.SlateBlue;
    this.gfButton.EndColor = System.Drawing.Color.LightCyan;
    gfButton.FillDirection = GradientFill.FillDirection.LeftToRight;
    
    this.Controls.Add(gfButton);
    
  6. 将处理按钮的 Click 事件的事件处理代码添加到窗体中。

    Visual Basic
    Private Sub gfButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) 
        Dim control As Control = sender
        System.Diagnostics.Debug.Assert( Not (control Is Nothing))
        MessageBox.Show("Clicked", "Click event handler")
    End Sub
    
    
    void gfButton_Click(object sender, System.EventArgs e)
    {
        Control control = sender as Control;
        System.Diagnostics.Debug.Assert(control != null);
        MessageBox.Show("Clicked", "Click event handler");
    }
    
  7. 重写 OnPaint 方法以渐变填充模式绘制窗体背景。该代码使用 GradientFill 类而不是 GradientFilledButton 类。

    Visual Basic
    ' Paints the background of the form with a GradientFill pattern.
    Protected Overrides Sub OnPaintBackground(ByVal e As PaintEventArgs) 
        ' On Windows Mobile Pocket PC 2003, the call to GradientFill
        ' fails with GetLastError() returning 87 (ERROR_INVALID_PARAMETER)
        ' when e.Graphics is used.
        ' Instead, fill into a bitmap and then draw that onto e.Graphics.
        Dim bm As New Bitmap(Width, Height)
        Dim gr As Graphics = System.Drawing.Graphics.FromImage(bm)
        
        GradientFill.Fill(gr, Me.ClientRectangle, Color.LightCyan, Color.SlateBlue, GradientFill.FillDirection.TopToBottom)
        e.Graphics.DrawImage(bm, 0, 0)
        gr.Dispose()
        bm.Dispose()
    
    End Sub 
    
    // Paints the background of the form with a GradientFill pattern.
    protected override void OnPaintBackground(PaintEventArgs e)
    {
        // On Windows Mobile Pocket PC 2003, the call to GradientFill
        // fails with GetLastError() returning 87 (ERROR_INVALID_PARAMETER)
        // when e.Graphics is used.
        // Instead, fill into a bitmap and then draw that onto e.Graphics.
        Bitmap bm = new Bitmap(Width, Height);
        Graphics gr = System.Drawing.Graphics.FromImage(bm);
    
        GradientFill.Fill(
            gr,
            this.ClientRectangle,
            Color.LightCyan, Color.SlateBlue,
            GradientFill.FillDirection.TopToBottom);
        e.Graphics.DrawImage(bm, 0, 0);
        gr.Dispose();
        bm.Dispose();
    }
    
  8. 生成和部署应用程序。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值