#include "pch.h"
using namespace System::Threading;
using namespace System;
using namespace System::IO;
using namespace System::IO::Ports;
using namespace System::Text;
ref class Chat
{
static bool _continua;
static SerialPort^ Puerto_serie;
public:
static void Main(array<System::String^>^ args)
{
const int MAXIMA_LONGITUD = 40000;
String^ COM = "";
String^ nombre;
String^ mensaje;
String^ titulo = "Mini chat C++ CLR .net";
StringComparer^ comparaString = StringComparer::OrdinalIgnoreCase;
//Thread^ readThread = gcnew Thread(Leer);
Thread^ readThread = gcnew Thread(gcnew ThreadStart(Chat::Leer));
#pragma region Configuración ventana.
// Título de la ventana.
Console::Title = titulo;
// Tamaño de la ventana, x, y, o ancho y alto.
const Byte ANCHO_X = 70, ALTO_Y = 25;
Console::SetWindowSize(ANCHO_X, ALTO_Y);
// Color de fondo.
Console::BackgroundColor = ConsoleColor::Yellow;
// Color de las letras.
Console::ForegroundColor = ConsoleColor::Black;
// Limpiar pantalla y dejarlo todo en color de fondo.
Console::Clear();
// Visible el cursor.
Console::CursorVisible = true;
#pragma endregion
#pragma region Configuración puerto serie.
// Crear un nuevo objeto SerialPort con la configuración predeterminada.
Puerto_serie = gcnew SerialPort();
// Codificar a UTF-8 para que se vean bien las tildes, ñ y otros caracteres.
Puerto_serie->Encoding = Encoding::UTF8;
// Obtenga una lista de nombres de puertos serie.
array<String^>^ puertos = SerialPort::GetPortNames();
Console::WriteLine("Se encontraron los siguientes puertos series:");
// Muestre el nombre de cada puerto en la consola.
for each (String ^ puerto in puertos)
{
Console::WriteLine(puerto);
}
// Configuración.
Console::Write(
"Introduzca un número para seleccionar puerto COM.\n"
"Por ejemplo el 4, sería COM4.\n"
"\n"
"Puerto: ");
COM = Console::ReadLine(); // Escribir el número del puerto.
Console::Clear(); // Limpiar pantalla.
Puerto_serie->PortName = "COM" + COM; // Número del puerto serie.
// Configuración del puerto serie.
Puerto_serie->BaudRate = 115200;
Puerto_serie->Parity = Parity::None;
Puerto_serie->StopBits = StopBits::One;
Puerto_serie->DataBits = 8;
Puerto_serie->Handshake = Handshake::None;
Puerto_serie->RtsEnable = true;
// Establecer los tiempos de espera de lectura / escritura.
Puerto_serie->ReadTimeout = 500; // 500 Milisegundos.
Puerto_serie->WriteTimeout = 500; // 500
// Comprueba si puede abrir el puerto serie.
try
{
Puerto_serie->Open(); // Abrir el puerto serie.
}
// En caso que diera algún error como que no encuentra el puerto seleccionado
// muestra una excepción.
catch (IOException^)
{
Console::ForegroundColor = ConsoleColor::Red; // Texto en rojo.
Console::CursorVisible = false;
Console::SetCursorPosition(16, 6);
Console::WriteLine("El puerto " + Puerto_serie->PortName + " no existe " +
"o no lo encuentra.");
Console::ReadKey(); // Pulse cualquier tecla.
Environment::Exit(1); // Salir de la aplicación.
}
// Se ha denegado el acceso al puerto.
catch (UnauthorizedAccessException^)
{
Console::ForegroundColor = ConsoleColor::Red; // Texto en rojo.
Console::CursorVisible = false;
Console::SetCursorPosition(16, 6);
Console::WriteLine("Se ha denegado el acceso al puerto " + Puerto_serie->PortName +
"" +
"\nPuede estar el puerto escogido en uso.\n" +
"Elija un puerto diferente o desactiva el que está en uso.");
Console::ReadKey(); // Pulse cualquier tecla.
Environment::Exit(1); // Salir de la aplicación.
}
#pragma endregion
_continua = true;
readThread->Start();
// Mostrar texto Nombre y se
Console::Write("Nombre: ");
// guarda en la variable nombre.
nombre = Console::ReadLine();
// Se muestra el nombre o nick y el puerto seleccionado al final del título de la ventana.
Console::Title = titulo + "- Nick: " + nombre + " - COM: " + COM;
Console::WriteLine("Escriba /salir para salir.");
while (_continua)
{
// Cualquier caracter recibido se guarda en la variable mensaje.
//mensaje = Console.ReadLine();
#pragma region Enviar más de 255 caracteres.
// #########################################################################
Stream^ entradaDeDatos = Console::OpenStandardInput();
array<Byte>^ buffer = gcnew array<Byte>(MAXIMA_LONGITUD);
int numerosBytesLeidos = entradaDeDatos->Read(buffer, 0, MAXIMA_LONGITUD);
array<Char>^ chars = Console::InputEncoding->GetChars(buffer, 0, numerosBytesLeidos);
mensaje = gcnew String(chars);
// #########################################################################
#pragma endregion
// Compara /salir con el mensaje /salir si lo haz escrito igual.
// ¿Escribiste la palabra /salir?
if (comparaString->Equals("/salir\r\n", mensaje))
{
// Sí. Entonces, pone esta variable _continue en false.
_continua = false;
}
// No. Entonces, envía por el puerto serie tu nick
// y mensaje que haz escrito.
else
{
Puerto_serie->WriteLine(String::Format("<{0}>: {1}", nombre, mensaje));
}
}
// Bloquea el subproceso.
readThread->Join();
// Cierra el puerto serie.
Puerto_serie->Close();
}
// Lee mensaje recibido.
static void Leer()
{
// Si _continua es true se ejecuta todas las instrucciones dentro de while.
while (_continua)
{
try
{
// Almacena en la variable mensaje cualquier caracter o mensaje recibido.
String^ mensaje = Puerto_serie->ReadLine();
// Muestra en pantalla mensaje recibido.
Console::WriteLine(mensaje);
}
catch (TimeoutException^) {}
}
}
};
int main(array<System::String^>^ args)
{
Chat::Main(args);
return 0;
}