65.9K
CodeProject 正在变化。 阅读更多。
Home

.NET LCD MatrixControl 和 GDI+

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.74/5 (13投票s)

2004年6月20日

1分钟阅读

viewsIcon

94096

downloadIcon

4640

使用 C# 在 .NET 中实现 LCD 用户控件。

Sample Image - LCDMatrixControl_screen.gif

引言

曾经,我需要一个类似于 LCD 的控件来展示数据。在互联网上搜索后,我找到了 Nic Wilson 的一个不错的实现 Nic Wilson。但是代码是用 C++ 编写的,而我的项目是用 C# 的。因此,我决定重写 Nic 的代码,同时我也想评估 GDI+ 在 .NET 中的运行速度。

使用代码

在您的项目中,您需要引用包含我们控件的库,然后在设计时将控件放置在您的项目中。

完成设计后,在构造函数中开始初始化我们的控件。

public Form1()
{
  InitializeComponent();
  BkColor = Color.FromArgb(R,G,B);
  OnColor = Color.FromArgb(R,G,B);
  OffColor = Color.FromArgb(R,G,B);
  //Set up initial text.
  this.matrixControl1.ScreenText = " Info Text ";
  //In this case pad symbol is empty.
  matrixControl1.SetAutoPadding(true,' ');
  //If you want immeditely start scrolling, 
  //please uncomment next line.
  //matrixControl1.DoScroll(1000, 
  //    MatrixLib.MatrixControl.ScrollDirection.Left);
}

主要的“魔术”发生在 OnPaint 方法中。

protected override void OnPaint(PaintEventArgs pea) 
{
  Rectangle m_rect = this.DisplayRectangle;
  //Create buffer image
  Bitmap _buffImage = new Bitmap(m_rect.Width,m_rect.Height);
  Graphics _buff = Graphics.FromImage(_buffImage);
  int x = 0, y = 0;
  int strlen = m_StrText.Length;
  if (strlen == 0)
    return;
  //Create array of color maps
  System.Drawing.Imaging.ColorMap []_ColorMap = 
            new System.Drawing.Imaging.ColorMap[3];
  _ColorMap[0] = new System.Drawing.Imaging.ColorMap();
  _ColorMap[1] = new System.Drawing.Imaging.ColorMap();
  _ColorMap[2] = new System.Drawing.Imaging.ColorMap();
  _ColorMap[0].OldColor = SEGM_COLORS[0];
  _ColorMap[0].NewColor = m_crOnColor;
  _ColorMap[1].OldColor = SEGM_COLORS[1];
  _ColorMap[1].NewColor = m_OffColor;
  _ColorMap[2].OldColor = SEGM_COLORS[2];
  _ColorMap[2].NewColor = m_crBackColor;
  
  //Obtain image attributes
  System.Drawing.Imaging.ImageAttributes bmpAttr = 
          new System.Drawing.Imaging.ImageAttributes();
  try
  {
    bmpAttr.SetRemapTable(_ColorMap);
  }
  catch(System.Exception ex)
  {
    Debug.Fail(ex.Message);
  }
  int charcount = 0;
  int linecount = 1;
  SolidBrush hbBkBrush = new SolidBrush(m_crBackColor);
  //Fill control rectangle 
  _buff.FillRectangle(hbBkBrush,m_rect);
  //Initialize two rectangeles
  Rectangle clipDstn = Rectangle.Empty;
  Rectangle clipSrc = Rectangle.Empty;

  //Now we will start main processing.
  for (int ix = 0; ix < strlen; ix++)
  {
    //This method calculates clip region for current char.
    GetCharBmpOffset((char)m_StrText[ix], ref clipSrc);
    //Initializes target clip.
    clipDstn = new Rectangle(x,y,clipSrc.Width,clipSrc.Height);
    //Draw current symbol in buffer
    _buff.DrawImage(m_ImageMatrix, clipDstn, clipSrc.X, 
              clipSrc.Y, clipSrc.Width, clipSrc.Height, 
              GraphicsUnit.Pixel, bmpAttr);

    x += m_CharWidth + m_XSpacing;
    charcount++;
    if ((charcount == m_MaxXChars) && m_MaxYChars == 1)
    {
      break;
    }
    else if ((charcount == m_MaxXChars) && m_MaxYChars > 1)
    {
      if (linecount == m_MaxYChars)
      {
        break;
      }
      x = charcount = 0;
      y += m_CharHeight + m_YSpacing;
      linecount++;
    }
  }
  //And finally draw our image on control surface.
  pea.Graphics.DrawImage(_buffImage,0,0); 
  //Next lines are necessary...
  hbBkBrush.Dispose();
  hbBkBrush= null;
  bmpAttr.Dispose();
  bmpAttr = null;
  _buff.Dispose();_buff = null;

  _buffImage.Dispose(); _buffImage = null;
}

结论和当前问题

该控件运行良好,没有闪烁,但是,如果您在不滚动的情况下使用该控件。如果您需要滚动,您的应用程序将占用 100% 的 CPU!!!。

可能,以下行导致了 CPU 时间的大量消耗

...

//Draw current symbol in buffer 
_buff.DrawImage(m_ImageMatrix, clipDstn, clipSrc.X, 
          clipSrc.Y, clipSrc.Width, clipSrc.Height, 
          GraphicsUnit.Pixel, bmpAttr);
...

确实如此……如果您注释掉这一行,您将获得 0% 的 CPU 使用率。

结论

对于繁重的操作,最好使用 API 的本机方法。您可以尝试用另一行替换这一行,并尝试使用 API 方法

[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
private static extern bool BitBlt(
IntPtr hdcDest, // handle to destination DC
int nXDest, // x-coord of dest upper-left corner
int nYDest, // y-coord of dest upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coord of source upper-left corner
int nYSrc, // y-coord of source upper-left corner
System.Int32 dwRop // raster operation code
);
© . All rights reserved.