Microsoft Visual C#2012のソースコード
Windows Forms ControlsをThread-Safe Callsする方法については以下のアドレスを参照する必要があります。
https://msdn.microsoft.com/en-us/library/ms171728(VS.80).aspx
以下にMicrosoft Visual C#2012のソースコードを示します。
//Here are some useful articles when creating new PC applications for COM ports:
//(links valid as of June 3, 2008)
//
//"SerialPort Class"
//http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.aspx
//
//"SerialPort Members"
//http://msdn.microsoft.com/en-us/library/system.io.ports.serialport_members.aspx
//
//"SerialPort.DataReceived Event"
//http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived.aspx
//
//"How to: Make Thread-Safe Calls to Windows Forms Controls"
//http://msdn.microsoft.com/en-us/library/ms171728(VS.80).aspx
//
//"The C# Language"
//http://msdn.microsoft.com/en-us/vcsharp/aa336809.aspx
//
//"C# Tutorials"
//http://msdn.microsoft.com/en-us/library/aa288436.aspxusing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
namespace Csharp_Simple_CDC_Demo
{
public partial class Form1 : Form
{
//txtDataReceivedテキストボックスに文字列を書き込むスレッドのためのデリゲート関数を作成します
delegate void SetTextCallback(string text);
//Form1クラスのコンストラクタ。この関数が作成されフォームオブジェクトのすべてを初期化します。
public Form1()
{
InitializeComponent();
//Initialize the COM ports list
UpdateCOMPortList();
}
//定期的に起動され、COMポートのリストボックスを更新します。
private void UpdateCOMPortList()
{
int i;
bool foundDifference;
i = 0;
foundDifference = false;
//If the number of COM ports is different than the last time we
// checked, then we know that the COM ports have changed and we
// don't need to verify each entry.
if (lstCOMPorts.Items.Count == SerialPort.GetPortNames().Length)
{
//Search the entire SerialPort object. Look at COM port name
// returned and see if it already exists in the list.
foreach (string s in SerialPort.GetPortNames())
{
//If any of the names have changed then we need to update
// the list
if (lstCOMPorts.Items[i++].Equals(s) == false)
{
foundDifference = true;
}
}
}
else
{
foundDifference = true;
}
//If nothing has changed, exit the function.
if (foundDifference == false)
{
return;
}
//If something has changed, then clear the list
lstCOMPorts.Items.Clear();
//Add all of the current COM ports to the list
foreach (string s in SerialPort.GetPortNames())
{
lstCOMPorts.Items.Add(s);
}
//Set the listbox to point to the first entry in the list
lstCOMPorts.SelectedIndex = 0;
}
//Timer1のIntervalに設定した数値のms毎に実行されます。
private void timer1_Tick(object sender, System.EventArgs e)
{
//Update the COM ports list so that we can detect
// new COM ports that have been added.
UpdateCOMPortList();
}
//Connectボタンが推されると実行されます。
private void btnConnect_Click(object sender, System.EventArgs e)
{
try
{
//Get the port name from the application list box.
// the PortName attribute is a string name of the COM port (e.g. - "COM1").
serialPort1.PortName = lstCOMPorts.Items[lstCOMPorts.SelectedIndex].ToString();
//Open the COM port.
serialPort1.Open();
//Change the state of the application objects
btnConnect.Enabled = false;
lstCOMPorts.Enabled = false;
btnClose.Enabled = true;
//Clear the textbox and print that we are connected.
txtDataReceived.Clear();
txtDataReceived.AppendText("Connected.\r\n");
}
catch
{
//If there was an exception, then close the handle to
// the device and assume that the device was removed
btnClose_Click(this, null);
}
}
//Closeボタンが押されると実行されます。
private void btnClose_Click(object sender, System.EventArgs e)
{
//Reset the state of the application objects
btnClose.Enabled = false;
btnConnect.Enabled = true;
lstCOMPorts.Enabled = true;
try
{
//Dispose the In and Out buffers;
serialPort1.DiscardInBuffer();
serialPort1.DiscardOutBuffer();
//Close the COM port
serialPort1.Close();
}
//If there was an exeception then there isn't much we can do. The port is no longer available.
catch { }
}
//データがCOMポートで受信されると、この関数が呼び出されtxtDataReceivedテキストボックスにそのデータを書き込みます
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
// ReadExisting()関数は、COMポートのバッファに現在利用可能なすべてのデータを読み込みます。
//この例では、setText()関数に使用可能なCOMポートのすべてのデータを送信しています。
//注:_DataReceived()関数は、アプリケーションの他の部分から独立したスレッドで起動されます。
//デリゲート機能が,、正しく他のスレッドの内部の管理対象オブジェクトにアクセスするために必要です。
//管理対象オブジェクトをてtextBoxに書くことになりますので、デリゲート機能が要求されます。
//デリゲートの機能とその使用方法の詳細については、のsetText()関数を参照してください。
SetText(serialPort1.ReadExisting());
}
catch
{
//If there was an exception, then close the handle to the device and assume that the device was removed
btnClose_Click(this, null);
}
}
//この関数は、txtDataReceivedテキストボックスに入力されたテキストを出力します。
//呼び出し元のスレッドがテキストボックスを所有するスレッドと同じである場合、appendText()メソッドを直接呼び出されます。
//メインスレッド以外がこの関数を呼び出した場合は、メインスレッドで再び実行されるように、デリゲート関数のインスタンスが作成されます。
private void SetText(string text)
{
//InvokeRequiredは呼び出し元のスレッドIDと作成スレッドIDの比較のため必要です。
//これらのスレッドが異なっている場合は、trueを返します。
//テキストボックスにテキストを直接追加できるか、デリゲート関数のインスタンスを起動する必要があるかをこの属性を利用します。
if (txtDataReceived.InvokeRequired)
{
//deleage機能を起動する必要があります。
//SetTextCallbackデリゲートのインスタンスを作成し、デリゲートの機能を割り当てます。
//これは事実上、第二のスレッドの代わりに、同じsetText()関数が、メインスレッド内で呼び出されます。
SetTextCallback d = new SetTextCallback(SetText);
//他のスレッドからこの関数に渡されたテキストを送信する新しいデリゲートを呼び出します
Invoke(d, new object[] { text });
}
else
{
//If this function was called from the same thread that
// holds the required objects then just add the text.
txtDataReceived.AppendText(text);
}
}
//SendDataボタンが押されたときに実行されます。
private void btnSendData_Click(object sender, System.EventArgs e)
{
try
{
//Write the data in the text box to the open serial port
serialPort1.Write(txtData.Text);
}
catch
{
//If there was an exception, then close the handle to
// the device and assume that the device was removed
btnClose_Click(this, null);
}
}
}
}