• 用.NET Compact Framework创建图像按钮




      一、概述

      .NET Compact Framework为开发者设计用户界面提供大量的控件。首先必需知道在.NET Compact Framework1.0版本中并没有.NET Framework所有的特性。另外要求知道在WIN CE平台上的内存、CPU、其它资源。意义是说,必需完全了解在.NET Framework和.NET Compact Framework两者之间的各种差异.例如,大部份的标准控件如按钮,列表框和标签都不能对其OnPanit事件重载以及自画。在技术白皮书中有一个简单图像按钮的主要例子。在这个例子中主要表现在自定义自画按钮和在.NET Compact Framework中画线,文字和图片时用最佳的实用方法来实现最理想的图像性能。

      二、不能缺少什么?

      由于设备的限制,在.NET Compact Framework中并不支持所有的GDI+特性.同样你也可能知道,GDI+分成下列三大类别:

      1. 2-D vector graphics(2-D向量绘图)

      2. Imageing(成像)

      3. Typography(排版)

      2-D Vectore Graphics在 .NET Compact Framework中,Graphics对象核心仅仅是用来做画椭圆,线,图像,多边形,方形,字符串,填充椭圆,填充多边形,填充方形和填充区域。

      在Imaging这一类别中,Bitmap类支持图像处理(在小块区域)或保存图片文件。Typography(排版)的分类是有关字体变化,大小及样式。.NET Compact Framework提供对本程序的支持。但用不着害怕!我们仍然可以用GDI功能的子集创建强大的绘图应用程序。正好关注一下.NET Compact Framework中的System.Windows.Forms.DataGrid控件.该控件是在我们完全利用自画控件在上.NETCompact Framework的平台上创造的真实的高性能图形用来表示多行多列。

      三、建立图像的最佳实践

      1, 当我们建立自画控件时,衍生自System.Windows.Forms.Control和重载OnPaint以及OnPaintBackground事件。

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

    public class MyButton : Control
    {

    protected override void OnPaint(PaintEventArgs e )
    {
    //Some drawing logic
    Graphics gr = e.Graphics;
    gr.DrawImage(image, 0, 0);
    Graphics gr = e.Graphics;
    gr.DrawImage(image, 0, 0);
    gr.DrawRectangle(pen, this.ClientRectangle);
    }

    protected override void OnPaintBackground(PaintEventArgs e )
    {
    //Do nothing
    }

    }

      2、建立好画笔(Pen)、位图(Bitmap)、笔刷(Brush)对象,然后用它们的OnPaint事件。操作系统需要一些时间来处理OnPaint事件。在实例化和清除这些对象的同时也就影响了图像性能。

      3、用双缓存来减少图像在屏幕刷新时的闪烁。通常,双缓存逻辑上按下面的样子:

    protected override void OnPaint(PaintEventArgs e )
    {
    Graphics gxOff; //Offscreen graphics

    if (m_bmpOffscreen == null) //Bitmap for doublebuffering
    {
    m_bmpOffscreen = new Bitmap(ClientSize.Width, ClientSize.Height);
    }

    gxOff = Graphics.FromImage(m_bmpOffscreen);

    gxOff.Clear(this.BackColor);
    //Draw some bitmap
    gxOff.DrawImage(bmpParent, 0, 0, bmpRect, GraphicsUnit.Pixel);

    //Boundary rectangle
    Rectangle rc = this.ClientRectangle;
    rc.Width--;
    rc.Height--;

    //Draw boundary
    gxOff.DrawRectangle(new Pen(Color.Black), rc);
    //Draw from the memory bitmap
    e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);

    base.OnPaint(e);
    }

      在以上代码中,我们用Graphics对象建立了一个空的位图(Bitmap),能过Graphics类的静态方法FormImage来获取图像在控件中的大小,我们将在内存中把这些图形对象画好,当所有的好了后,才准确的把这些图形对像画在控件上,可以通过.NET Compact Framework中的ImageAttributes的参数来实现位图的透明。

    ImageAttributes imageAttr = new ImageAttributes();
    // Make a transparent key 
    imageAttr.SetColorKey(Color.White, Color.White);
    //Use the key when drawing 
    gxOff.DrawImage(m_bmp, imgRect, 0, 0, img.Width, img.Height,GraphicsUnit.Pixel, imageAttr);


      记住那些低和高的颜色键值,在SetColorKey方法中应该设置成一样的值。主要是因为.NET Compact Framework不支持用任何方法设置透明色。



      三、应用规则

      在实际的操作中,我们将建立一个自画的图像按钮控件.需要在按钮上面显示一个图片,当用户在按按钮时可以看到效果。

      我们开始 Visual Studio .NET中建立一个SmartDevice项目的Windows应用程序.在这个项目中我们加入一个新的ImageButton类。

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

    public class ImageButton : Control
    {
    //Private members 
    private Image image;
    //flag to indicate the pressed state
    private bool bPushed; 
    private Bitmap m_bmpOffscreen;

    public ImageButton()
    {
    bPushed = false;
    //default minimal size
    this.Size = new Size(21, 21); 
    }

    protected override void OnPaint(PaintEventArgs e )
    {
    //Some drawing logic
    }

    protected override void OnPaintBackground(PaintEventArgs e )
    {
    //Do nothing
    }
    }

      在以上代码中,我们用Control控件中的ImageButton类,和重载OnPaint以及OnPaintBackground事件,在上面提到,ImageButton将要一个图片用来显示,所以我们添加图像属性:

    public Image Image
    {
    get
    {
    return image; 
    }
    set
    {
    image = value;
    }
    }

      当然,还有重载OnPaint事件来绘制按钮

    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e )
    {
    Graphics gxOff; //Offscreen graphics
    Rectangle imgRect; //image rectangle
    Brush backBrush; //brush for filling a backcolor

    if (m_bmpOffscreen == null) //Bitmap for doublebuffering
    {
    m_bmpOffscreen = new Bitmap(ClientSize.Width, ClientSize.Height);
    }

    gxOff = Graphics.FromImage(m_bmpOffscreen);

    gxOff.Clear(this.BackColor);

    if (!bPushed) 
    backBrush = new SolidBrush(Parent.BackColor);
    else //change the background when it's pressed
    backBrush = new SolidBrush(Color.LightGray);

    gxOff.FillRectangle(backBrush, this.ClientRectangle);

    if (image != null)
    {
    //Center the image relativelly to the control
    int imageLeft = (this.Width - image.Width) / 2;
    int imageTop = (this.Height - image.Height) / 2;

    if (!bPushed)
    {
    imgRect = new Rectangle(imageLeft, imageTop, image.Width,
    image.Height);
    }
    else //The button was pressed
    {
    //Shift the image by one pixel
    imgRect = new Rectangle(imageLeft + 1, imageTop + 1, image.Width, 
    image.Height);
    }
    //Set transparent key
    ImageAttributes imageAttr = new ImageAttributes();
    imageAttr.SetColorKey(BackgroundImageColor(image),
    BackgroundImageColor(image));
    //Draw image
    gxOff.DrawImage(image, imgRect, 0, 0, image.Width, image.Height,
    GraphicsUnit.Pixel, imageAttr); 

    }

    if (bPushed) //The button was pressed
    {
    //Prepare rectangle
    Rectangle rc = this.ClientRectangle;
    rc.Width--;
    rc.Height--;
    //Draw rectangle
    gxOff.DrawRectangle(new Pen(Color.Black), rc);
    }

    //Draw from the memory bitmap
    e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);

    base.OnPaint(e);
    }

      根据上面章节的提要,我们成功的按.NET Compact Framework的画图方法写下了这些代码。我们先建立好绘图对象的缓存,并尽可能的用双缓存来减少图像闪烁。我们用下面的函数来帮助识别背景色,使图像透明:

    private Color BackgroundImageColor(Image image)
    {
    Bitmap bmp = new Bitmap(image);
    return bmp.GetPixel(0, 0);
    }

      上面的函数返加位图左上角的颜色。当在画按钮时,我们用bPushed标志判断按钮按下否。我们可以很容易重载OnMouseDown和OnMouseUp事件:

    protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e )
    {
    bPushed = true;
    this.Invalidate();
    }

    protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
    {
    bPushed = false;
    this.Invalidate();
    }

      五、用法

      可以很容易的新建一个ImageButton控件。把下面的少量代码添加到Form 结构中:

    public Form1()
    {
    InitializeComponent();

    imageButton1 = new ImageButton();
    imageButton1.Image = new 
    Bitmap(Assembly.GetExecutingAssembly().GetManifestResourceStream("ImageButtonProject.doorin2.gif"));
    imageButton1.Location = new Point(30, 50);
    imageButton1.Size = new Size(44, 34);
    //Hook up into click event
    imageButton1.Click+=new EventHandler(imageButton1_Click);
    this.Controls.Add(imageButton1);
    }

      我们添加doorin2.gif文件,同样可以在很容易用GetManifestResourceStream方法当前集合在项目的资源中。

     
    图一(程序界面上三个按钮)

     
    图二(第一个控件按下时)

      六、结论

      .NET Compact Framework并不像.NET Framework一样提供很多可用的图形和绘图函数。这是由于平台资源限制的缘故。不过,我们可以用一些自画技巧,在用户程序中建立大量丰富和可响应的图形。
  • 相关阅读:
    [o] SQLite数据库报错: Invalid column C
    startActivityForResult和setResult详解
    [o] duplicate column name: _id 问题解决
    [O] SQLite数据库报错:no such column
    [原创] SQLite数据库使用清单(下)
    [原创] SQLite数据库使用清单(上)
    iOS CocoaPods详解之 Analyzing dependencies
    iOS UILabe的详细使用及特殊效果
    一个简单的socket通信小demo
    iOS Lable给文字添加中划线和下划线
  • 原文地址:https://www.cnblogs.com/chinatefl/p/1467552.html
Copyright © 2020-2023  润新知