Files
ModbusTool/CommonControls/DataTab.cs
T
Thomas Blenkers 480412ec27 Fixes issue #17
2020-06-15 16:02:31 +02:00

461 lines
17 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Modbus.Common
{
public partial class DataTab : UserControl
{
protected int _displayCtrlCount;
public DataTab()
{
InitializeComponent();
}
#region properties
public ushort StartAddress
{
get
{
ushort rVal = 0;
try
{
if (txtStartAdress.Text.IndexOf("0x", 0, txtStartAdress.Text.Length) == 0)
{
string str = txtStartAdress.Text.Replace("0x", "");
rVal = Convert.ToUInt16(str, 16);
}
// bugfix "not accepting hex register address"
else
rVal = Convert.ToUInt16(txtStartAdress.Text);
}
catch (Exception)
{
txtStartAdress.Text = "0";
}
return rVal;
}
set
{
txtStartAdress.Text = Convert.ToString(value);
}
}
public ushort DataLength
{
get
{
ushort rVal = 64;
try
{
if (txtSize.Text.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
{
string str = txtSize.Text.Replace("0x", "");
rVal = Convert.ToUInt16(str, 16);
}
else
rVal = Convert.ToUInt16(txtSize.Text);
}
catch (Exception)
{
txtSize.Text = "64";
}
return rVal;
}
set
{
if (txtSize.Text.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
{
// obey hex input
txtSize.Text = "0x"+Convert.ToString(value, 16);
}
else
txtSize.Text = Convert.ToString(value);
}
}
private void txtSize_TextChanged(object sender, EventArgs e)
{
if (DataLength > 127)
{
DataLength = 127;
}
}
public bool ShowDataLength
{
get
{
return txtSize.Visible;
}
set
{
txtSize.Visible = value;
labelTxtSize.Visible = value;
}
}
public event EventHandler OnApply;
public ushort[] RegisterData { get; set; }
public DisplayFormat DisplayFormat { get; set; }
#endregion
#region Data Table
public void RefreshData()
{
// Create as many textboxes as fit into window
groupBoxData.Visible = false;
groupBoxData.Controls.Clear();
var idxControl = 0;
var screenX = 10;
var screenY = 20;
while (screenX < groupBoxData.Size.Width - 100)
{
var labData = new Label();
groupBoxData.Controls.Add(labData);
labData.Size = new Size(40, 20);
labData.Location = new Point(screenX, screenY);
labData.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 0);
switch (DisplayFormat)
{
case DisplayFormat.LED:
var bulb = new LedBulb();
groupBoxData.Controls.Add(bulb);
bulb.Size = new Size(25, 25);
bulb.Location = new Point(screenX + 40, screenY - 5);
bulb.Padding = new Padding(3);
bulb.Color = Color.Red;
bulb.On = false;
bulb.Tag = idxControl;
bulb.Click += BulbClick;
screenY = screenY + bulb.Size.Height + 10;
labData.Text = Convert.ToString(idxControl);
break;
case DisplayFormat.Binary:
var txtDataB = new TextBox();
groupBoxData.Controls.Add(txtDataB);
txtDataB.Size = new Size(110, 20);
txtDataB.Location = new Point(screenX + 40, screenY - 2);
txtDataB.TextAlign = HorizontalAlignment.Right;
txtDataB.Tag = idxControl;
txtDataB.Leave += TxtDataBinaryLeave;
txtDataB.Enter += txtData_Enter;
txtDataB.KeyPress += txtDataBinaryKeyPress;
txtDataB.MaxLength = 16;
screenY = screenY + txtDataB.Size.Height + 5;
labData.Text = Convert.ToString(StartAddress + idxControl);
break;
case DisplayFormat.Hex:
var txtDataH = new TextBox();
groupBoxData.Controls.Add(txtDataH);
txtDataH.Size = new Size(55, 20);
txtDataH.Location = new Point(screenX + 40, screenY - 2);
txtDataH.TextAlign = HorizontalAlignment.Right;
txtDataH.Tag = idxControl;
txtDataH.MaxLength = 5;
txtDataH.Leave += TxtDataHexLeave;
txtDataH.Enter += txtData_Enter;
txtDataH.KeyPress += txtDataHexKeyPress;
screenY = screenY + txtDataH.Size.Height + 5;
labData.Text = Convert.ToString(StartAddress + idxControl);
break;
case DisplayFormat.Integer:
var txtData = new TextBox();
groupBoxData.Controls.Add(txtData);
txtData.Size = new Size(55, 20);
txtData.Location = new Point(screenX + 40, screenY - 2);
txtData.TextAlign = HorizontalAlignment.Right;
txtData.Tag = idxControl;
txtData.MaxLength = 5;
txtData.Leave += TxtDataLeave;
txtData.Enter += txtData_Enter;
txtData.KeyPress += txtDataIntegerKeyPress;
screenY = screenY + txtData.Size.Height + 5;
labData.Text = Convert.ToString(StartAddress + idxControl);
break;
case DisplayFormat.FloatReverse:
// Float values require two registers, thus skip every second control
// hide even controls
labData.Text = Convert.ToString(StartAddress + idxControl);
if ((idxControl & 1) == 0)
{
var txtFloatReverse = new TextBox();
groupBoxData.Controls.Add(txtFloatReverse);
txtFloatReverse.Size = new Size(55, 40);
txtFloatReverse.Location = new Point(screenX + 40, screenY - 2);
txtFloatReverse.TextAlign = HorizontalAlignment.Right;
txtFloatReverse.Tag = idxControl;
txtFloatReverse.MaxLength = 5;
txtFloatReverse.Leave += TxtFloatReverseLeave;
txtFloatReverse.Enter += TxtFloatReverse_Enter;
txtFloatReverse.KeyPress += txtDataFloatReverseKeyPress;
screenY = screenY + txtFloatReverse.Size.Height *2 + 10; // Float Values Require Two Registers
labData.Visible = true;
}
else
{
labData.Visible = false;
}
break;
}
idxControl++;
if (screenY > groupBoxData.Size.Height - 30)
{
var inc = DisplayFormat == DisplayFormat.Binary ? 200 : 100;
screenX = screenX + inc;
screenY = 20;
}
}
_displayCtrlCount = idxControl;
UpdateDataTable();
groupBoxData.Visible = true;
}
void txtDataBinaryKeyPress(object sender, KeyPressEventArgs e)
{
const char Delete = (char)8;
// this will only allow valid binary values [0-1] [delete] to be entered.
char c = e.KeyChar;
if (c != '\b' && c != 0x30 && c != 0x31 && c != Delete)
{
e.Handled = true;
}
}
void txtDataHexKeyPress(object sender, KeyPressEventArgs e)
{
const char Delete = (char)8;
// this will only allow valid hex values [0-9][a-f][A-F] [delete] to be entered.
char c = e.KeyChar;
if (c != '\b' && !((c <= 0x66 && c >= 61) || (c <= 0x46 && c >= 0x41) || (c >= 0x30 && c <= 0x39)) && c != Delete)
{
e.Handled = true;
}
}
void txtDataIntegerKeyPress(object sender, KeyPressEventArgs e)
{
const char Delete = (char)8;
e.Handled = !Char.IsDigit(e.KeyChar) && e.KeyChar != Delete;
}
void txtDataFloatReverseKeyPress(object sender, KeyPressEventArgs e)
{
const char Delete = (char)8;
e.Handled = !Char.IsDigit(e.KeyChar) && e.KeyChar != Delete && e.KeyChar != NumberFormatInfo.CurrentInfo.NumberDecimalSeparator[0];
}
void txtData_Enter(object sender, EventArgs e)
{
var textBox = (TextBox)sender;
if (!String.IsNullOrEmpty(textBox.Text))
{
textBox.Clear();
}
}
void TxtFloatReverse_Enter(object sender, EventArgs e)
{
var textBox = (TextBox)sender;
if (!String.IsNullOrEmpty(textBox.Text))
{
textBox.Clear();
}
}
void TxtDataLeave(object sender, EventArgs e)
{
var textBox = (TextBox)sender;
var textBoxNumber = Int32.Parse(textBox.Tag.ToString());
UInt16 res;
if (UInt16.TryParse(textBox.Text, out res))
{
RegisterData[StartAddress + textBoxNumber] = res;
}
else
{
textBox.Text = "0";
}
}
void TxtFloatReverseLeave(object sender, EventArgs e)
{
var textBox = (TextBox)sender;
var textBoxNumber = Int32.Parse(textBox.Tag.ToString());
float res;
if (float.TryParse(textBox.Text, out res))
{
var intRes = BitConverter.ToUInt32(BitConverter.GetBytes(res), 0);
var firstPart = (ushort) (intRes >> 16);
var secondPart = (ushort)(intRes & 0xFFFF);
RegisterData[StartAddress + textBoxNumber] = firstPart;
RegisterData[StartAddress + 1 + textBoxNumber] = secondPart;
}
else
{
textBox.Text = "0.0";
}
}
void TxtDataHexLeave(object sender, EventArgs e)
{
var textBox = (TextBox)sender;
var textBoxNumber = Int32.Parse(textBox.Tag.ToString());
ushort res;
if (UInt16.TryParse(textBox.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out res))
{
RegisterData[StartAddress + textBoxNumber] = res;
}
else
{
textBox.Text = "0x0000";
}
textBox.Text = string.Format("0x{0}", textBox.Text.ToLower().PadLeft(4, '0'));
}
void TxtDataBinaryLeave(object sender, EventArgs e)
{
var textBox = (TextBox)sender;
var textBoxNumber = Int32.Parse(textBox.Tag.ToString());
try
{
RegisterData[StartAddress + textBoxNumber] = Convert.ToUInt16(textBox.Text, 2);
textBox.Text = textBox.Text.PadLeft(16, '0');
}
catch (Exception)
{
textBox.Text = "0000000000000000";
}
}
private void BulbClick(object sender, EventArgs e)
{
var bulb = (LedBulb)sender;
bulb.On = !bulb.On;
var bulbNumber = Int32.Parse(bulb.Tag.ToString());
var index = bulbNumber / 16;
var bulbHiByte = (bulbNumber & 0x0008) != 0;
ushort shifter = bulbHiByte ? (ushort)0x0001 : (ushort)0x0100;
var shift = bulbNumber & 0x0007;
var mask = Convert.ToUInt16(shifter << shift);
if (bulb.On)
{
RegisterData[StartAddress + index] |= mask;
}
else
{
mask = (ushort)~mask; ;
RegisterData[StartAddress + index] &= mask;
}
}
public void UpdateDataTable()
{
// for float values we need two registers for one value
// add one extra data value for the last control
var data = new uint[_displayCtrlCount+1];
for (int i = 0; i < _displayCtrlCount+1; i++)
{
var index = StartAddress + i;
if (index >= RegisterData.Length)
{
break;
}
data[i] = RegisterData[index];
}
// ------------------------------------------------------------------------
// Put new data into text boxes
foreach (Control ctrl in groupBoxData.Controls)
{
if (ctrl is TextBox)
{
int x = Convert.ToInt16(ctrl.Tag);
if (x <= data.GetUpperBound(0))
{
switch (DisplayFormat)
{
case DisplayFormat.Binary:
ctrl.Text = Convert.ToString(data[x], 2).PadLeft(16, '0');
break;
case DisplayFormat.Hex:
ctrl.Text = String.Format("0x{0:x4}", data[x]);
break;
case DisplayFormat.Integer:
ctrl.Text = data[x].ToString(CultureInfo.InvariantCulture);
break;
case DisplayFormat.FloatReverse:
uint twoWords = ((uint)data[x] << 16) + data[x + 1];
float r = BitConverter.ToSingle(BitConverter.GetBytes(twoWords), 0);
ctrl.Text = String.Format("{0:0.000}", r);
break;
}
ctrl.Visible = true;
}
else ctrl.Text = "";
}
else if (ctrl is LedBulb)
{
var led = (LedBulb)ctrl;
var bulbNumber = Convert.ToInt16(ctrl.Tag);
var index = bulbNumber / 16;
var bulbHiByte = (bulbNumber & 0x0008) != 0;
var shift = bulbNumber & 0x0007;
ushort shifter = bulbHiByte ? (ushort)0x0001 : (ushort)0x0100;
var mask = Convert.ToUInt16(shifter << shift);
led.On = (mask & data[index]) != 0;
}
}
}
private void buttonApply_Click(object sender, EventArgs e)
{
if (txtStartAdress.Text != "")
{
try
{
var address = StartAddress;
if (OnApply != null) OnApply(this, new EventArgs());
RefreshData();
}
catch (Exception)
{
txtStartAdress.Text = "";
}
}
}
private void buttonClear_Click(object sender, EventArgs e)
{
if (RegisterData != null)
{
var count = DataLength;
for (int i = StartAddress; i < RegisterData.Length && count-- != 0; i++)
{
RegisterData[i] = 0;
}
RefreshData();
}
}
#endregion
}
}