开发者社区> 技术小胖子> 正文

How to: Display a Gradient Fill

简介:
+关注继续查看

To display a gradient fill

  1. 第一步:In Visual Studio, create a Smart Device project.

  2. 第二部:Add the Gradientfill and GradientFilledButton classes to your project.

  3.  

  4.  

  5. 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);
    }

    }

第三步:Add the Win32Helper class to your project, which contains the platform invoke and structures for native code interoperability.

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; }

 

第四步:Declare a form variable named gfButton of type GradientFilledButton.

private GradientFilledButton gfButton;

第五步:Add the following code, which initializes the gradient filled button custom control, to the constructor of the Form1 class. This code should follow the call to the InitializeComponent method. You can specify the start and ending colors of the gradient fill and either a TopToBottom or LeftToRight fill direction.

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);

 

第六步:Add the event handling code for the button's Click event to form.

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"); }

第七步:Override the OnPaint method to paint the background of the form with a gradient fill pattern. This code uses the GradientFill class but not the GradientFilledButton class.

 

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();
}

 

第八步:Build and deploy the application.


     本文转自xyz_lmn51CTO博客,原文链接:http://blog.51cto.com/xyzlmn/819955,如需转载请自行联系原作者


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,大概有三种登录方式:
9068 0
使用SSH远程登录阿里云ECS服务器
远程连接服务器以及配置环境
12457 0
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
19698 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,云吞铺子总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系统盘、创建快照、配置安全组等操作如何登录ECS云服务器控制台? 1、先登录到阿里云ECS服务器控制台 2、点击顶部的“控制台” 3、通过左侧栏,切换到“云服务器ECS”即可,如下图所示 通过ECS控制台的远程连接来登录到云服务器 阿里云ECS云服务器自带远程连接功能,使用该功能可以登录到云服务器,简单且方便,如下图:点击“远程连接”,第一次连接会自动生成6位数字密码,输入密码即可登录到云服务器上。
32729 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
17986 0
使用NAT网关轻松为单台云服务器设置多个公网IP
在应用中,有时会遇到用户询问如何使单台云服务器具备多个公网IP的问题。 具体如何操作呢,有了NAT网关这个也不是难题。
34558 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
24794 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
14681 0
阿里云服务器ECS登录用户名是什么?系统不同默认账号也不同
阿里云服务器Windows系统默认用户名administrator,Linux镜像服务器用户名root
13821 0
21117
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载