16x16 点阵






4.50/5 (5投票s)
构建 16x16 点阵和 Matrix UserControl

引言
实际上,我只是想练习一下编写用户控件。我开始在onPaint
方法中使用矩形、画笔和画笔进行练习,直到我想到创建自己的点阵控件。点阵用于以点阵样式显示文本和符号,就像LC显示器一样。作为这个矩阵的衍生产品,我得到一个编辑器来构建矩阵的字符集。
开始吧
点阵由16行组成,每行包含16个点。更准确地说,是16x16个矩形。每个矩形可以完全填充,也可以只填充圆形。由于我至少需要每个点(矩形)的一些属性,所以我从自己的rectangle
类开始。让我们称之为RectangleXT
。
Using the Code
class RectangleXT
{
public RectangleXT()
{
}
private Rectangle _rect;
public Rectangle Rect
{
get { return _rect; }
set { _rect = value; }
}
private int _id;
public int Id
{
get { return _id; }
set { _id = value; }
}
private bool _enabled;
public bool Enabled
{
get { return _enabled; }
set { _enabled = value; }
}
private int _row;
public int Row
{
get { return _row; }
set { _row = value; }
}
private int _col;
public int Column
{
get { return _col; }
set { _col = value; }
}
private int _binVal;
public int BinaryValue
{
get { return _binVal; }
set { _binVal = value; }
}
private Color _color;
public Color Color
{
get { return _color; }
set { _color = value; }
}
}
完成此操作后,我就可以开始构建矩阵了。我的Matrix16x16:Control的构造函数首先构建一个RectangleXT[]
数组。
int row = 0;
int column = 0;
for (int i = 0; i < 256; i++)
{
dotRects[i] = new RectangleXT();
dotRects[i].Id = i;
if (i % 16 == 0 && i != 0)
{
column = 0;
row++;
}
dotRects[i].Column = column++;
dotRects[i].Row = row;
dotRects[i].BinaryValue = 15 - dotRects[i].Column;
dotRects[i].Rect = new Rectangle(_dotRectWidth * dotRects[i].Column,
_dotRectHeight * dotRects[i].Row, _dotRectWidth, _dotRectHeight);
}
现在我们准备开始绘制了……
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics gr = e.Graphics;
Rectangle rect = ClientRectangle;
Brush brushEnabeld = new SolidBrush(ColorEnabled);
Brush brushDisabled = new SolidBrush(ColorDisabled);
int rw = rect.Width;
int refw = _dotRectWidth * 16;
for (int i = 0; i < 256; i++)
{
Rectangle rtmp = dotRects[i].Rect;
if (this.ShowBorders)
{
rtmp.Inflate(-1, -1);
}
if (dotRects[i].Enabled)
{
dotRects[i].Color = ColorEnabled;
switch (DisplayStyle)
{
case Style.Dots:
gr.FillEllipse(brushEnabeld, rtmp);
break;
case Style.Rectagles:
gr.FillRectangle(brushEnabeld, rtmp);
break;
default:
break;
}
}
else
{
dotRects[i].Color = ColorDisabled;
switch (DisplayStyle)
{
case Style.Dots:
gr.FillEllipse(brushDisabled, rtmp);
break;
case Style.Rectagles:
gr.FillRectangle(brushDisabled, rtmp);
break;
default:
break;
}
}
if (_teachMode && _showNumbers)
{
gr.DrawString((dotRects[i].Column + 1).ToString(),
this.Font, new SolidBrush(Color.Black),
dotRects[i].Rect.X + 5, dotRects[i].Rect.Y + 5);
}
}
onMatrixChanged();
}
嗯,onPaint
方法中完成的事情相当多。我们必须处理矩形的一些属性。
Enabled
- 根据此属性,点将以'ColorEnabled
'或'ColorDisabled
'颜色绘制,这两者都是Matrix16x16的属性。DisplayStyle
- 决定使用点还是矩形来绘制矩阵。ShowBorders
- 每个矩形周围是否有边框TeachMode
&&ShowNumbers
- 这些将在我们构建要与矩阵一起显示的字符集时进行解释。最后,onMatrixChanged()
将通知任何想要知道矩阵发生了一些更改的人。既然我们有了矩阵,显示一些内容会很好。(实际上,这是我们构建它的原因)为了获得每个点的地址,它有一个二进制值。从值为15的最左边的点开始,我们向下计数到最右边的点为零。有了这个,我们就能计算出行的值。让我们先做一些二进制数学运算。
最左边的点表示值为2^15 = 32768,最右边的点表示值为2^0 = 1。因此,如果我们想要显示第一点和最后一点都启用(点亮)的行,则行值为2^15 + 2^0 = 32769。使用一个包含16个整数值的数组,我们现在可以定义矩阵的所有16行。这是通过以下方式完成的
public void setMatrix(int[] dots)
{
for (int i = 0; i < 256; i++) // all Dots
{
for (int j = 0; j < 16; j++) // 16 Rows
{
if (dotRects[i].Row == j)
{
if (dotRects[i].BinaryValue < 8) // LowByte
{
byte value = (byte)(Math.Pow(2, dotRects[i].BinaryValue));
byte mask = (byte)dots[j];
byte check = (byte)(value & mask);
dotRects[i].Enabled = (check == value);
}
else // HighByte
{
int value = (int)(Math.Pow(2, dotRects[i].BinaryValue)) >> 8;
int mask = dots[j] >> 8;
byte check = (byte)(value & mask);
dotRects[i].Enabled = (check == value);
}
}
}
}
this.Invalidate();
onMatrixChanged();
}
要显示字母“A
”,我们可以简单地调用setMatrix({ 0, 2016, 4080, 6168, 6168, 6168, 6168, 6168, 8184, 8184, 6168, 6168, 6168, 6168, 6168, 0 })
相当容易,不是吗?但是更多字母呢?好的,拿一张纸和一支笔,开始计算字母“B
”。你说工作量太大?你说对了。
我也不会这样做。这就是我实现“TeachMode
”的原因。在演示应用程序中,您可以使用复选框启用TeachMode
。在TeachMode
中,您可以单击矩阵中的点以启用或禁用它们。按住鼠标左键,您可以轻松地绘制一条线。使用鼠标右键,您可以禁用一行中的多个点。矩阵下方的TextBox
将显示您的绘图的int[16]
。这就是我设置要显示的char
集的方式。
class Chars
{
private Dictionary<string,> stdChars = new Dictionary<string,>();
public Chars()
{
buildStdCharset();
}
private void buildStdCharset()
{
stdChars.Add(" ", new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0 });
stdChars.Add("A", new int[] { 0, 2016, 4080, 6168, 6168,
6168, 6168, 6168, 8184, 8184, 6168, 6168, 6168,
6168, 6168, 0 });
stdChars.Add("B", new int[] { 0, 8160, 8176, 6168, 6168,
6168, 6168, 8184, 8184, 6168, 6168, 6168, 6168,
8176, 8160, 0 });
stdChars.Add("C", new int[] { 0, 1984, 4064, 6160, 6144,
6144, 6144, 6144, 6144, 6144, 6144, 6144, 6160,
4064, 1984, 0 });
stdChars.Add("D", new int[] { 0, 8160, 8176, 6168, 6168,
6168, 6168, 6168, 6168, 6168, 6168, 6168, 6168,
8176, 8160, 0 });
stdChars.Add("E", new int[] { 0, 8184, 8184, 6144, 6144,
6144, 6144, 8160, 8160, 6144, 6144, 6144, 6144,
8184, 8184, 0 });
stdChars.Add("F", new int[] { 0, 8184, 8184, 6144, 6144,
6144, 6144, 8160, 8160, 6144, 6144, 6144, 6144,
6144, 6144, 0 });
[...]
}
public Dictionary<string,int[]> Standard
{
get { return stdChars; }
}
使用setChar()
方法,可以显示这些char
中的每一个。
public void setChar(char character)
{
try
{
setMatrix(_characters.Standard[character.ToString()]);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
我的下一步就是将其中一些矩阵放入UserControl
中。