mirror of
https://github.com/jie65535/CodeMatrix.git
synced 2025-06-01 17:29:10 +08:00
重构 所有代码结构,减少暴露属性,并为每个方法添加注释
This commit is contained in:
parent
877a92d727
commit
f50732f708
@ -1,11 +1,4 @@
|
|||||||
using System;
|
using System.Drawing;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Data;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace CodeMatrix
|
namespace CodeMatrix
|
||||||
@ -49,8 +42,6 @@ namespace CodeMatrix
|
|||||||
codeTarget.InputCode(value);
|
codeTarget.InputCode(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Controls.Add(codeMatrix);
|
Controls.Add(codeMatrix);
|
||||||
Controls.Add(codeQueue);
|
Controls.Add(codeQueue);
|
||||||
Controls.AddRange(codeTargets);
|
Controls.AddRange(codeTargets);
|
||||||
@ -59,6 +50,5 @@ namespace CodeMatrix
|
|||||||
size.Width += codeQueue.Width;
|
size.Width += codeQueue.Width;
|
||||||
ClientSize = size;
|
ClientSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,45 +4,88 @@ using System.Windows.Forms;
|
|||||||
|
|
||||||
namespace CodeMatrix
|
namespace CodeMatrix
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 表示代码矩阵控件 游戏中的代码矩阵
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="System.Windows.Forms.Control" />
|
||||||
internal class UCCodeMatrix : Control
|
internal class UCCodeMatrix : Control
|
||||||
{
|
{
|
||||||
public Size CellSize { get; set; }
|
private static readonly Size MaximumMatrixSize = new Size(10, 10);
|
||||||
public int Columns { get; set; }
|
private static readonly Size MinimumMatrixSize = new Size(5, 5);
|
||||||
public int Rows { get; set; }
|
|
||||||
public byte[,] Matrix { get; set; }
|
/// <summary>
|
||||||
public Point SelectPoint { get; private set; }
|
/// The cell size
|
||||||
public Point CursorPoint { get; private set; }
|
/// </summary>
|
||||||
private Point _HoverPoint;
|
private Size _CellSize;
|
||||||
public Point HoverPoint
|
|
||||||
{
|
/// <summary>
|
||||||
get => _HoverPoint;
|
/// The code matrix rect
|
||||||
set
|
/// </summary>
|
||||||
{
|
private RectangleF _CodeMatrixRect;
|
||||||
_HoverPoint = value;
|
|
||||||
if (HoverPoint.X >= 0)
|
/// <summary>
|
||||||
HoverValueChangedEvent?.Invoke(this, Matrix[HoverPoint.X, HoverPoint.Y]);
|
/// The columns
|
||||||
else
|
/// </summary>
|
||||||
HoverValueChangedEvent?.Invoke(this, 0);
|
private int _Columns = 5;
|
||||||
}
|
|
||||||
}
|
/// <summary>
|
||||||
public RectangleF CodeMatrixRect { get; private set; }
|
/// The curr dir
|
||||||
|
/// </summary>
|
||||||
|
private Directions _currDir;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The cursor point
|
||||||
|
/// </summary>
|
||||||
|
private Point _CursorPoint;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The highlight code
|
||||||
|
/// </summary>
|
||||||
private byte _HighlightCode;
|
private byte _HighlightCode;
|
||||||
public byte HighlightCode
|
|
||||||
|
/// <summary>
|
||||||
|
/// The hover point
|
||||||
|
/// </summary>
|
||||||
|
private Point _HoverPoint;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The is loaded
|
||||||
|
/// </summary>
|
||||||
|
private bool _IsLoaded;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The matrix
|
||||||
|
/// </summary>
|
||||||
|
private byte[,] _Matrix;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The rows
|
||||||
|
/// </summary>
|
||||||
|
private int _Rows = 5;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The select point
|
||||||
|
/// </summary>
|
||||||
|
private Point _SelectPoint;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UCCodeMatrix"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public UCCodeMatrix()
|
||||||
{
|
{
|
||||||
get => _HighlightCode;
|
InitComponent();
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_HighlightCode != value)
|
|
||||||
{
|
|
||||||
_HighlightCode = value;
|
|
||||||
Invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler<byte> HoverValueChangedEvent;
|
/// <summary>
|
||||||
|
/// Occurs when [code selected event].
|
||||||
|
/// </summary>
|
||||||
public event EventHandler<byte> CodeSelectedEvent;
|
public event EventHandler<byte> CodeSelectedEvent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when [hover value changed event].
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<byte> HoverValueChangedEvent;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 方向
|
/// 方向
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -59,153 +102,131 @@ namespace CodeMatrix
|
|||||||
Horizontal,
|
Horizontal,
|
||||||
}
|
}
|
||||||
|
|
||||||
private Directions _currDir;
|
/// <summary>
|
||||||
|
/// Gets or sets the columns.
|
||||||
public UCCodeMatrix()
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The columns.
|
||||||
|
/// </value>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">Columns - 设置矩阵大小数值不能小于 {MinimumMatrixSize.Width} 或者大于 {MaximumMatrixSize.Width}</exception>
|
||||||
|
public int Columns
|
||||||
{
|
{
|
||||||
InitData();
|
get => _Columns;
|
||||||
InitComponent();
|
set
|
||||||
|
{
|
||||||
|
if (_Columns != value)
|
||||||
|
{
|
||||||
|
if (value < MinimumMatrixSize.Width || value > MaximumMatrixSize.Width)
|
||||||
|
throw new ArgumentOutOfRangeException("Columns", value, $"设置矩阵大小数值不能小于 {MinimumMatrixSize.Width} 或者大于 {MaximumMatrixSize.Width}");
|
||||||
|
_Columns = value;
|
||||||
|
OnCodeMatrixSizeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitData()
|
/// <summary>
|
||||||
|
/// Gets or sets the highlight code.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The highlight code.
|
||||||
|
/// </value>
|
||||||
|
public byte HighlightCode
|
||||||
|
{
|
||||||
|
get => _HighlightCode;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_HighlightCode != value)
|
||||||
|
{
|
||||||
|
_HighlightCode = value;
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the rows.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The rows.
|
||||||
|
/// </value>
|
||||||
|
public int Rows
|
||||||
|
{
|
||||||
|
get => _Rows;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_Rows != value)
|
||||||
|
{
|
||||||
|
if (value < MinimumMatrixSize.Height || value > MaximumMatrixSize.Height)
|
||||||
|
throw new ArgumentOutOfRangeException("value", value, $"设置矩阵大小数值不能小于 {MinimumMatrixSize.Height} 或者大于 {MaximumMatrixSize.Height}");
|
||||||
|
_Rows = value;
|
||||||
|
OnCodeMatrixSizeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the hover point.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The hover point.
|
||||||
|
/// </value>
|
||||||
|
private Point HoverPoint
|
||||||
|
{
|
||||||
|
get => _HoverPoint;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_HoverPoint = value;
|
||||||
|
if (HoverPoint.X >= 0)
|
||||||
|
HoverValueChangedEvent?.Invoke(this, _Matrix[HoverPoint.X, HoverPoint.Y]);
|
||||||
|
else
|
||||||
|
HoverValueChangedEvent?.Invoke(this, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reloads the code matrix.
|
||||||
|
/// </summary>
|
||||||
|
public void ReloadCodeMatrix()
|
||||||
{
|
{
|
||||||
Rows = 7;
|
|
||||||
Columns = 7;
|
|
||||||
_currDir = Directions.Horizontal;
|
_currDir = Directions.Horizontal;
|
||||||
HoverPoint = new Point(-1, -1);
|
HoverPoint = new Point(-1, -1);
|
||||||
|
GenerateCodeMatrix();
|
||||||
|
CalcCodeMatrixRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitComponent()
|
protected override void OnMouseClick(MouseEventArgs e)
|
||||||
{
|
{
|
||||||
CellSize = Styles.Default.CellSizeA;
|
|
||||||
MinimumSize = new Size(CellSize.Width * Columns + 100, CellSize.Height * Rows + 10);
|
|
||||||
Margin = Padding.Empty;
|
|
||||||
DoubleBuffered = true;
|
|
||||||
|
|
||||||
Font = Styles.Default.CodeFontA;
|
|
||||||
BackColor = Styles.Default.BackColor;
|
|
||||||
ForeColor = Styles.Default.CodeColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _IsLoaded;
|
|
||||||
|
|
||||||
protected override void OnVisibleChanged(EventArgs e)
|
|
||||||
{
|
|
||||||
if (Visible && !_IsLoaded)
|
|
||||||
{
|
|
||||||
Load();
|
|
||||||
_IsLoaded = true;
|
|
||||||
}
|
|
||||||
base.OnVisibleChanged(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Load()
|
|
||||||
{
|
|
||||||
Matrix = new byte[Columns, Rows];
|
|
||||||
for (int col = 0; col < Columns; col++)
|
|
||||||
for (int row = 0; row < Rows; row++)
|
|
||||||
Matrix[col, row] = Common.Codes[Common.Random.Next(Common.Codes.Length)];
|
|
||||||
|
|
||||||
var blockSize = new SizeF(Columns*CellSize.Width, Rows*CellSize.Height);
|
|
||||||
var blockOffset = new PointF((Width-blockSize.Width)/2, (Height-blockSize.Height)/2);
|
|
||||||
CodeMatrixRect = new RectangleF(blockOffset, blockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
//int _paintCount;
|
|
||||||
protected override void OnPaint(PaintEventArgs e)
|
|
||||||
{
|
|
||||||
if (!_IsLoaded) return;
|
|
||||||
//_paintCount++;
|
|
||||||
|
|
||||||
var offset = new PointF(SelectPoint.X*CellSize.Width, SelectPoint.Y*CellSize.Height);
|
|
||||||
if (_currDir == Directions.Horizontal)
|
|
||||||
e.Graphics.FillRectangle(Styles.Default.DefaultLineBrush, 0, offset.Y + CodeMatrixRect.Y, Width, CellSize.Height);
|
|
||||||
else if (_currDir == Directions.Vertical)
|
|
||||||
e.Graphics.FillRectangle(Styles.Default.DefaultLineBrush, offset.X + CodeMatrixRect.X, 0, CellSize.Width, Height);
|
|
||||||
|
|
||||||
if (HoverPoint.X >= 0)
|
if (HoverPoint.X >= 0)
|
||||||
{
|
{
|
||||||
Cursor = Cursors.Hand;
|
_SelectPoint = HoverPoint;
|
||||||
if (_currDir == Directions.Horizontal)
|
_currDir = _currDir == Directions.Horizontal ? Directions.Vertical : Directions.Horizontal;
|
||||||
{
|
CodeSelectedEvent?.Invoke(this, _Matrix[_SelectPoint.X, _SelectPoint.Y]);
|
||||||
offset.X = HoverPoint.X * CellSize.Width;
|
HoverPoint = _CursorPoint = new Point(-1, -1);
|
||||||
e.Graphics.FillRectangle(Styles.Default.SelectLineBrush, offset.X + CodeMatrixRect.X, 0, CellSize.Width, Height);
|
_Matrix[_SelectPoint.X, _SelectPoint.Y] = 0;
|
||||||
|
Invalidate();
|
||||||
}
|
}
|
||||||
else if (_currDir == Directions.Vertical)
|
base.OnMouseClick(e);
|
||||||
{
|
|
||||||
offset.Y = HoverPoint.Y * CellSize.Height;
|
|
||||||
e.Graphics.FillRectangle(Styles.Default.SelectLineBrush, 0, offset.Y + CodeMatrixRect.Y, Width, CellSize.Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
offset.X += CodeMatrixRect.X;
|
|
||||||
offset.Y += CodeMatrixRect.Y;
|
|
||||||
e.Graphics.DrawRectangle(Styles.Default.SelectCellBorderPen, offset.X, offset.Y, CellSize.Width - 1, CellSize.Height - 1);
|
|
||||||
e.Graphics.DrawRectangle(Styles.Default.SelectCellBorderPen, offset.X + 3, offset.Y + 3, CellSize.Width - 6 - 1, CellSize.Height - 6 - 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Cursor = Cursors.Default;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int col = 0; col < Columns; col++)
|
|
||||||
{
|
|
||||||
for (int row = 0; row < Rows; row++)
|
|
||||||
{
|
|
||||||
var cellOffset = new PointF(col*CellSize.Width, row*CellSize.Height);
|
|
||||||
//var cellRect = new RectangleF(cellOffset, CellSize);
|
|
||||||
Brush brush;
|
|
||||||
string code;
|
|
||||||
if (Matrix[col, row] == 0)
|
|
||||||
{
|
|
||||||
code = "[ ]";
|
|
||||||
brush = Styles.Default.EmptyCellBrush;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (HoverPoint.X == col && HoverPoint.Y == row)
|
|
||||||
brush = Styles.Default.SelectBrush;
|
|
||||||
else
|
|
||||||
brush = Styles.Default.CodeBrush;
|
|
||||||
code = Matrix[col, row].ToString("X2");
|
|
||||||
}
|
|
||||||
if (HighlightCode != 0 && HighlightCode == Matrix[col, row])
|
|
||||||
{
|
|
||||||
e.Graphics.DrawRectangle(Styles.Default.SelectedCellBorderPen,
|
|
||||||
CodeMatrixRect.X+cellOffset.X+1,
|
|
||||||
CodeMatrixRect.Y+cellOffset.Y+1,
|
|
||||||
CellSize.Width - 3,
|
|
||||||
CellSize.Height - 3);
|
|
||||||
}
|
|
||||||
var codeSize = e.Graphics.MeasureString(code, Font);
|
|
||||||
var codeOffset = new PointF((CellSize.Width-codeSize.Width)/2, (CellSize.Height-codeSize.Height)/2);
|
|
||||||
var codePoint = new PointF(codeOffset.X+cellOffset.X+CodeMatrixRect.X, codeOffset.Y+cellOffset.Y+CodeMatrixRect.Y);
|
|
||||||
e.Graphics.DrawString(code, Font, brush, codePoint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
e.Graphics.DrawRectangle(Styles.Default.DefaultBorderPen, 0, 0, Width - 1, Height - 1);
|
|
||||||
//e.Graphics.DrawString(_paintCount.ToString(), Font, Styles.Default.CodeBrush, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnMouseMove(MouseEventArgs e)
|
protected override void OnMouseMove(MouseEventArgs e)
|
||||||
{
|
{
|
||||||
if (CodeMatrixRect.Left <= e.X
|
if (_CodeMatrixRect.Left <= e.X
|
||||||
&& CodeMatrixRect.Top <= e.Y
|
&& _CodeMatrixRect.Top <= e.Y
|
||||||
&& CodeMatrixRect.Right > e.X
|
&& _CodeMatrixRect.Right > e.X
|
||||||
&& CodeMatrixRect.Bottom > e.Y)
|
&& _CodeMatrixRect.Bottom > e.Y)
|
||||||
{
|
{
|
||||||
var offset = new PointF(e.X-CodeMatrixRect.X, e.Y-CodeMatrixRect.Y);
|
var offset = new PointF(e.X-_CodeMatrixRect.X, e.Y-_CodeMatrixRect.Y);
|
||||||
var current = new Point((int)(offset.X / CellSize.Width), (int)(offset.Y / CellSize.Height));
|
var current = new Point((int)(offset.X / _CellSize.Width), (int)(offset.Y / _CellSize.Height));
|
||||||
if (CursorPoint != current)
|
if (_CursorPoint != current)
|
||||||
{
|
{
|
||||||
CursorPoint = current;
|
_CursorPoint = current;
|
||||||
Point hoverPoint;
|
Point hoverPoint;
|
||||||
if (_currDir == Directions.Vertical)
|
if (_currDir == Directions.Vertical)
|
||||||
hoverPoint = new Point(SelectPoint.X, CursorPoint.Y);
|
hoverPoint = new Point(_SelectPoint.X, _CursorPoint.Y);
|
||||||
else
|
else
|
||||||
hoverPoint = new Point(CursorPoint.X, SelectPoint.Y);
|
hoverPoint = new Point(_CursorPoint.X, _SelectPoint.Y);
|
||||||
|
|
||||||
if (Matrix[hoverPoint.X, hoverPoint.Y] == 0)
|
if (_Matrix[hoverPoint.X, hoverPoint.Y] == 0)
|
||||||
hoverPoint = new Point(-1, -1);
|
hoverPoint = new Point(-1, -1);
|
||||||
|
|
||||||
if (HoverPoint != hoverPoint)
|
if (HoverPoint != hoverPoint)
|
||||||
@ -219,25 +240,149 @@ namespace CodeMatrix
|
|||||||
{
|
{
|
||||||
if (HoverPoint.X >= 0)
|
if (HoverPoint.X >= 0)
|
||||||
{
|
{
|
||||||
HoverPoint = CursorPoint = new Point(-1, -1);
|
HoverPoint = _CursorPoint = new Point(-1, -1);
|
||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
base.OnMouseMove(e);
|
base.OnMouseMove(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnMouseClick(MouseEventArgs e)
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
{
|
{
|
||||||
|
if (!_IsLoaded) return;
|
||||||
|
|
||||||
|
var offset = new PointF(_SelectPoint.X*_CellSize.Width, _SelectPoint.Y*_CellSize.Height);
|
||||||
|
if (_currDir == Directions.Horizontal)
|
||||||
|
e.Graphics.FillRectangle(Styles.Default.DefaultLineBrush, 0, offset.Y + _CodeMatrixRect.Y, Width, _CellSize.Height);
|
||||||
|
else if (_currDir == Directions.Vertical)
|
||||||
|
e.Graphics.FillRectangle(Styles.Default.DefaultLineBrush, offset.X + _CodeMatrixRect.X, 0, _CellSize.Width, Height);
|
||||||
|
|
||||||
if (HoverPoint.X >= 0)
|
if (HoverPoint.X >= 0)
|
||||||
{
|
{
|
||||||
SelectPoint = HoverPoint;
|
Cursor = Cursors.Hand;
|
||||||
_currDir = _currDir == Directions.Horizontal ? Directions.Vertical : Directions.Horizontal;
|
if (_currDir == Directions.Horizontal)
|
||||||
CodeSelectedEvent?.Invoke(this, Matrix[SelectPoint.X, SelectPoint.Y]);
|
{
|
||||||
HoverPoint = CursorPoint = new Point(-1, -1);
|
offset.X = HoverPoint.X * _CellSize.Width;
|
||||||
Matrix[SelectPoint.X, SelectPoint.Y] = 0;
|
e.Graphics.FillRectangle(Styles.Default.SelectLineBrush, offset.X + _CodeMatrixRect.X, 0, _CellSize.Width, Height);
|
||||||
Invalidate();
|
|
||||||
}
|
}
|
||||||
base.OnMouseClick(e);
|
else if (_currDir == Directions.Vertical)
|
||||||
|
{
|
||||||
|
offset.Y = HoverPoint.Y * _CellSize.Height;
|
||||||
|
e.Graphics.FillRectangle(Styles.Default.SelectLineBrush, 0, offset.Y + _CodeMatrixRect.Y, Width, _CellSize.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
offset.X += _CodeMatrixRect.X;
|
||||||
|
offset.Y += _CodeMatrixRect.Y;
|
||||||
|
e.Graphics.DrawRectangle(Styles.Default.SelectCellBorderPen, offset.X, offset.Y, _CellSize.Width - 1, _CellSize.Height - 1);
|
||||||
|
e.Graphics.DrawRectangle(Styles.Default.SelectCellBorderPen, offset.X + 3, offset.Y + 3, _CellSize.Width - 6 - 1, _CellSize.Height - 6 - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Cursor = Cursors.Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int col = 0; col < Columns; col++)
|
||||||
|
{
|
||||||
|
for (int row = 0; row < Rows; row++)
|
||||||
|
{
|
||||||
|
var cellOffset = new PointF(col*_CellSize.Width, row*_CellSize.Height);
|
||||||
|
//var cellRect = new RectangleF(cellOffset, CellSize);
|
||||||
|
Brush brush;
|
||||||
|
string code;
|
||||||
|
if (_Matrix[col, row] == 0)
|
||||||
|
{
|
||||||
|
code = "[ ]";
|
||||||
|
brush = Styles.Default.EmptyCellBrush;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (HoverPoint.X == col && HoverPoint.Y == row)
|
||||||
|
brush = Styles.Default.SelectBrush;
|
||||||
|
else
|
||||||
|
brush = Styles.Default.CodeBrush;
|
||||||
|
code = _Matrix[col, row].ToString("X2");
|
||||||
|
}
|
||||||
|
if (HighlightCode != 0 && HighlightCode == _Matrix[col, row])
|
||||||
|
{
|
||||||
|
e.Graphics.DrawRectangle(Styles.Default.SelectedCellBorderPen,
|
||||||
|
_CodeMatrixRect.X + cellOffset.X + 1,
|
||||||
|
_CodeMatrixRect.Y + cellOffset.Y + 1,
|
||||||
|
_CellSize.Width - 3,
|
||||||
|
_CellSize.Height - 3);
|
||||||
|
}
|
||||||
|
var codeSize = e.Graphics.MeasureString(code, Font);
|
||||||
|
var codeOffset = new PointF((_CellSize.Width-codeSize.Width)/2, (_CellSize.Height-codeSize.Height)/2);
|
||||||
|
var codePoint = new PointF(codeOffset.X+cellOffset.X+_CodeMatrixRect.X, codeOffset.Y+cellOffset.Y+_CodeMatrixRect.Y);
|
||||||
|
e.Graphics.DrawString(code, Font, brush, codePoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Graphics.DrawRectangle(Styles.Default.DefaultBorderPen, 0, 0, Width - 1, Height - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnVisibleChanged(EventArgs e)
|
||||||
|
{
|
||||||
|
if (Visible && !_IsLoaded)
|
||||||
|
{
|
||||||
|
OnLoad();
|
||||||
|
_IsLoaded = true;
|
||||||
|
}
|
||||||
|
base.OnVisibleChanged(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the code matrix rect.
|
||||||
|
/// </summary>
|
||||||
|
private void CalcCodeMatrixRect()
|
||||||
|
{
|
||||||
|
var blockSize = new SizeF(Columns*_CellSize.Width, Rows*_CellSize.Height);
|
||||||
|
var blockOffset = new PointF((Width-blockSize.Width)/2, (Height-blockSize.Height)/2);
|
||||||
|
_CodeMatrixRect = new RectangleF(blockOffset, blockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates the code matrix.
|
||||||
|
/// </summary>
|
||||||
|
private void GenerateCodeMatrix()
|
||||||
|
{
|
||||||
|
_Matrix = new byte[Columns, Rows];
|
||||||
|
for (int col = 0; col < Columns; col++)
|
||||||
|
for (int row = 0; row < Rows; row++)
|
||||||
|
_Matrix[col, row] = Common.Codes[Common.Random.Next(Common.Codes.Length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the component.
|
||||||
|
/// </summary>
|
||||||
|
private void InitComponent()
|
||||||
|
{
|
||||||
|
_CellSize = Styles.Default.CellSizeA;
|
||||||
|
MinimumSize = new Size(_CellSize.Width * Columns, _CellSize.Height * Rows);
|
||||||
|
Size = MinimumSize + new Size(100, 10);
|
||||||
|
Margin = Padding.Empty;
|
||||||
|
DoubleBuffered = true;
|
||||||
|
|
||||||
|
Font = Styles.Default.CodeFontA;
|
||||||
|
BackColor = Styles.Default.BackColor;
|
||||||
|
ForeColor = Styles.Default.CodeColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when [code matrix size changed].
|
||||||
|
/// </summary>
|
||||||
|
private void OnCodeMatrixSizeChanged()
|
||||||
|
{
|
||||||
|
MinimumSize = new Size(_CellSize.Width * Columns, _CellSize.Height * Rows);
|
||||||
|
if (_IsLoaded)
|
||||||
|
ReloadCodeMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when [load].
|
||||||
|
/// </summary>
|
||||||
|
private void OnLoad()
|
||||||
|
{
|
||||||
|
ReloadCodeMatrix();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,87 +1,157 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace CodeMatrix
|
namespace CodeMatrix
|
||||||
{
|
{
|
||||||
class UCCodeQueue : Control
|
/// <summary>
|
||||||
|
/// 表示代码队列控件 游戏中的输入缓冲区
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="System.Windows.Forms.Control" />
|
||||||
|
internal class UCCodeQueue : Control
|
||||||
{
|
{
|
||||||
public Size CellSize { get; private set; }
|
/// <summary>
|
||||||
public Padding CellMargin { get; set; }
|
/// The maximum buffer size
|
||||||
|
/// </summary>
|
||||||
|
private const int MaximumBufferSize = 10;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The minimum buffer size
|
||||||
|
/// </summary>
|
||||||
|
private const int MinimumBufferSize = 4;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The buffer
|
||||||
|
/// </summary>
|
||||||
|
private byte[] _Buffer = new byte[MaximumBufferSize];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The buffer size
|
||||||
|
/// </summary>
|
||||||
|
private int _BufferSize = 4;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The cell margin
|
||||||
|
/// </summary>
|
||||||
|
private Padding _CellMargin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The cell size
|
||||||
|
/// </summary>
|
||||||
|
private Size _CellSize;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The curr index
|
||||||
|
/// </summary>
|
||||||
|
private int _CurrIndex;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The hover code
|
||||||
|
/// </summary>
|
||||||
private byte _HoverCode;
|
private byte _HoverCode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The is loaded/
|
||||||
|
/// </summary>
|
||||||
|
private bool _IsLoaded;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UCCodeQueue"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public UCCodeQueue()
|
||||||
|
{
|
||||||
|
InitComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the size of the buffer.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The size of the buffer.
|
||||||
|
/// </value>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">BufferSize - 设置缓冲区大小数值不能小于 {MinimumBufferSize} 或者大于 {MaximumBufferSize}</exception>
|
||||||
|
public int BufferSize
|
||||||
|
{
|
||||||
|
get => _BufferSize;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_BufferSize != value)
|
||||||
|
{
|
||||||
|
if (value < MinimumBufferSize || value > MaximumBufferSize)
|
||||||
|
throw new ArgumentOutOfRangeException("BufferSize", value, $"设置缓冲区大小数值不能小于 {MinimumBufferSize} 或者大于 {MaximumBufferSize}");
|
||||||
|
_BufferSize = value;
|
||||||
|
OnBufferSizeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the hover code.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The hover code.
|
||||||
|
/// </value>
|
||||||
public byte HoverCode
|
public byte HoverCode
|
||||||
{
|
{
|
||||||
get => _HoverCode;
|
get => _HoverCode;
|
||||||
set
|
set
|
||||||
|
{
|
||||||
|
if (_HoverCode != value)
|
||||||
{
|
{
|
||||||
_HoverCode = value;
|
_HoverCode = value;
|
||||||
Invalidate();
|
OnHoverCodeChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public int BufferSize { get; set; }
|
|
||||||
public int CurrIndex { get; private set; }
|
|
||||||
public byte[] Buffer { get; } = new byte[32];
|
|
||||||
|
|
||||||
public UCCodeQueue()
|
|
||||||
{
|
|
||||||
InitData();
|
|
||||||
InitComponent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitData()
|
/// <summary>
|
||||||
|
/// Inputs the code.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="code">The code.</param>
|
||||||
|
public void InputCode(byte code)
|
||||||
{
|
{
|
||||||
BufferSize = 9;
|
if (_CurrIndex < BufferSize)
|
||||||
CurrIndex = 0;
|
_Buffer[_CurrIndex++] = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reloads the code queue.
|
||||||
|
/// </summary>
|
||||||
|
public void ReloadCodeQueue()
|
||||||
|
{
|
||||||
|
_CurrIndex = 0;
|
||||||
HoverCode = 0;
|
HoverCode = 0;
|
||||||
}
|
Invalidate();
|
||||||
|
|
||||||
private void InitComponent()
|
|
||||||
{
|
|
||||||
CellSize = Styles.Default.CellSizeB;
|
|
||||||
Margin = Padding.Empty;
|
|
||||||
Padding = new Padding(10);
|
|
||||||
CellMargin = new Padding(3);
|
|
||||||
MinimumSize = new Size((CellSize.Width + CellMargin.Horizontal) * BufferSize + Padding.Horizontal,
|
|
||||||
CellSize.Height + CellMargin.Vertical + Padding.Vertical);
|
|
||||||
DoubleBuffered = true;
|
|
||||||
|
|
||||||
Font = Styles.Default.CodeFontB;
|
|
||||||
BackColor = Styles.Default.BackColor;
|
|
||||||
ForeColor = Styles.Default.CodeColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPaint(PaintEventArgs e)
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
{
|
{
|
||||||
var cellOffset = new Rectangle(Padding.Left + CellMargin.Left,
|
var cellOffset = new Rectangle(Padding.Left + _CellMargin.Left,
|
||||||
Padding.Top + CellMargin.Top,
|
Padding.Top + _CellMargin.Top,
|
||||||
CellSize.Width-1,
|
_CellSize.Width-1,
|
||||||
CellSize.Height-1);
|
_CellSize.Height-1);
|
||||||
var cellOffsetWidth = CellSize.Width + CellMargin.Horizontal;
|
var cellOffsetWidth = _CellSize.Width + _CellMargin.Horizontal;
|
||||||
for (int i = 0; i < CurrIndex && i < BufferSize; i++)
|
for (int i = 0; i < _CurrIndex && i < BufferSize; i++)
|
||||||
{
|
{
|
||||||
e.Graphics.DrawRectangle(Styles.Default.SelectedCellBorderPen, cellOffset);
|
e.Graphics.DrawRectangle(Styles.Default.SelectedCellBorderPen, cellOffset);
|
||||||
var code = Buffer[i].ToString("X2");
|
var code = _Buffer[i].ToString("X2");
|
||||||
var codeSize = e.Graphics.MeasureString(code, Font);
|
var codeSize = e.Graphics.MeasureString(code, Font);
|
||||||
var codeOffset = new PointF((CellSize.Width-codeSize.Width)/2, (CellSize.Height-codeSize.Height)/2);
|
var codeOffset = new PointF((_CellSize.Width-codeSize.Width)/2, (_CellSize.Height-codeSize.Height)/2);
|
||||||
var codePoint = new PointF(codeOffset.X+cellOffset.X, codeOffset.Y+cellOffset.Y);
|
var codePoint = new PointF(codeOffset.X+cellOffset.X, codeOffset.Y+cellOffset.Y);
|
||||||
e.Graphics.DrawString(code, Font, Styles.Default.CodeBrush, codePoint);
|
e.Graphics.DrawString(code, Font, Styles.Default.CodeBrush, codePoint);
|
||||||
cellOffset.X += cellOffsetWidth;
|
cellOffset.X += cellOffsetWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurrIndex < BufferSize)
|
if (_CurrIndex < BufferSize)
|
||||||
{
|
{
|
||||||
int i = CurrIndex;
|
int i = _CurrIndex;
|
||||||
if (HoverCode > 0)
|
if (HoverCode > 0)
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
e.Graphics.DrawRectangle(Styles.Default.SelectCellBorderPen, cellOffset);
|
e.Graphics.DrawRectangle(Styles.Default.SelectCellBorderPen, cellOffset);
|
||||||
var code = HoverCode.ToString("X2");
|
var code = HoverCode.ToString("X2");
|
||||||
var codeSize = e.Graphics.MeasureString(code, Font);
|
var codeSize = e.Graphics.MeasureString(code, Font);
|
||||||
var codeOffset = new PointF((CellSize.Width-codeSize.Width)/2, (CellSize.Height-codeSize.Height)/2);
|
var codeOffset = new PointF((_CellSize.Width-codeSize.Width)/2, (_CellSize.Height-codeSize.Height)/2);
|
||||||
var codePoint = new PointF(codeOffset.X+cellOffset.X, codeOffset.Y+cellOffset.Y);
|
var codePoint = new PointF(codeOffset.X+cellOffset.X, codeOffset.Y+cellOffset.Y);
|
||||||
e.Graphics.DrawString(code, Font, Styles.Default.SelectBrush, codePoint);
|
e.Graphics.DrawString(code, Font, Styles.Default.SelectBrush, codePoint);
|
||||||
cellOffset.X += cellOffsetWidth;
|
cellOffset.X += cellOffsetWidth;
|
||||||
@ -94,22 +164,63 @@ namespace CodeMatrix
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
e.Graphics.DrawRectangle(Styles.Default.DefaultBorderPen, 0, 0, Width - 1, Height - 1);
|
e.Graphics.DrawRectangle(Styles.Default.DefaultBorderPen, 0, 0, Width - 1, Height - 1);
|
||||||
|
|
||||||
base.OnPaint(e);
|
base.OnPaint(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InputCode(byte code)
|
protected override void OnVisibleChanged(EventArgs e)
|
||||||
{
|
{
|
||||||
if (CurrIndex < BufferSize)
|
if (Visible && !_IsLoaded)
|
||||||
Buffer[CurrIndex++] = code;
|
{
|
||||||
|
OnLoad();
|
||||||
|
_IsLoaded = true;
|
||||||
|
}
|
||||||
|
base.OnVisibleChanged(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearBuffer()
|
/// <summary>
|
||||||
|
/// Initializes the component.
|
||||||
|
/// </summary>
|
||||||
|
private void InitComponent()
|
||||||
{
|
{
|
||||||
CurrIndex = 0;
|
_CellSize = Styles.Default.CellSizeB;
|
||||||
HoverCode = 0;
|
Margin = Padding.Empty;
|
||||||
|
Padding = new Padding(10);
|
||||||
|
_CellMargin = new Padding(3);
|
||||||
|
MinimumSize = new Size((_CellSize.Width + _CellMargin.Horizontal) * BufferSize + Padding.Horizontal,
|
||||||
|
_CellSize.Height + _CellMargin.Vertical + Padding.Vertical);
|
||||||
|
DoubleBuffered = true;
|
||||||
|
|
||||||
|
Font = Styles.Default.CodeFontB;
|
||||||
|
BackColor = Styles.Default.BackColor;
|
||||||
|
ForeColor = Styles.Default.CodeColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when [buffer size changed].
|
||||||
|
/// </summary>
|
||||||
|
private void OnBufferSizeChanged()
|
||||||
|
{
|
||||||
|
MinimumSize = new Size((_CellSize.Width + _CellMargin.Horizontal) * BufferSize + Padding.Horizontal,
|
||||||
|
_CellSize.Height + _CellMargin.Vertical + Padding.Vertical);
|
||||||
|
ReloadCodeQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when [hover code changed].
|
||||||
|
/// </summary>
|
||||||
|
private void OnHoverCodeChanged()
|
||||||
|
{
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when [load].
|
||||||
|
/// </summary>
|
||||||
|
private void OnLoad()
|
||||||
|
{
|
||||||
|
ReloadCodeQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,18 +1,179 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace CodeMatrix
|
namespace CodeMatrix
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 表示代码目标序列控件 游戏中的目标序列
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="System.Windows.Forms.Control" />
|
||||||
public class UCCodeTarget : Control
|
public class UCCodeTarget : Control
|
||||||
{
|
{
|
||||||
public Size CellSize { get; private set; }
|
/// <summary>
|
||||||
public Padding CellMargin { get; set; }
|
/// The maximum buffer size
|
||||||
|
/// </summary>
|
||||||
|
private const int MaximumBufferSize = 10;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The minimum buffer size
|
||||||
|
/// </summary>
|
||||||
|
private const int MinimumBufferSize = 4;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The minimum target length
|
||||||
|
/// </summary>
|
||||||
|
private const int MinimumTargetLength = 2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The KMP next Array
|
||||||
|
/// </summary>
|
||||||
|
private readonly int[] _Next = new int[MaximumBufferSize];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The target codes
|
||||||
|
/// </summary>
|
||||||
|
private readonly byte[] _TargetCodes = new byte[MaximumBufferSize];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The buffer size
|
||||||
|
/// </summary>
|
||||||
|
private int _BufferSize = 4;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The cell margin
|
||||||
|
/// </summary>
|
||||||
|
private Padding _CellMargin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The cell size
|
||||||
|
/// </summary>
|
||||||
|
private Size _CellSize;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The curr state
|
||||||
|
/// </summary>
|
||||||
|
private State _CurrState;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The hover code
|
||||||
|
/// </summary>
|
||||||
private byte _HoverCode;
|
private byte _HoverCode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The is loaded
|
||||||
|
/// </summary>
|
||||||
|
private bool _IsLoaded;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The offset index
|
||||||
|
/// </summary>
|
||||||
|
private int _OffsetIndex;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The target length
|
||||||
|
/// </summary>
|
||||||
|
private int _TargetLength = 3;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The hover index
|
||||||
|
/// </summary>
|
||||||
|
private int HoverIndex = -1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UCCodeTarget"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public UCCodeTarget()
|
||||||
|
{
|
||||||
|
InitComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when [code target state changed event].
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler CodeTargetStateChangedEvent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when [hover code event].
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<byte> HoverCodeEvent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 状态枚举
|
||||||
|
/// </summary>
|
||||||
|
public enum State
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 输入中
|
||||||
|
/// </summary>
|
||||||
|
Input,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 已通过/已安装
|
||||||
|
/// </summary>
|
||||||
|
Pass,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 已拒绝
|
||||||
|
/// </summary>
|
||||||
|
Reject,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the size of the buffer.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The size of the buffer.
|
||||||
|
/// </value>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">BufferSize - 设置缓冲区大小数值不能小于 {MinimumBufferSize} 或者大于 {MaximumBufferSize}</exception>
|
||||||
|
public int BufferSize
|
||||||
|
{
|
||||||
|
get => _BufferSize;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_BufferSize != value)
|
||||||
|
{
|
||||||
|
if (value < MinimumBufferSize || value > MaximumBufferSize)
|
||||||
|
throw new ArgumentOutOfRangeException("BufferSize", value, $"设置缓冲区大小数值不能小于 {MinimumBufferSize} 或者大于 {MaximumBufferSize}");
|
||||||
|
_BufferSize = value;
|
||||||
|
OnBufferSizeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取当前正在输入的下标位置
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// 当前正在输入的下标位置
|
||||||
|
/// </value>
|
||||||
|
public int CurrIndex { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取当前序列的输入状态
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// 当前序列的输入状态
|
||||||
|
/// </value>
|
||||||
|
public State CurrState
|
||||||
|
{
|
||||||
|
get => _CurrState;
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
if (_CurrState != value)
|
||||||
|
{
|
||||||
|
_CurrState = value;
|
||||||
|
OnTargetStateChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the hover code.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The hover code.
|
||||||
|
/// </value>
|
||||||
public byte HoverCode
|
public byte HoverCode
|
||||||
{
|
{
|
||||||
get => _HoverCode;
|
get => _HoverCode;
|
||||||
@ -25,173 +186,33 @@ namespace CodeMatrix
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public event EventHandler<byte> HoverCodeEvent;
|
|
||||||
public int BufferSize { get; set; }
|
|
||||||
public int TargetLength { get; set; }
|
|
||||||
public int OffsetIndex { get; private set; }
|
|
||||||
public int CurrIndex { get; private set; }
|
|
||||||
public byte[] TargetCodes { get; } = new byte[32];
|
|
||||||
private int[] _Next = new int[32];
|
|
||||||
|
|
||||||
public enum State
|
/// <summary>
|
||||||
|
/// Gets or sets the length of the target.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The length of the target.
|
||||||
|
/// </value>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">TargetLength - 设置目标序列长度不能小于 {MinimumTargetLength} 或者大于缓冲区大小</exception>
|
||||||
|
public int TargetLength
|
||||||
{
|
{
|
||||||
Input,
|
get => _TargetLength;
|
||||||
Pass,
|
set
|
||||||
Reject,
|
|
||||||
}
|
|
||||||
public State CurrState { get; private set; }
|
|
||||||
|
|
||||||
public UCCodeTarget()
|
|
||||||
{
|
{
|
||||||
InitData();
|
if (_TargetLength != value)
|
||||||
InitComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void InitData()
|
|
||||||
{
|
{
|
||||||
BufferSize = 9;
|
if (value < MinimumBufferSize || value > BufferSize)
|
||||||
TargetLength = Common.Random.Next(3, 6);
|
throw new ArgumentOutOfRangeException("TargetLength", value, $"设置目标序列长度不能小于 {MinimumTargetLength} 或者大于缓冲区大小");
|
||||||
OffsetIndex = 0;
|
_TargetLength = value;
|
||||||
CurrIndex = 0;
|
OnTargetLengthChanged();
|
||||||
HoverCode = 0;
|
|
||||||
CurrState = State.Input;
|
|
||||||
for (int i = 0; i < TargetLength; i++)
|
|
||||||
TargetCodes[i] = Common.Codes[Common.Random.Next(Common.Codes.Length)];
|
|
||||||
_Next[0] = -1;
|
|
||||||
_Next[1] = 0;
|
|
||||||
for (int i = 1, j = 0; i < TargetLength;)
|
|
||||||
{
|
|
||||||
if (j == -1 || TargetCodes[i] == TargetCodes[j])
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
j++;
|
|
||||||
if (TargetCodes[i] != TargetCodes[j])
|
|
||||||
_Next[i] = j;
|
|
||||||
else
|
|
||||||
_Next[i] = _Next[j];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
j = _Next[j];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitComponent()
|
/// <summary>
|
||||||
{
|
/// Inputs the code.
|
||||||
CellSize = Styles.Default.CellSizeB;
|
/// </summary>
|
||||||
Margin = Padding.Empty;
|
/// <param name="code">The code.</param>
|
||||||
Padding = new Padding(10, 5, 10, 5);
|
|
||||||
CellMargin = new Padding(3);
|
|
||||||
MinimumSize = new Size((CellSize.Width + CellMargin.Horizontal) * BufferSize + Padding.Horizontal,
|
|
||||||
CellSize.Height + CellMargin.Vertical + Padding.Vertical);
|
|
||||||
DoubleBuffered = true;
|
|
||||||
|
|
||||||
Font = Styles.Default.CodeFontB;
|
|
||||||
BackColor = Styles.Default.BackColor;
|
|
||||||
ForeColor = Styles.Default.CodeColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnPaint(PaintEventArgs e)
|
|
||||||
{
|
|
||||||
if (CurrState == State.Pass)
|
|
||||||
{
|
|
||||||
e.Graphics.FillRectangle(Styles.Default.PassBrush, ClientRectangle);
|
|
||||||
}
|
|
||||||
else if (CurrState == State.Reject)
|
|
||||||
{
|
|
||||||
e.Graphics.FillRectangle(Styles.Default.RejectBrush, ClientRectangle);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var cellOffset = new Rectangle(Padding.Left + CellMargin.Left,
|
|
||||||
Padding.Top + CellMargin.Top,
|
|
||||||
CellSize.Width-1,
|
|
||||||
CellSize.Height-1);
|
|
||||||
var cellOffsetWidth = CellSize.Width + CellMargin.Horizontal;
|
|
||||||
cellOffset.X += cellOffsetWidth * OffsetIndex;
|
|
||||||
int i = 0;
|
|
||||||
for (; i < CurrIndex && i < TargetLength; i++)
|
|
||||||
{
|
|
||||||
DrawCode(e.Graphics, TargetCodes[i], Font, Styles.Default.CodeBrush, cellOffset, Styles.Default.SelectedCellBorderPen);
|
|
||||||
cellOffset.X += cellOffsetWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
e.Graphics.FillRectangle(Styles.Default.CurrIndexBrush, cellOffset.X, 0, cellOffset.Width, this.Height);
|
|
||||||
|
|
||||||
if (i == CurrIndex && HoverCode == TargetCodes[i])
|
|
||||||
{
|
|
||||||
DrawCode(e.Graphics, TargetCodes[CurrIndex], Font, Styles.Default.SelectBrush, cellOffset, Styles.Default.SelectCellBorderPen);
|
|
||||||
cellOffset.X += cellOffsetWidth;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; i < TargetLength; i++)
|
|
||||||
{
|
|
||||||
DrawCode(e.Graphics, TargetCodes[i], Font, Styles.Default.ToBeSelectBrush, cellOffset);
|
|
||||||
cellOffset.X += cellOffsetWidth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
base.OnPaint(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawCode(Graphics g, byte code, Font font, Brush brush, Rectangle cellRect, Pen borderPen = null)
|
|
||||||
{
|
|
||||||
if (borderPen != null)
|
|
||||||
g.DrawRectangle(borderPen, cellRect);
|
|
||||||
var codeStr = code.ToString("X2");
|
|
||||||
var codeSize = g.MeasureString(codeStr, font);
|
|
||||||
var codeOffset = new PointF((CellSize.Width-codeSize.Width)/2, (CellSize.Height-codeSize.Height)/2);
|
|
||||||
var codePoint = new PointF(codeOffset.X+cellRect.X, codeOffset.Y+cellRect.Y);
|
|
||||||
g.DrawString(codeStr, font, brush, codePoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int HoverIndex = -1;
|
|
||||||
protected override void OnMouseMove(MouseEventArgs e)
|
|
||||||
{
|
|
||||||
if (CurrState == State.Input)
|
|
||||||
{
|
|
||||||
int hoverIndex = -1;
|
|
||||||
//Point currPoint = new Point(e.X - Padding.Left, e.Y - Padding.Top - CellMargin.Top);
|
|
||||||
//if (currPoint.X >= 0 && currPoint.Y >= 0 && currPoint.Y < CellSize.Height)
|
|
||||||
//{
|
|
||||||
// int cellfullwidth = CellSize.Width + CellMargin.Horizontal;
|
|
||||||
// int index = currPoint.X / cellfullwidth - OffsetIndex;
|
|
||||||
// int offset = currPoint.X % cellfullwidth;
|
|
||||||
// if (offset > CellMargin.Left && offset < cellfullwidth - CellMargin.Left)
|
|
||||||
// {
|
|
||||||
// if (index >= 0 && index < TargetLength)
|
|
||||||
// {
|
|
||||||
// hoverIndex = index;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
Point currPoint = new Point(e.X - Padding.Left, e.Y - Padding.Top);
|
|
||||||
if (currPoint.X >= 0 && currPoint.Y >= 0 && currPoint.Y < CellSize.Height)
|
|
||||||
{
|
|
||||||
int cellfullwidth = CellSize.Width + CellMargin.Horizontal;
|
|
||||||
int index = currPoint.X / cellfullwidth - OffsetIndex;
|
|
||||||
if (index >= 0 && index < TargetLength)
|
|
||||||
{
|
|
||||||
hoverIndex = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HoverIndex != hoverIndex)
|
|
||||||
{
|
|
||||||
HoverIndex = hoverIndex;
|
|
||||||
if (HoverIndex >= 0)
|
|
||||||
HoverCodeEvent?.Invoke(this, TargetCodes[HoverIndex]);
|
|
||||||
else
|
|
||||||
HoverCodeEvent?.Invoke(this, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
base.OnMouseMove(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void InputCode(byte code)
|
public void InputCode(byte code)
|
||||||
{
|
{
|
||||||
if (CurrState == State.Input)
|
if (CurrState == State.Input)
|
||||||
@ -203,7 +224,7 @@ namespace CodeMatrix
|
|||||||
CurrIndex = 0;
|
CurrIndex = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (code == TargetCodes[CurrIndex])
|
if (code == _TargetCodes[CurrIndex])
|
||||||
{
|
{
|
||||||
CurrIndex++;
|
CurrIndex++;
|
||||||
break;
|
break;
|
||||||
@ -211,22 +232,213 @@ namespace CodeMatrix
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var next = _Next[CurrIndex];
|
var next = _Next[CurrIndex];
|
||||||
OffsetIndex += CurrIndex - next;
|
_OffsetIndex += CurrIndex - next;
|
||||||
CurrIndex = next;
|
CurrIndex = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OffsetIndex + TargetLength > BufferSize)
|
if (_OffsetIndex + TargetLength > BufferSize)
|
||||||
CurrState = State.Reject;
|
CurrState = State.Reject;
|
||||||
else if (CurrIndex == TargetLength)
|
else if (CurrIndex == TargetLength)
|
||||||
CurrState = State.Pass;
|
CurrState = State.Pass;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearBuffer()
|
/// <summary>
|
||||||
|
/// Reloads the target sequence.
|
||||||
|
/// </summary>
|
||||||
|
public void ReloadTargetSequence()
|
||||||
{
|
{
|
||||||
|
_OffsetIndex = 0;
|
||||||
CurrIndex = 0;
|
CurrIndex = 0;
|
||||||
HoverCode = 0;
|
HoverCode = 0;
|
||||||
|
CurrState = State.Input;
|
||||||
|
GenerateTargetSequence();
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnMouseMove(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
if (CurrState == State.Input)
|
||||||
|
{
|
||||||
|
int hoverIndex = -1;
|
||||||
|
Point currPoint = new Point(e.X - Padding.Left, e.Y - Padding.Top);
|
||||||
|
if (currPoint.X >= 0 && currPoint.Y >= 0 && currPoint.Y < _CellSize.Height)
|
||||||
|
{
|
||||||
|
int cellfullwidth = _CellSize.Width + _CellMargin.Horizontal;
|
||||||
|
int index = currPoint.X / cellfullwidth - _OffsetIndex;
|
||||||
|
if (index >= 0 && index < TargetLength)
|
||||||
|
{
|
||||||
|
hoverIndex = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HoverIndex != hoverIndex)
|
||||||
|
{
|
||||||
|
HoverIndex = hoverIndex;
|
||||||
|
if (HoverIndex >= 0)
|
||||||
|
HoverCodeEvent?.Invoke(this, _TargetCodes[HoverIndex]);
|
||||||
|
else
|
||||||
|
HoverCodeEvent?.Invoke(this, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnMouseMove(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
|
{
|
||||||
|
if (CurrState == State.Pass)
|
||||||
|
{
|
||||||
|
e.Graphics.FillRectangle(Styles.Default.PassBrush, ClientRectangle);
|
||||||
|
e.Graphics.DrawString("已安装", Font, Brushes.Black, 20, 8);
|
||||||
|
}
|
||||||
|
else if (CurrState == State.Reject)
|
||||||
|
{
|
||||||
|
e.Graphics.FillRectangle(Styles.Default.RejectBrush, ClientRectangle);
|
||||||
|
e.Graphics.DrawString("失败", Font, Brushes.Black, 20, 8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var cellOffset = new Rectangle(Padding.Left + _CellMargin.Left,
|
||||||
|
Padding.Top + _CellMargin.Top,
|
||||||
|
_CellSize.Width-1,
|
||||||
|
_CellSize.Height-1);
|
||||||
|
var cellOffsetWidth = _CellSize.Width + _CellMargin.Horizontal;
|
||||||
|
cellOffset.X += cellOffsetWidth * _OffsetIndex;
|
||||||
|
int i = 0;
|
||||||
|
for (; i < CurrIndex && i < TargetLength; i++)
|
||||||
|
{
|
||||||
|
DrawCode(e.Graphics, _TargetCodes[i], Font, Styles.Default.CodeBrush, cellOffset, Styles.Default.SelectedCellBorderPen);
|
||||||
|
cellOffset.X += cellOffsetWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Graphics.FillRectangle(Styles.Default.CurrIndexBrush, cellOffset.X, 0, cellOffset.Width, this.Height);
|
||||||
|
|
||||||
|
if (i == CurrIndex && HoverCode == _TargetCodes[i])
|
||||||
|
{
|
||||||
|
DrawCode(e.Graphics, _TargetCodes[CurrIndex], Font, Styles.Default.SelectBrush, cellOffset, Styles.Default.SelectCellBorderPen);
|
||||||
|
cellOffset.X += cellOffsetWidth;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < TargetLength; i++)
|
||||||
|
{
|
||||||
|
DrawCode(e.Graphics, _TargetCodes[i], Font, Styles.Default.ToBeSelectBrush, cellOffset);
|
||||||
|
cellOffset.X += cellOffsetWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.OnPaint(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnVisibleChanged(EventArgs e)
|
||||||
|
{
|
||||||
|
if (Visible && !_IsLoaded)
|
||||||
|
{
|
||||||
|
OnLoad();
|
||||||
|
_IsLoaded = true;
|
||||||
|
}
|
||||||
|
base.OnVisibleChanged(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws the code.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="g">The graphics.</param>
|
||||||
|
/// <param name="code">The code.</param>
|
||||||
|
/// <param name="font">The font.</param>
|
||||||
|
/// <param name="brush">The brush.</param>
|
||||||
|
/// <param name="cellRect">The cell rect.</param>
|
||||||
|
/// <param name="borderPen">The border pen.</param>
|
||||||
|
private void DrawCode(Graphics g, byte code, Font font, Brush brush, Rectangle cellRect, Pen borderPen = null)
|
||||||
|
{
|
||||||
|
if (borderPen != null)
|
||||||
|
g.DrawRectangle(borderPen, cellRect);
|
||||||
|
var codeStr = code.ToString("X2");
|
||||||
|
var codeSize = g.MeasureString(codeStr, font);
|
||||||
|
var codeOffset = new PointF((_CellSize.Width-codeSize.Width)/2, (_CellSize.Height-codeSize.Height)/2);
|
||||||
|
var codePoint = new PointF(codeOffset.X+cellRect.X, codeOffset.Y+cellRect.Y);
|
||||||
|
g.DrawString(codeStr, font, brush, codePoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates the target sequence.
|
||||||
|
/// </summary>
|
||||||
|
private void GenerateTargetSequence()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < TargetLength; i++)
|
||||||
|
_TargetCodes[i] = Common.Codes[Common.Random.Next(Common.Codes.Length)];
|
||||||
|
_Next[0] = -1;
|
||||||
|
_Next[1] = 0;
|
||||||
|
for (int i = 1, j = 0; i < TargetLength;)
|
||||||
|
{
|
||||||
|
if (j == -1 || _TargetCodes[i] == _TargetCodes[j])
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
j++;
|
||||||
|
if (_TargetCodes[i] != _TargetCodes[j])
|
||||||
|
_Next[i] = j;
|
||||||
|
else
|
||||||
|
_Next[i] = _Next[j];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
j = _Next[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the component.
|
||||||
|
/// </summary>
|
||||||
|
private void InitComponent()
|
||||||
|
{
|
||||||
|
_CellSize = Styles.Default.CellSizeB;
|
||||||
|
Margin = Padding.Empty;
|
||||||
|
Padding = new Padding(10, 5, 10, 5);
|
||||||
|
_CellMargin = new Padding(3);
|
||||||
|
MinimumSize = new Size((_CellSize.Width + _CellMargin.Horizontal) * BufferSize + Padding.Horizontal,
|
||||||
|
_CellSize.Height + _CellMargin.Vertical + Padding.Vertical);
|
||||||
|
DoubleBuffered = true;
|
||||||
|
|
||||||
|
Font = Styles.Default.CodeFontB;
|
||||||
|
BackColor = Styles.Default.BackColor;
|
||||||
|
ForeColor = Styles.Default.CodeColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when [buffer size changed].
|
||||||
|
/// </summary>
|
||||||
|
private void OnBufferSizeChanged()
|
||||||
|
{
|
||||||
|
if (TargetLength > BufferSize)
|
||||||
|
TargetLength = BufferSize;
|
||||||
|
else
|
||||||
|
ReloadTargetSequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when [load].
|
||||||
|
/// </summary>
|
||||||
|
private void OnLoad()
|
||||||
|
{
|
||||||
|
ReloadTargetSequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when [target length changed].
|
||||||
|
/// </summary>
|
||||||
|
private void OnTargetLengthChanged()
|
||||||
|
{
|
||||||
|
ReloadTargetSequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when [target state changed].
|
||||||
|
/// </summary>
|
||||||
|
private void OnTargetStateChanged()
|
||||||
|
{
|
||||||
|
CodeTargetStateChangedEvent?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user