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

16x16 点阵

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (5投票s)

2011 年 3 月 28 日

CPOL

3分钟阅读

viewsIcon

55048

downloadIcon

4221

构建 16x16 点阵和 Matrix UserControl

16x16demo.png

引言

实际上,我只是想练习一下编写用户控件。我开始在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中。

© . All rights reserved.