I'm designing an interface using C# windows Forms and I want to send and receive 1024 bits using serial port, the number I'm sending is in the hex-form, so what I did was the next:
private void button2_Click(object sender, EventArgs e)
{
int i;
int a = 0;
byte[] mychar;
mychar = new byte[128];
string M = textBox1.Text;
for (i = 0; i < 127; i++ )
{
mychar[i] = Convert.ToByte((M.Substring(a,2)),16);
a += 2;
}
serialPort1.Write(mychar,0,127);
}
and to check if the data is correct or not, I shorted out both the transmitter and receiver so I can see what I send from textbox1 to be shown in textbox5, the problem is the textbox is shown the output as ASCII, and I couldn't tell how to convert it to Hex form ,(see my attempt as commented bellow):
private void displaytext(object s, EventArgs e)
{
textBox5.Clear();
textBox5.AppendText(RXstring);
//int value = Convert.ToInt32(RXstring, 16);
//string stringValue = Char.ConvertFromUtf32(value);
//textBox4.AppendText(stringValue);
}
so to summarize my problems:
1- Is the code to send data is correct?
2- How can I force the textbox to show the output as Hex?
thank you very much.
UPDATE this is my full code, maybe then you understand my problem :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
string RXstring = "";
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
try
{
RXstring = serialPort1.ReadExisting();
this.Invoke(new EventHandler(displaytext));
}
catch (System.TimeoutException)
{
}
}
private void displaytext(object s, EventArgs e)
{
textBox5.Clear();
textBox5.AppendText(RXstring);
//int value = Convert.ToInt32(RXstring, 16);
//string stringValue = Char.ConvertFromUtf32(value);
//textBox4.AppendText(stringValue);
}
private void pictureBox2_Click(object sender, EventArgs e)
{
serialPort1.Close();
Form1 myForm = new Form1();
this.Close();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
if (!serialPort1.IsOpen)
{
serialPort1.Open();
button1.Enabled = false;
}
else
{
MessageBox.Show("Port is Open by other party!");
}
}
catch (UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message);
}
}
private void Form3_FormClosed(object sender, FormClosedEventArgs e)
{
serialPort1.Close();
}
private void button3_Click(object sender, EventArgs e)
{
textBox1.Text = "0";
textBox2.Text = "0";
textBox3.Text = "0";
textBox4.Text = "0";
textBox5.Text = "";
}
private void button2_Click(object sender, EventArgs e)
{
int i;
int a=0;
byte[] mychar;
mychar = new byte[128];
string M = textBox1.Text;
for (i = 0; i < 127; i++ ) {
mychar[i] = Convert.ToByte((M.Substring(a,2)),16);
a += 2;
}
serialPort1.Write(mychar,0,127);
}
}
}
when I send data from textbox1 I want to be shown exactly as I send it in textbox5, can you help me in that ?
https://drive.google.com/file/d/0B5PXKMhwKWQRREtuMXBaZDA1LUU/view?usp=sharing
This MCVE shows how to convert between bytes and hexadecimal strings:
class Program {
static void Main(string[] args) {
byte[] bytes = FromHexString("0123456789ABCEF");
string text = ToHexString(bytes);
Console.Write(text);
Console.ReadKey(true);
}
static byte[] FromHexString(string hexString) {
byte[] result;
//determine length and handle case of uneven digit count
int length = hexString.Length / 2;
bool even = length * 2 == hexString.Length;
if(!even) {
length++;
}
//allocate memory
result = new byte[length];
int offset;
if(even) {
offset = 0;
} else {
//convert first digit, if digit count is uneven
result[0] = Convert.ToByte(hexString[0].ToString(), 16);
offset = 1;
}
for(int i = offset; i < result.Length; i++) {
//convert digit to byte
result[i] = Convert.ToByte((hexString.Substring(i * 2 - offset, 2)), 16);
}
return result;
}
static string ToHexString(byte[] bytes, bool upperCase = true) {
string format = upperCase ? "X" : "x";
//initialize result with double capacity as a byte in hex notation occupies 2 chars
StringBuilder result = new StringBuilder(bytes.Length * 2);
foreach(var #byte in bytes) {
result.Append(#byte.ToString(format));
}
return result.ToString();
}
}
I just added the following to the code :
string hex = "";
foreach (char c in RXstring)
{
int tmp = c;
hex += String.Format("{0:X2}", (uint)System.Convert.ToUInt32(tmp.ToString()));
}
textBox5.AppendText(hex);
thank you any way :)
Related
i am receiving bytes from the serial port on my c# , and i am storing them in a byte array and then making them as string so now i need to convert the bytes to ASCII how i can do that? This is my code
void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
string bytestr = "";
int numbytes = serialPort1.BytesToRead;
byte[] rxbytearray = new byte[numbytes];
for (int i = 0; i < numbytes; i++)
{
rxbytearray[i] = (byte)serialPort1.ReadByte();
}
string hexvalues = "";
foreach (byte b in rxbytearray)
{
if (b != '\r')
hexvalues = hexvalues + (b.ToString()) + " ";
} // hexvalues = richTextBox1.Text;
Thread.Sleep(500);
MessageBox.Show(hexvalues);
}
Encoding.ASCII.GetString(byteArray);
I'd do it this way:
class SomeClass
{
private StringBuilder _sb = new StringBuilder();
private SerialPort serialPort1
[...]
void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
if (e.EventType == SerialData.Chars)
{
_sb.Append(serialPort1.ReadExisting());
}
else
{
MessageBox.Show(_sb.ToString());
_sb.Clear();
}
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e)
{
string s = "String test <123> blablabla1 </123> <123> blablabla2 </123> <123> blablabla3 </123>";
for (int i = 0; i < s.Length; i++)
{
int s1 = s.IndexOf("<123>");
int s2 = s.IndexOf("</123>");
int s3 = s2 - s1;
s = s.Remove(s1, s3);
}
textBox.Text = s;
}
private void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
}
}
I have the following code.
The string s contains several "blablabla#" values that I want removed.
I managed to get the first removed using simple string.remove math.
How could i make it loop for each occurrence of the starting string "<123>"?
You can replace all at once with Regex.Replace:
s = Regex.Replace(s, #"<123>.*?<\/123>", "");
or to replace the extra spaces too:
s = Regex.Replace(s, #"\s*<123>.*?<\/123>\s*", "");
private void button_Click(object sender, RoutedEventArgs e)
{
string s = "String test <123> blablabla1 </123> <123> blablabla2 </123> <123> blablabla3 </123>";
int s1;
while ((s1 = s.IndexOf("<123>")) >= 0)
{
int s2 = s.IndexOf("</123>");
int s3 = s2 - s1;
s = s.Remove(s1, s3);
}
textBox.Text = s;
}
I'm trying to program the textboxes, so they do their instructions AFTER the textbox is left. Any ideas on how to do it? I tried smth with KeyUp, but don't really know how it works
using System;
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;
namespace For_homework
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var LoopResult = new List<int>();
var LoopParameters = new List<int>();
LoopParameters = TakeInput();
LoopResult = Looping(LoopParameters);
Result(LoopResult);
FinalResult(LoopResult);
}
private List<int> TakeInput()
{
var Loop = new List<int>();
Loop.Add(int.Parse(textBox1.Text));
Loop.Add(int.Parse(textBox2.Text));
Loop.Add(int.Parse(textBox3.Text));
Loop.Add(int.Parse(textBox4.Text));
Loop.Add(int.Parse(textBox5.Text));
Loop.Add(int.Parse(textBox6.Text));
return Loop;
}//Take the input
private List<int> Looping(List<int> LoopParam)
{
var LoopSum = new List<int>();
LoopSum.Add(0);
LoopSum.Add(0);
for (int i = LoopParam[0]; i <= LoopParam[1]; i += LoopParam[2])
{
LoopSum[0]+=i;
}
for(int i = LoopParam[3]; i <= LoopParam[4]; i += LoopParam[5])
{
LoopSum[1]+=i;
}
return LoopSum;
}//Do the loop and summarize
void Result (List<int> LoopResult)
{
resultA.Text = ""+LoopResult[0];
resultB.Text = ""+LoopResult[1];
}//Give result
void FinalResult(List<int> LoopResult)
{
if(LoopResult[0]>LoopResult[1])
{
WhoWins.Text = "Player A wins";
}
else if(LoopResult[1]>LoopResult[0])
{
WhoWins.Text = "Player B wins";
}
else
{
WhoWins.Text = "It's a draw";
}
}//Give final result
private void textBox1_TextChanged(object sender, EventArgs e)
{
int i = int.Parse(textBox1.Text);
if (i < 1 || i > 6)
label3.Text = "Wrong number";
}//Texbox evaluation
private void textBox2_TextChanged(object sender, EventArgs e)
{
int i = int.Parse(textBox2.Text);
if (i < 7 || i > 18)
label4.Text = "Wrong number";
}
private void textBox4_TextChanged(object sender, EventArgs e)
{
int i = int.Parse(textBox4.Text);
if (i < 1 || i > 6)
label7.Text = "Wrong number";
}//Textbox evaluation
private void textBox5_TextChanged(object sender, EventArgs e)
{
int i = int.Parse(textBox5.Text);
if (i < 7 || i > 18)
label8.Text = "Wrong number";
}
}
}
The form itself
It told me my post is mostly code so I need to add more details
There is LostFocus TextBox Event that might be useful for you in this case:
private void textBox1_LostFocus(object sender, System.EventArgs e)
{
//Do something
}
And don't forget to register event in your designer file as
textBox1.LostFocus += new EventHandler(textBox1_LostFocus);
I use this code to read from a weighting scale, I successfully read weight value from it but when trying to set the variable hex = "" for the next weight value I can't get it in the textbox, it appears very quickly and then disappears again, if I trace the program with the hex = "" enabled the results are as expected, but if run the program without trace it, then the blinking with the values and the textbox gets empty :( any ideas
string hex = "";
private delegate void Closure();
private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
if (InvokeRequired)
{
BeginInvoke(new Closure(() => { SerialPortOnDataReceived(sender, serialDataReceivedEventArgs); }));
}
else
{
if (_serialPort.BytesToRead > 0)
{
//hex = ""; <- Without this different weight values appears one after another. If applied then happens what explained above.
while (_serialPort.BytesToRead > 0) //<-- repeats until the In-Buffer is empty
{
hex += string.Format("{0:X2} ", _serialPort.ReadByte());
}
byte[] data = FromHex(hex.Trim());
textBox1.Text = Encoding.ASCII.GetString(data).Trim();
}
}
}
public byte[] FromHex(string aHex)
{
aHex = aHex.Replace(" ", "");
byte[] raw = new byte[aHex.Length / 2];
for (int i = 0; i < raw.Length; i++)
{
raw[i] = Convert.ToByte(aHex.Substring(i * 2, 2), 16);
}
return raw;
}
This is the code to start listening:
private void button1_Click(object sender, EventArgs e)
{
//<-- This block ensures that no exceptions happen
if (_serialPort != null && _serialPort.IsOpen)
_serialPort.Close();
if (_serialPort != null)
_serialPort.Dispose();
//<-- End of Block
/*--- OHAUS Ranger Count Config ---*/
//http://us.ohaus.com/us/en/home/support/faq.aspx
_serialPort = new SerialPort(comboBox1.Text);
_serialPort.BaudRate = 2400;
_serialPort.Parity = Parity.None;
_serialPort.DataBits = 7;
_serialPort.StopBits = StopBits.Two;
_serialPort.Handshake = Handshake.None;
/*--- End OHAUS Ranger Count Config ---*/
label1.Text = "Listening on " + _serialPort.PortName + "...";
_serialPort.DataReceived += SerialPortOnDataReceived; //<- Here I add the event
_serialPort.Open(); //<-- make the comport listen
}
Inside the method that is called when you press the print key, you can add the serial port event handler:
_serialPort.OnDataReceived+=SerialPortOnDataReceived;
Then, at the end of your SerialPortOnDataReceived method (after the successful read), remove the event handler from the serial port object. This will make it stop listening for new data on the serial port until you press print again.
private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
if (InvokeRequired)
{
BeginInvoke(new Closure(() => { SerialPortOnDataReceived(sender, serialDataReceivedEventArgs); }));
}
else
{
if (_serialPort.BytesToRead > 0)
{
//hex = ""; <- Without this different weight values appears one after another. If applied then happens what explained above.
while (_serialPort.BytesToRead > 0) //<-- repeats until the In-Buffer is empty
{
hex += string.Format("{0:X2} ", _serialPort.ReadByte());
}
byte[] data = FromHex(hex.Trim());
textBox1.Text = Encoding.ASCII.GetString(data).Trim();
_serialPort.OnDataReceived-=SerialPortOnDataReceived; // <---add this
}
}
}
This is how I update the UI thread.
delegate void SerialPortOnDataReceivedDelegate(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs);
private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
if (InvokeRequired)
BeginInvoke(new SerialPortOnDataReceivedDelegate(SerialPortOnDataReceived), new object[] { sender, serialDataReceivedEventArgs });
else
{
if (_serialPort.BytesToRead > 0)
{
//hex = ""; <- Without this different weight values appears one after another. If applied then happens what explained above.
while (_serialPort.BytesToRead > 0) //<-- repeats until the In-Buffer is empty
{
hex += string.Format("{0:X2} ", _serialPort.ReadByte());
}
byte[] data = FromHex(hex.Trim());
textBox1.Text = Encoding.ASCII.GetString(data).Trim();
}
}
}
public byte[] FromHex(string aHex)
{
aHex = aHex.Replace(" ", "");
byte[] raw = new byte[aHex.Length / 2];
for (int i = 0; i < raw.Length; i++)
{
raw[i] = Convert.ToByte(aHex.Substring(i * 2, 2), 16);
}
return raw;
}
This is what worked for me, I added some delay before hex = "", however I believe this is not a good practice though:
string hex = "";
private delegate void Closure();
private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
if (InvokeRequired)
{
BeginInvoke(new Closure(() => { SerialPortOnDataReceived(sender, serialDataReceivedEventArgs); }));
}
else
{
if (_serialPort.BytesToRead > 0)
{
Thread.Sleep(200); //<-- Add some delay
hex = "";
while (_serialPort.BytesToRead > 0) //<-- repeats until the In-Buffer is empty
{
hex += string.Format("{0:X2} ", _serialPort.ReadByte());
}
byte[] data = FromHex(hex.Trim());
textBox1.Text = Encoding.ASCII.GetString(data).Trim();
}
}
}
With this code I can modify decimal place, using numericUpDown. This code works if I initialize myDecimal variable. But I need modify decimal place to a value typed in textbox.
In other word myDecimal = tbxConvertito.Text. But in this case, code not work.
Check screenshot in this page please: change decimal place in textbox using numericUpDown
public partial class Form1 : Form
{
public decimal myDecimal = 3755.25012345M;
public Form1()
{
InitializeComponent();
tbxConvertito.Text = myDecimal.ToString();
numericUpDown1_ValueChanged(this, EventArgs.Empty);
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
int decimalPlace = (int)numericUpDown1.Value;
string[] numbers = myDecimal.ToString().Split(new char[] { '.', ',' });
string tmp = string.Empty;
if (decimalPlace <= numbers[1].Length)
{
tmp = "," + numbers[1].Substring(0, decimalPlace);
if (tmp.EndsWith(","))
tmp = string.Empty;
}
else
tmp = "," + numbers[1];
tbxConvertito.Text = numbers[0] + tmp;
}
}
You can split property Text from tbxConvertito.
Also when text will be changed in TextBox you must invoke numericUpDown1_ValueChanged to restrict settings in NumericUpDown.
public partial class Form1 : Form
{
public decimal myDecimal = 3755.25012345M;
public Form1()
{
InitializeComponent();
tbxConvertito.Text = myDecimal.ToString();
numericUpDown1_ValueChanged(this, EventArgs.Empty);
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
int decimalPlace = (int)numericUpDown1.Value;
string[] numbers = tbxConvertito.Text.Split(new char[] { '.', ',' });
string tmp = string.Empty;
if (numbers.Length != 1)
{
if (decimalPlace <= numbers[1].Length)
{
tmp = "," + numbers[1].Substring(0, decimalPlace);
if (tmp.EndsWith(","))
tmp = string.Empty;
}
else
tmp = "," + numbers[1];
}
tbxConvertito.Text = numbers[0] + tmp;
tbxConvertito.Select(tbxConvertito.Text.Length, 0);
}
private void tbxConvertito_TextChanged(object sender, EventArgs e)
{
numericUpDown1_ValueChanged(this, EventArgs.Empty);
decimal.TryParse(tbxConvertito.Text.Replace(',', '.'), out myDecimal);
}
}
Without lose data:
public partial class Form1 : Form
{
public decimal myDecimal = 0;
public Form1()
{
InitializeComponent();
// init value
tbxConvertito.Text = myDecimal.ToString();
numericUpDown1_ValueChanged(this, EventArgs.Empty);
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
int decimalPlace = (int)numericUpDown1.Value;
string[] numbers = myDecimal.ToString().Split(new char[] { '.', ',' });
string tmp = string.Empty;
if (numbers.Length != 1)
{
if (decimalPlace <= numbers[1].Length)
{
tmp = "," + numbers[1].Substring(0, decimalPlace);
if (tmp.EndsWith(","))
tmp = string.Empty;
}
else
tmp = "," + numbers[1];
}
tbxConvertito.Text = numbers[0] + tmp;
tbxConvertito.Select(tbxConvertito.Text.Length, 0);
}
private void tbxConvertito_TextChanged(object sender, EventArgs e)
{
if (keyValue == 188) return;
if (keyPressed)
{
string stringValue = tbxConvertito.Text;
if ((stringValue.Contains(',') && stringValue.Split(new char[] { ',' })[1].Length <= (int)numericUpDown1.Value) || !stringValue.Contains(','))
decimal.TryParse(tbxConvertito.Text.Replace(',', '.'), out myDecimal);
keyPressed = false;
}
numericUpDown1_ValueChanged(this, EventArgs.Empty);
Console.WriteLine("Displayed value: {0}", tbxConvertito.Text);
Console.WriteLine("Actual value: {0}", myDecimal);
}
bool keyPressed = false;
int keyValue;
private void tbxConvertito_KeyDown(object sender, KeyEventArgs e)
{
keyValue = e.KeyValue;
keyPressed = true;
}
}
Scenarios:
[Decimal Places = 0] you can type e.g. [1], [1234], [12345]
[Decimal Places = 1] you can type e.g. [1,1], [1234], [12345,3]
if
you change value in NumericUpDown to 0 displayed value will be [1],
[1234], [12345]
if you change value in NumericUpDown to 1 again
displayed value will be [1,1], [1234], [12345,3]
[Decimal Places = 1] the same situation as for step 2
Now we don't lose any data. We update our original data only if user will type something in our textbox.
Give it a try
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
//var ix = tbxConvertito.Text.IndexOf(',');
decimal myDecimal = 0;
bool IsDecimal = decimal.TryParse(tbxConvertito.Text, out myDecimal);
if (IsDecimal)
{
decimal letDivide = myDecimal / 100;
int decimalPlace = (int)numericUpDown1.Value;
tbxConvertito.Text = letDivide.ToString().Replace(".", "");
var index = tbxConvertito.Text.Length - decimalPlace;
if (index > -1)
tbxConvertito.Text = tbxConvertito.Text.Insert(index, ",");
else
tbxConvertito.Text = tbxConvertito.Text.Insert(1, ",");
}
else
{
tbxConvertito.Text = tbxConvertito.Text.ToString().Replace(",", "");
}
}