I'm trying to make a windows form application in Visual Studio in C# and the purpose is to be able to communicate with an Arduino microcontroller. Right now I have 2 forms (Form1 and Form2) and I need to send and receive data from both windows to the microcontroller. I have defined a class SerialComms.cs in which there I start my serialPort and I have been able to send messages from both forms to the Arduino.
The problem is I don't know how to go about to receiving data from the Arduino as soon as the data is received. If I were to create the serialPort from one of the forms i would be able to create a function for DataReceived that will run anytime data is received but I don't know how to do that when I start my serialPort from a class. Any help?
Here is my code for both forms and my serialComms class:
Form1
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;
using System.IO.Ports;
using System.IO;
namespace Test_Comms
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
connectToArduino();
}
void connectToArduino()
{
try { SerialComms.SerialPort.Close(); }
catch { }
getAvailablePorts();
for (int i = 0; i < COMcomboBox.Items.Count; i++)
{
string inputMsg = "None";
string commport = COMcomboBox.GetItemText(COMcomboBox.Items[i]);
//Wait for Arduino message sent
//If not receieved go to next port
SerialComms.SerialPort.PortName = commport;
SerialComms.SerialPort.BaudRate = 9600;
SerialComms.SerialPort.Open();
try { SerialComms.SerialPort.Open(); }
catch { }
int counter1 = 0;
while (counter1 < 100)
{
inputMsg = SerialComms.SerialPort.ReadLine();
try { inputMsg = SerialComms.SerialPort.ReadLine(); }
catch { }
counter1++;
if (inputMsg == "Arduino")
{
counter1 = 1000;
}
}
if (inputMsg != "Arduino")
{
try { SerialComms.SerialPort.Close(); }
catch { }
}
else
{
i = COMcomboBox.Items.Count;
SerialComms.SerialPort.WriteLine("Connection Established");
toolStripStatusLabel1.Text = "Connected";
break;
}
}
}
void getAvailablePorts()
{
COMcomboBox.Items.Clear();
String[] ports = SerialPort.GetPortNames();
COMcomboBox.Items.AddRange(ports);
}
private void button1_Click(object sender, EventArgs e)
{
SerialComms.SerialPort.WriteLine("LED ON");
}
private void button2_Click(object sender, EventArgs e)
{
SerialComms.SerialPort.WriteLine("LED OFF");
}
private void button3_Click(object sender, EventArgs e) //Opens second form
{
Form2 settingsForm = new Form2();
settingsForm.ShowDialog();
}
}
}
Form2
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;
using System.IO.Ports;
using System.IO;
namespace Test_Comms
{
public partial class Form2 : Form
{
public static string text = "Test text";
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
SerialComms.SerialPort.WriteLine("LED ON");
}
private void button2_Click(object sender, EventArgs e)
{
SerialComms.SerialPort.WriteLine("LED OFF");
button2.Text = text;
}
private void Form2_Load(object sender, EventArgs e)
{
}
}
}
SerialComms.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.IO;
namespace Test_Comms
{
public static class SerialComms
{
//public static delegate void DataReceivedEventHandler(object sender, ReceivedEventArgs e);
//public static event DataReceivedEventHandler DataReceived;
private static SerialPort _serialPort = new SerialPort();
public static SerialPort SerialPort
{
get { return _serialPort; }
set { _serialPort = value; }
}
}
}
Related
I am having trouble with using serialPort1 in both of my forms. I have opened the serialPort but it just isn't receiving or sending anything. Am I not able to do it this way or is there a simpler way of doing this. Please let me know.
Form 1 Code
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 Arduino_GUI
{
public partial class Form1 : Form
{
public delegate void d1(string indata);
public Form1()
{
InitializeComponent();
serialPort1.Open();
}
private void onButton_Click(object sender, EventArgs e)
{
serialPort1.Write("A"); // on
}
private void offButton_Click(object sender, EventArgs e)
{
serialPort1.Write("a"); // off
}
private void btnOForm2_Click(object sender, EventArgs e)
{
serialPort1.Close();
Form2 f2 = new Form2();
f2.Show();
this.Hide();
}
}
}
Form 2 Code
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 Arduino_GUI
{
public partial class Form2 : Form
{
public delegate void d1(string indata);
public Form2()
{
InitializeComponent();
serialPort1.Open();
}
private void btnMain_Click(object sender, EventArgs e)
{
serialPort1.Close();
Form1 f1 = new Form1();
f1.Show();
this.Hide();
}
private void button1_Click(object sender, EventArgs e)
{
serialPort1.WriteLine("2");
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) // receiving data
{
String indata = serialPort1.ReadLine();
d1 writeit = new d1(Write2Form);
Invoke(writeit, indata);
}
public void Write2Form(string indata)
{
char firstchar;
string test;
firstchar = indata[0];
switch (firstchar)
{
case 'r':
test = indata.Substring(1);
label1.Text = test;
break;
}
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
Form1 f1 = new Form1();
f1.Show();
f1.Close();
}
}
}
Arduino Code
String data;
char d1;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
if(Serial.available()){
data = Serial.readString();
d1 = data.charAt(0);
switch(d1){ // select action based on first character
case '2': // Do when Form2 opens
Serial.println('r');
break;
}
}
}
Thank you for going through this all and I hope you can help me.
:)
Why I cannot send message to server, can anyone help me? programming language is C#, I have turned off my firewall but it's still not work.
Why I cannot send message to server, can anyone help me? programming language is C#, I have turned off my firewall but it's still not work.
Here is my server
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;
using SimpleTCP;
namespace TCP
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
SimpleTcpServer server;
private void Form1_Load(object sender, EventArgs e)
{
server = new SimpleTcpServer();
server.Delimiter = 0x13;
server.StringEncoder = Encoding.UTF8;
server.DataReceived += Server_DataReceived;
}
private void Server_DataReceived(object sender, SimpleTCP.Message e)
{
txtStatus.Invoke((MethodInvoker)delegate ()
{
txtStatus.Text += e.MessageString;
e.ReplyLine(string.Format("You said: {0}", e.MessageString));
});
}
private void btnStart_Click(object sender, EventArgs e)
{
txtStatus.Text += "Server starting...";
System.Net.IPAddress ip = System.Net.IPAddress.Parse(txtHost.Text);
server = new SimpleTcpServer().Start(ip, Convert.ToInt32(txtPort.Text));
txtStatus.Text += Environment.NewLine + "Server connected!";
//server.Start(ip, Convert.ToInt32(txtPort.Text));
}
private void btnStop_Click(object sender, EventArgs e)
{
if (server.IsStarted)
server.Stop();
}
}
}
Here is my client
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;
using SimpleTCP;
namespace Client
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
SimpleTcpClient client;
private void btnConnect_Click(object sender, EventArgs e)
{
btnConnect.Enabled = false;
//Connect to server
client.Connect(txtHost.Text, Convert.ToInt32(txtPort.Text));
}
private void Form1_Load(object sender, EventArgs e)
{
client = new SimpleTcpClient();
client.StringEncoder = Encoding.UTF8;
client.DataReceived += Client_DataReceived;
}
private void Client_DataReceived(object sender, SimpleTCP.Message e)
{
//Update message to txtStatus
txtStatus.Invoke((MethodInvoker)delegate ()
{
txtStatus.Text += e.MessageString;
});
}
private void btnSend_Click(object sender, EventArgs e)
{
client.WriteLineAndGetReply(txtMessage.Text, TimeSpan.FromSeconds(0));
}
}
}
I don't know if I have problem with connection or message problem
I cannot get the ui thread to update the ui while the file copy thread is running. My end goal is to have the animation continue to rotate until the large file copy finally completes to let the user know that the program is not frozen. It's a very simple server to server file copy program.
Can someone tell me what I'm doing wrong?
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;
using System.Threading;
using System.IO;
using System.Threading.Tasks;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void ResetProgress()
{
lblStep1.Image = null;
}
private void SetupProgress()
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
}
private void fileCopy()
{
File.Copy("large file source", "large file destination", true);
}
private void Form1_Load(object sender, EventArgs e)
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
}
private async void button1_Click(object sender, EventArgs e)
{
SetupProgress();
await Task.Run(() => fileCopy());
ResetProgress();
}
private void btnStop_Click(object sender, EventArgs e)
{
// unhandled currently
}
}
}
* Original version *
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;
using System.Threading;
using System.IO;
using System.Threading.Tasks;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private Thread workItemsProducerThread;
private Thread workItemsCopyThread;
public Form1()
{
InitializeComponent();
}
private void ResetProgress()
{
lblStep1.Image = null;
}
private void SetupProgress()
{
this.BeginInvoke((MethodInvoker)delegate ()
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
});
}
private void fileCopy()
{
File.Copy("Large file source", "Large file destination", true);
this.BeginInvoke((MethodInvoker)delegate ()
{
MessageBox.Show("Done");
});
}
private void Form1_Load(object sender, EventArgs e)
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
}
private void btnStart_Click(object sender, EventArgs e)
{
this.workItemsProducerThread = new Thread(new ThreadStart(this.SetupProgress));
this.workItemsProducerThread.IsBackground = true;
this.workItemsProducerThread.Start();
this.SetupProgress();
this.workItemsCopyThread = new Thread(new ThreadStart(this.fileCopy));
this.workItemsCopyThread.IsBackground = true;
this.workItemsCopyThread.Start();
while (workItemsCopyThread.IsAlive)
{
Thread.Sleep(1000); // wait
}
MessageBox.Show("Done");
}
private void btnStop_Click(object sender, EventArgs e)
{
if (this.workItemsProducerThread != null)
{
this.workItemsProducerThread.Abort();
lblStep1.Image = global::animation1.Properties.Resources.animation;
}
}
private void btnTest_Click(object sender, EventArgs e)
{
fileCopy();
}
}
}
Don’t sleep in your click handler. That freezes the UI thread. Just let the clock handler exit. In your file copy thread, when the copy is don’t. Use Invoke(or BeginInvoke) to cause the done messagebox to pop up on the UI thread.
Try this oldy style
private void SetupProgress()
{
Invoke((MethodInvoker) delegate
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
});
}
private Thread TDoSomeWork()
{
var t = new Thread(() => DoSomeWork());
t.Start();
return t;
}
TDoSomeWork();
I have some problems to use the MSTSCLib to connect from 1 PC to another one.
It's working with Servers but not with normal Workstations...
private void btn_connect_Click(object sender, EventArgs e)
{
try
{
rdp_control.Server = tbx_servername.Text;
rdp_control.Connect();
tabPage1.Text = "Connected";
}
catch (Exception exp)
{
MessageBox.Show(exp.ToString());
}
}
private void btn_disconnect_Click(object sender, EventArgs e)
{
if (rdp_control.Connected.ToString() == "1")
{
rdp_control.Disconnect();
}
}
Both client and server applications are in the Same Network under the same NAT. Problem is the certificate,... I need to find a way to include the certificate. With the normal Remote Desktop from Windows, you see a MessageBox with the question:"Do you want to use this certificate.... blablabla" But this is not coming up with the RDP function in c#
Any Ideas?
Thanks B.R.
Following code shows a simple RDP client and server.
RDP Server
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;
using RDPCOMAPILib;
using AxMSTSCLib;
using System.Runtime.InteropServices;
namespace TCP_to_RDP_Converter
{
public partial class Form1 : Form
{
public static RDPSession currentSession = null;
public static void createSession()
{
currentSession = new RDPSession();
}
public static void Connect(RDPSession session)
{
session.OnAttendeeConnected += Incoming;
session.Open();
}
public static void Disconnect(RDPSession session)
{
session.Close();
}
public static string getConnectionString(RDPSession session, String authString,
string group, string password, int clientLimit)
{
IRDPSRAPIInvitation invitation =
session.Invitations.CreateInvitation
(authString, group, password, clientLimit);
return invitation.ConnectionString;
}
private static void Incoming(object Guest)
{
IRDPSRAPIAttendee MyGuest = (IRDPSRAPIAttendee)Guest;
MyGuest.ControlLevel = CTRL_LEVEL.CTRL_LEVEL_INTERACTIVE;
}
/// <summary>
/// Handle the form items
/// </summary>
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
createSession();
Connect(currentSession);
textConnectionString.Text = getConnectionString(currentSession,
"Test","Group","",5);
}
private void button2_Click(object sender, EventArgs e)
{
Disconnect(currentSession);
}
}
}
In order to use the RDP communication library you need to add rdpcompapi and Microsoft windows terminal services, form the COM references.
RDP Client
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;
using RDPCOMAPILib;
using AxRDPCOMAPILib;
namespace Simple_RDP_Client
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public static void Connect(string invitation, AxRDPViewer display, string userName, string password)
{
display.Connect(invitation, userName, password);
}
public static void disconnect(AxRDPViewer display)
{
display.Disconnect();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
Connect(textConnectionString.Text, this.axRDPViewer, "", "");
}
catch (Exception)
{
MessageBox.Show("Unable to connect to the Server");
}
}
}
}
you can add reference to the AxRDPCOMAPILib by importing RDP viewer class component to the main form.
Full project can be downloaded from here [Download]:http://sandaruwmp.blogspot.com/2014/05/remote-desktop-application-with-rdp.html
use this....
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;
using MSTSCLib;
namespace RemoteTool
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MSTerminalServiceControl1.Server = textBox1.Text;
MSTerminalServiceControl1.UserName = textBox2.Text;
IMsTscNonScriptable secured = (IMsTscNonScriptable)MSTerminalServiceControl1.GetOcx();
secured.ClearTextPassword = textBox3.Text;
MSTerminalServiceControl1.Connect();
}
private void button2_Click(object sender, EventArgs e)
{
MSTerminalServiceControl1.Disconnect();
}
}
}
I want to transfer my code to a WinForms.
I know how to create buttons, text, etc... and how to operate them.
The problem is that I made my code in a windows application, and I want to transform it to WinForms application. I don't know how to copy and paste the whole code, cause in the WinForms application there is no main method..
Here is my code that I am trying to transfer to WinForms:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
TcpClient connection = new TcpClient("127.0.0.1", 5000);
StreamReader sr = new StreamReader(connection.GetStream());
StreamWriter sw = new StreamWriter(connection.GetStream());
string name2 = "";
while (true)
{
Console.WriteLine("Enter your name and press submit");
name2=Console.ReadLine();
if (name2 != "")
{
sw.WriteLine(name2);
break;
}
}
Console.WriteLine("Loop is over");
Thread t2 = new Thread(Reader);
t2.IsBackground = true;
t2.Start(connection);
while (true)
{
sw.WriteLine(Console.ReadLine());
sw.Flush();
}
}
public static void Reader(object o)
{
TcpClient con = o as TcpClient;
if (con == null)
return;
StreamReader sr = new StreamReader(con.GetStream());
while (true)
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine();
}
Console.WriteLine(sr.ReadLine());
Console.WriteLine();
}
}
}
}
Here is the Form that I have created:
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 Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void label1_Click(object sender, EventArgs e)
{
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
}
}
}
In windows form application there is main method but it is in program.cs file and its starts your default form after you program starts execution.
You can add the the textbox in form and on button event get the text of the textbox.
String username = textboxusername.Text;
Similarly you can do all the things you want.
The code that you have written before was for console application and that is not the same for the windows form application.
You have to code differently for this.