GDI+Visual Studio .NET 2002.NET 1.0Visual Studio .NET 2003.NET 1.1Windows 2000Visual C++ 6.0Windows XP中级开发Visual StudioWindowsC++.NETC#
.NET LCD MatrixControl 和 GDI+






4.74/5 (13投票s)
2004年6月20日
1分钟阅读

94096

4640
使用 C# 在 .NET 中实现 LCD 用户控件。
引言
曾经,我需要一个类似于 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
);