Introduction
Once, it was required for me, a control similar to LCD, for data presentation. Having looked in the Internet, I found a nice realization from Nic Wilson. But the code was written in C++, and my project was in C#. Therefore, I decided to rewrite Nic's code, and at the same time I wanted to estimate how quick GDI+ works in .NET.
Using the code
In your project, you need to refer to the library with our control, then you should place the control in design time in your project.
After you finish with design time, start initializing our control in the constructor.
public Form1()
{
InitializeComponent();
BkColor = Color.FromArgb(R,G,B);
OnColor = Color.FromArgb(R,G,B);
OffColor = Color.FromArgb(R,G,B);
this.matrixControl1.ScreenText = " Info Text ";
matrixControl1.SetAutoPadding(true,' ');
}
The main "magic" occurs in a method OnPaint
.
protected override void OnPaint(PaintEventArgs pea)
{
Rectangle m_rect = this.DisplayRectangle;
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;
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;
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);
_buff.FillRectangle(hbBkBrush,m_rect);
Rectangle clipDstn = Rectangle.Empty;
Rectangle clipSrc = Rectangle.Empty;
for (int ix = 0; ix < strlen; ix++)
{
GetCharBmpOffset((char)m_StrText[ix], ref clipSrc);
clipDstn = new Rectangle(x,y,clipSrc.Width,clipSrc.Height);
_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++;
}
}
pea.Graphics.DrawImage(_buffImage,0,0);
hbBkBrush.Dispose();
hbBkBrush= null;
bmpAttr.Dispose();
bmpAttr = null;
_buff.Dispose();_buff = null;
_buffImage.Dispose(); _buffImage = null;
}
Conclusion and current issues
The control works perfect, without flickering, but, if you will use the control without scrolling. If you will need scrolling, your application will consume 100% CPU!!!.
Probably, the following line causes the strong consumption of CPU time:
...
_buff.DrawImage(m_ImageMatrix, clipDstn, clipSrc.X,
clipSrc.Y, clipSrc.Width, clipSrc.Height,
GraphicsUnit.Pixel, bmpAttr);
...
It's really so... if you comment out this line, you will get 0% CPU usage.
Conclusion
For heavy operations, it is better to use native methods of API. You may try replacing this line with another one, and try using the API method:
[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
private static extern bool BitBlt(
IntPtr hdcDest,
int nXDest,
int nYDest,
int nWidth,
int nHeight,
IntPtr hdcSrc,
int nXSrc,
int nYSrc,
System.Int32 dwRop
);