Back to basics #6 - Resistencias y diodos LED.
Hola de nuevo a todos, el día de hoy vamos a ver un poco de cómo usar unos de mi componentes electrónicos favoritos: el diodo LED.Imaginemos que en algun momento contruyes un velocímetro para una bicicleta y te levantas por las mañanas a hacer tu recorrido, pero un buen dia, por alguna razon las lamparas ddel alumbrado publico no encienden, al inicio supones que es algo normal, ya que las cosas tienden a fallar, pero tras tres semanas te das cuenta que probablemente no las van a reparar en fechas próximas por lo que decides agregarle "iluminacion" a tu bicicleta, pero surge una pregunta ¿Cómo alimentar la iluminacion?
Ultimamente se han hecho bastante accesibles los diodos LED, gracias a su alta eficiencia, son muy utiles a la hora de obtener alimentacion por medio de pilas o baterias pues nos asegura que estas duraran algo de tiempo; cosa que no pasaba antes con las lamparas que usaban filamento incandescentes y que se devoraban las pilas.
Si no has visto cómo es que hice el velocímetro, aun puedes hacerlo pero haciendo memoria, este funciona con un voltaje de 5 v, si intentamos conectar un diodo directamente, este explotaría.
Dependiendo del tipo de diodo LED, este requerirá mas o menos voltaje, en mi caso conseguí LED's de color rojo, amarillo, azul, verde y blanco. Cada uno posee una hoja de datos en la cual podemos cuales son las condiciones para que cada uno de ellos funcione, en el caso de los LED's rojos, la hoja de datos dice que se le debe de aplicar un voltaje 2.1 v y una corriente de 0.02 A (20 mili Amperes), al conectarlo a una fuente con esas características, el diodo enciende.
![]() |
| La corriente esta limitada a 20mA |
Pero si vemos bien en la imagen, si limitamos la corriente a 20 mA, el voltaje no es el que viene descrito en la hoja de datos, hay una diferencia de 0.1 V.
Para trabajar con diodos LED, lo primero que debemos de tomar en cuenta, es que no todos los diodos son iguales, la hoja de datos presentará datos nominales, pero en si cada uno es diferente. Al revisar 10 LED's rojos, si la corriente se mantiene constante, el voltaje varia desde los 1.9 V hasta los 2.2 V. Si a todos estos LED's se les alimenta con los 2.1V que dice la hoja de datos, los que funcionaron a los 1.9 V, se terminarán "acabando" mas rápido, debido que a mayor voltaje (del requerido), mayor corriente va a circular, generado calor que es uno de los enemigos de los LED, ya que a mayor temperatura, mayor corriente circula por ellos.
Si no se dispone de una fuente con control de corriente o cómo en mi caso, no es facil agregar un control de corriente (porque soy flojo), podemos simplemente agregar una resistencia que sirva para limitar la corriente.
En algunos de los post pasados hemos usado LED's y algunos de los visitantes del blog me han preguntado si podía hacer una calculadora que sirva para calcular la resistencia para llevarla en el teléfono y eso es lo que haremos, pero no en este post; al igual que en ocasiones anteriores, primero veremos como hacer los cálculos "a mano".
Aguantando con resistencia.
Para empezar, lo primero que debemos de tomar en cuenta es la ley del Ohm.
- Donde R es la resistencia que se mide en Ohm y su símbolo es "Ω".
- V es el voltaje que se mide en volt y su símbolo es "V".
- I es la corriente que se mide en Ampere y su símbolo es "A".
Para conectar, la resistencia, simplemente debemos de ponerla en serie con el diodo.
De esta forma la resistencia "disipara" el voltaje excedente, es decir si vemos la imagen anterior, tendremos que la resistencia deberá de hacer algo con los 5V de entrada menos los 3.1V del diodo, es decir 5 V - 3.1 V = 1.9 V y aquí es donde entra la ley del Ohm, el revisar la formula, vemos que necesitamos tres componentes: la resistencia, el voltaje y la corriente, pero de estos solo conocemos dos que son: el voltaje y la corriente por lo tanto si sustituimos los valores en la ecuación, tendremos:
Si tenemos un diodo 20 mA a 3.1 V y lo alimentamos con 5 V, necesitamos una resistencia de 95 Ω para que el diodo no se queme.
Ahora supongamos que conectamos diez diodos de las mismas características en paralelo, es posible poner una sola resistencia, pero debemos de tener algunas cosas en consideración, pero primero los cálculos.
Tenemos una corriente de 20 mA * 10 = 200 mA (hay que recordar que en este caso, en paralelo la corriente aumenta pero no el voltaje. Cosa contraria a cuando se hacen las conexiones en serie), el voltaje que "caerá" en la resistencia es el mismo, ya que usamos los mismos 5V para alimentar el circuito.
Al momento de elegir el tipo de resistencia, debemos de tener en cuenta cuanta potencia es capaz de disipar, en esto casos, la resistencia más común de 0.250W por lo que si excedemos esa potencia, esta se destruirá.
Para calcular cual es la potencia que una resistencia debe de soportar, debemos de recurrir a la ley del Watt que la siguiente:
Donde:
- P es la potencia que se mide en Watts y su símbolo es "W".
- V es el voltaje que se mide en Volts y su símbolo es "V".
- I es la corriente que se mide en Ampere y su símbolo es "A".
Tomado el ultimo ejemplo tenemos:
Por lo quedemos de usar una resistencia de 9.5Ω a medio Watt (que es lo mas común).
Dado que toda la energía no usada por el LED es disipada en calor por la resistencia, esta es una forma no muy conveniente de regularlo, pero para pocos LED's sirve.
Y bien, por ahora es todo, en el siguiente post haremos una calculadora para android que nos ayude a calcular la resistencia y la potencia de esta para poder usarlas, además veremos otras posibles soluciones.
Los leo luego.
Vamos a programar #69 - Syntax Highlighter M 1.0
3/17/2019 02:37:00 p.m.
aprende
,
expresiones regulares
,
programacion
,
Syntax Highlighter
No hay comentarios.
Hola de nuevo a todos, el día de hoy vamos a terminar con el código de Syntax Highlighter M.En los post anteriores implementamos la mayor parte del código, solo restaba implementar una parte para poder decir que es la versión 1.0 del programa.
El Código.
Primero veremos el código fuente de los dos formularios y la clase, y después explicare cada parte.
El código del formulario 1 es el siguiente:
/*Iconos cortesia de:
//https://www.flaticon.com/
//y
//https://www.flaticon.com/authors/dave-gandy
*/
using System;
using System.Drawing;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
namespace SyntaxHighlighter
{
public partial class FrmMain : Form
{
#region Cargar Estilos por default
private Color FontColor1 = (Color)Properties.Settings.Default["ColorRW1"];
private Color FontColor2 = (Color)Properties.Settings.Default["ColorRW2"];
private Color FontColor3 = (Color)Properties.Settings.Default["ColorRW3"];
private Color ColorComments = (Color)Properties.Settings.Default["ColorCom"];
private Color ColorNum = (Color)Properties.Settings.Default["ColorNum"];
private Color ColorStrings = (Color)Properties.Settings.Default["ColorStrings"];
private Color ColorOperator = (Color)Properties.Settings.Default["ColorOp"];
private Color GeneralColor = (Color)Properties.Settings.Default["GeneralFontColor"];
private Font GeneralFont = (Font)Properties.Settings.Default["GeneralFont"];
private string CurrentLang = "Texto plano";
#endregion
public string Comments = "";
public string Numbers = "";
public string Strings = "";
public string Operators = "";
public string ReservedWords3 = "";
public string ReservedWords2 = "";
public string ReservedWords1 = "";
#region Delegados
private delegate void UpadteRTBDelegate(int Start, int End, Color Colores);
private delegate string GetTextDelegate();
#endregion
private void UpdateRTB(int Start, int End, Color Colores)
{
if (RTBMain.InvokeRequired)
RTBMain.Invoke(new UpadteRTBDelegate(UpdateRTB), Start, End, Colores);
else
{
RTBMain.SelectionStart = Start;
RTBMain.SelectionLength = End;
RTBMain.SelectionColor = Colores;
}
}
private string GetText()
{
if (RTBMain.InvokeRequired)
return (string)RTBMain.Invoke(new GetTextDelegate(GetText));
else
return RTBMain.Text;
}
private void DoTheWork()
{
Thread DoWork = new Thread(new ThreadStart(() => ColorizeAll()));
DoWork.Start();
}
private void LoadProfile(string InXMLFile)
{
using (XmlReader XMLR = new XmlTextReader(InXMLFile))
{
try
{
XMLR.ReadToFollowing("Perfil");
XMLR.ReadToFollowing("Lenguaje");
CurrentLang = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("RW1");
ReservedWords1 = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("RW2");
ReservedWords2 = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("RW3");
ReservedWords3 = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("Comentarios");
Comments = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("Numeros");
Numbers = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("Texto");
Strings = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("Operadores");
Operators = XMLR.ReadElementContentAsString();
TSSLblLang.Text = CurrentLang;
}
catch (Exception)
{
MessageBox.Show("Parece que el XML no es valido", "Syntax Highlighter M (beta)", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
public FrmMain()
{
InitializeComponent();
}
private void ColorizeAll()
{
Colorize(ReservedWords1, WordTypes.WType1);
Colorize(ReservedWords2, WordTypes.WType2);
Colorize(ReservedWords3, WordTypes.WType3);
Colorize(Numbers, WordTypes.NType);
Colorize(Operators, WordTypes.OpType);
Colorize(Strings, WordTypes.SType);
Colorize(Comments, WordTypes.CType);
}
private void SaveColor(WordTypes Tipo, Color Colores)
{
switch (Tipo)
{
case WordTypes.WType1:
FontColor1 = Colores;
Properties.Settings.Default["ColorRW1"] = Colores;
Properties.Settings.Default.Save();
break;
case WordTypes.WType2:
FontColor2 = Colores;
Properties.Settings.Default["ColorRW2"] = Colores;
Properties.Settings.Default.Save();
break;
case WordTypes.WType3:
FontColor3 = Colores;
Properties.Settings.Default["ColorRW3"] = Colores;
Properties.Settings.Default.Save();
break;
case WordTypes.NType:
ColorNum = Colores;
Properties.Settings.Default["ColorNum"] = Colores;
Properties.Settings.Default.Save();
break;
case WordTypes.OpType:
ColorOperator = Colores;
Properties.Settings.Default["ColorOp"] = Colores;
Properties.Settings.Default.Save();
break;
case WordTypes.SType:
ColorStrings = Colores;
Properties.Settings.Default["ColorStrings"] = Colores;
Properties.Settings.Default.Save();
break;
case WordTypes.CType:
ColorComments = Colores;
Properties.Settings.Default["ColorCom"] = Colores;
Properties.Settings.Default.Save();
break;
case WordTypes.OtherType:
GeneralColor = Colores;
RTBMain.ForeColor = GeneralColor;
Properties.Settings.Default["GeneralFontColor"] = Colores;
Properties.Settings.Default.Save();
break;
default:
break;
}
}
private void Colorize(string Patron, WordTypes Tipo)
{
Color CurrentFontColor = GeneralColor;
switch (Tipo)
{
case WordTypes.WType1:
CurrentFontColor = FontColor1;
break;
case WordTypes.WType2:
CurrentFontColor = FontColor2;
break;
case WordTypes.WType3:
CurrentFontColor = FontColor3;
break;
case WordTypes.CType:
CurrentFontColor = ColorComments;
break;
case WordTypes.NType:
CurrentFontColor = ColorNum;
break;
case WordTypes.SType:
CurrentFontColor = ColorStrings;
break;
case WordTypes.OpType:
CurrentFontColor = ColorOperator;
break;
case WordTypes.OtherType:
CurrentFontColor = GeneralColor;
break;
}
try
{
//Si quitas el comentario siguiente y comentas la linea que sigue, puedes ver lo importante de la funcion GetText()
//MatchCollection wordColl = Regex.Matches(RTBMain.Text, Patron);
MatchCollection wordColl = Regex.Matches(GetText(), Patron);
foreach (Match m in wordColl)
{
UpdateRTB(m.Index, m.Length, CurrentFontColor);
}
}
catch
{
}
}
private void TSBtnOpen_Click(object sender, EventArgs e)
{
using (OpenFileDialog OpDiag = new OpenFileDialog())
{
OpDiag.Filter = "Todos los archivos|*.*|Código fuente C#|*.cs|Arvhivos de texto|*.txt";
OpDiag.Multiselect = false;
DialogResult DiagRes = OpDiag.ShowDialog();
if (DiagRes == DialogResult.OK)
{
RTBMain.Clear();
StreamReader SR = new StreamReader(OpDiag.FileName, Encoding.UTF8);
RTBMain.AppendText(SR.ReadToEnd());
DoTheWork();
}
}
}
private void TSBtnSave_Click(object sender, EventArgs e)
{
using (SaveFileDialog SaveDiag = new SaveFileDialog())
{
SaveDiag.Filter = "Texto enriquecido|*.rtf";
if (SaveDiag.ShowDialog() == DialogResult.OK)
RTBMain.SaveFile(SaveDiag.FileName);
}
}
private void TSBtnFont_Click(object sender, EventArgs e)
{
using (FontDialog FontDiag = new FontDialog())
{
FontDiag.ShowApply = false;
if (FontDiag.ShowDialog() == DialogResult.OK)
{
RTBMain.Font = FontDiag.Font;
Properties.Settings.Default["GeneralFont"] = FontDiag.Font;
Properties.Settings.Default.Save();
DoTheWork();
}
}
}
private void TSBtnColor_Click(object sender, EventArgs e)
{
using (ColorDialog ColorDiag = new ColorDialog())
{
if (ColorDiag.ShowDialog() == DialogResult.OK)
{
SaveColor((WordTypes)TSLBWordTypes.SelectedIndex, ColorDiag.Color);
}
}
}
private void FrmMain_Load(object sender, EventArgs e)
{
RTBMain.Font = GeneralFont;
RTBMain.ForeColor = GeneralColor;
TSLBWordTypes.SelectedIndex = 7;
TSSLblLang.Text = CurrentLang;
}
private void TSBtnReDo_Click(object sender, EventArgs e)
{
DoTheWork();
}
private void TSLBWordTypes_TextChanged(object sender, EventArgs e)
{
}
private void TSBtnSaveLangStyle_Click(object sender, EventArgs e)
{
using (Form2 FrmOptions = new Form2())
{
FrmOptions.ShowDialog();
}
}
private void TSLoadLang_Click(object sender, EventArgs e)
{
using (OpenFileDialog OpDiag = new OpenFileDialog())
{
OpDiag.Filter = "Archivos XML|*.xml";
if (OpDiag.ShowDialog() == DialogResult.OK)
{
LoadProfile(OpDiag.FileName);
}
}
}
}
}
El codigo del formulario 2 es el siguiente:
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.Xml;
namespace SyntaxHighlighter
{
public partial class Form2 : Form
{
private string CurrentLang = "Texto plano";
private string Comments = "";
private string Numbers = "";
private string Strings = "";
private string Operators = "";
private string ReservedWords3 = "";
private string ReservedWords2 = "";
private string ReservedWords1 = "";
private void SaveRegEx(string Patron, WordTypes Tipo)
{
switch (Tipo)
{
case WordTypes.WType1:
ReservedWords1 = Patron;
break;
case WordTypes.WType2:
ReservedWords2 = Patron;
break;
case WordTypes.WType3:
ReservedWords3 = Patron;
break;
case WordTypes.NType:
Numbers = Patron;
break;
case WordTypes.OpType:
Operators = Patron;
break;
case WordTypes.SType:
Strings = Patron;
break;
case WordTypes.CType:
Comments = Patron;
break;
case WordTypes.OtherType:
break;
default:
break;
}
}
private void LoadProfile(string InXMLFile)
{
using (XmlReader XMLR = new XmlTextReader(InXMLFile))
{
try
{
XMLR.ReadToFollowing("Perfil");
XMLR.ReadToFollowing("Lenguaje");
CurrentLang = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("RW1");
ReservedWords1 = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("RW2");
ReservedWords2 = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("RW3");
ReservedWords3 = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("Comentarios");
Comments = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("Numeros");
Numbers = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("Texto");
Strings = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("Operadores");
Operators = XMLR.ReadElementContentAsString();
TxtLang.Text = CurrentLang;
}
catch (Exception)
{
MessageBox.Show("Parece que el XML no es valido", "Syntax Highlighter M (beta)", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private string GetRegEx(WordTypes Cual)
{
switch (Cual)
{
case WordTypes.WType1:
return ReservedWords1;
case WordTypes.WType2:
return ReservedWords2;
case WordTypes.WType3:
return ReservedWords3;
case WordTypes.NType:
return Numbers;
case WordTypes.OpType:
return Operators;
case WordTypes.SType:
return Strings;
case WordTypes.CType:
return Comments;
case WordTypes.OtherType:
return "";
default:
return "";
}
}
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
LBWordTypes.SelectedIndex = 0;
TxtLang.Text = CurrentLang;
}
private void BtnSave_Click(object sender, EventArgs e)
{
SaveRegEx(TxtExpression.Text, (WordTypes)LBWordTypes.SelectedIndex);
}
private void LBWordTypes_SelectedIndexChanged(object sender, EventArgs e)
{
TxtExpression.Text = GetRegEx((WordTypes)LBWordTypes.SelectedIndex);
}
private void BtnSaveToFile_Click(object sender, EventArgs e)
{
CurrentLang = TxtLang.Text;
using (SaveFileDialog SavDiag = new SaveFileDialog())
{
SavDiag.Filter = "Archivo XML|*.xml";
if (SavDiag.ShowDialog() == DialogResult.OK)
{
HandleData HD = new HandleData();
HD.SaveProfile(SavDiag.FileName, CurrentLang, CurrentLang, ReservedWords1, ReservedWords2, ReservedWords3, Comments, Numbers, Strings, Operators);
}
}
}
private void TxtExpression_TextChanged(object sender, EventArgs e)
{
SaveRegEx(TxtExpression.Text, (WordTypes)LBWordTypes.SelectedIndex);
}
private void BtnOpen_Click(object sender, EventArgs e)
{
using (OpenFileDialog OpDiag = new OpenFileDialog())
{
OpDiag.Filter = "Archivos XML|*.xml";
if (OpDiag.ShowDialog() == DialogResult.OK)
{
LoadProfile(OpDiag.FileName);
LBWordTypes.SelectedIndex = 0;
TxtExpression.Text = GetRegEx((WordTypes)0);
}
}
}
}
}
El código de la clase es el siguiente:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace SyntaxHighlighter
{
public enum WordTypes : int
{
WType1 = 0,
WType2,
WType3,
NType,
OpType,
SType,
CType,
OtherType
}
class HandleData
{
public void SaveProfile(string XmlPath, string Lenguaje, string CurrentLang, string ReservedWords1, string ReservedWords2,
string ReservedWords3, string Comments, string Numbers, string Strings, string Operators)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = "\t";
using (XmlWriter XWriter = XmlWriter.Create(XmlPath, settings))
{
XWriter.WriteStartDocument();
XWriter.WriteComment("Syntax Highlighter M (beta)");
XWriter.WriteStartElement("Perfil");
XWriter.WriteElementString("Lenguaje", CurrentLang);
XWriter.WriteElementString("RW1", ReservedWords1);
XWriter.WriteElementString("RW2", ReservedWords2);
XWriter.WriteElementString("RW3", ReservedWords3);
XWriter.WriteElementString("Comentarios", Comments);
XWriter.WriteElementString("Numeros", Numbers);
XWriter.WriteElementString("Texto", Strings);
XWriter.WriteElementString("Operadores", Operators);
XWriter.WriteEndElement();
XWriter.WriteEndDocument();
}
}
}
}
Primero revisemos el código del formulario 1. Primero definimos todas la variables que almacenarán los datos que están guardados en los ajustes, en los ajustes guardamos todos los estilos, fuentes y algunos datos más que vamos a usar. Luego iniciamos las variables que contendrán las expresiones regulares, se dejan vacías puesto que todas se van a cargar de los archivos externos. De ahi en fuera las funciones permanecen igual.
En el formulario 2, se han añadido tres funciones, la primera de ellas en orden de aparición es "SaveRegEx()" su función solamente es la de asignarle el valor del parámetro "Patron" a la variable indicada dependiendo de cual sea el valor del parámetro "Tipo"; este del tipo "WordTypes".
La siguiente función es "LoadProfile", está función es idéntica a la que se encuentra en el formulario 1, al inicio iba a ponerla en la clase para acceder al ella, pero cómo había que hacer más cambios, simplemente decidí no hacerlo (la pereza es mala ;)) y simplemente copie la función y cree variables con el mismo nombre (después veremos porque si podemos hacer esto).
La siguiente función es "GetRegEx()", esta recibe un parámetro del tipo "WordTypes" llamado "Cual", el objetivo de esta, es obtener el valor de la variable que contienen el valor de una expresión regular, dependiendo el caso regresara un valor con la expresión regular, esto lo usamos para cada vez que se cambie la selección de un elemento de "LBWordTypes" que es un "ListBox", obtengamos el valor adecuado dependiendo de la selección.
En este formulario podemos crear un estilo o editar uno ya existente y precisamente esta era la razón por la cual en el post anterior no podíamos decir que el programa estaba terminado, ahora tenemos la capicidad de editar un estilo existente o de crear uno nuevo.
La clase "HandleData" no contiene cambios. En ella simplemente definimos la enumeración "WordTypes" y creamos la función "SaveProfile" que se usa para guardar las expresiones regulares en un archivo XML, la idea original era poner aquí todas las funciones, pero por cuestiones que son difíciles de explicar (recuerden otra vez, la pereza es mala), simplemente no lo hice.
Con lo anterior hemos creado un programa que sirve para resaltar la sintaxis, la descarga incluye dos archivos XML con las expresiones regulares que sirven para resaltar el código en C# y C para arduino, puedes usarlo cómo ejemplo para crear otros. Solo debes de tomar en cuenta que en lenguajes cómo visual basic las palabras reservadas no importa si están con mayúsculas o minúsculas.
¿Cómo usarlo?
El uso del programa es realmente sencillo, si queremos resaltar el código fuente, lo primero que demos de hacer es cargar el estilo para el lenguaje que queremos, para eso hacemos clic en el boton "Cargar estilo", una vez cargado, debemos de abrir el archivo de código fuente o pegar el código fuente directamente en el editor, si elegimos la opción de "Abrir", en cuanto cargue el archivo, intentará colorearlo dependiendo del estilo cargado, por lo que si no hay ninguno previamente cargado, recorrerá todo el archivo y no pintará nada.
Para cambiar los colores de cada estilo, debemos de seleccionar que tipo de elemento es al que queremos cambiar el color.
En la lista debemos de seleccionar cual es el tipo de elemento que queremos editar y para editarlo, debemos de hacer clic en el botón "Color" y se abrirá el cuadro de selección de color, cuando hayamos hecho todos los cambios que queremos, debemos de hacer clic en el botón "Volver a colorear", para que los cambios se hagan visibles.
Para editar o crear un nuevo estilo, debemos de hacer clic en el botón "Editar estilo", después se nos abrirá una nueva ventana donde podremos editar las expresiones regulares.
Una vez que hayamos editado la expresión regular para cada apartado, debemos de hacer clic en "Guardar en archivo" para que los cambios se guarden. Para aplicar el estilo, es necesario cargarlo en la ventana principal usando el botón "Cargar estilo".
Para guardar el resultados del resaltado, en la ventana principal, debemos de hacer clic en "Guardar", con esto se creara un archivo de formato enriquecido que podremos abrir en Microsoft Word (o cualquier editor de texto que soporte rtf). Otro cosa que es importante remarcar, es que por ahora, el fondo del texto es transparente, por lo que al exportarlo y abrirlo con Word, veremos que todas las letras que estén en blanco no se verán, para eso es necesario cambiar el color de la hoja.
![]() |
| Así se ve con el fondo cambiado a negro. |
![]() |
| Así se ve con el fondo por default |
Y bien, por ahora es todo, el código fuente cómo de costumbre lo pongo en mi dropbox para que lo descargues y lo edites a tu gusto.
Los leo luego
Vamos a programar #68 - Syntax Highlighter M (beta 2)
3/10/2019 01:43:00 p.m.
c#
,
expresiones regulares
,
programacion
,
Syntax Highlighter
No hay comentarios.
Hola de nuevo a todos, el dia de hoy vamos a continuar con mas de Syntax Highlighter M ahora en su versión beta 2.En el post anterior vimos cómo implementar el programa de tal forma que coloreaba el código en C#, pero la idea del programa es poder resaltar la sintaxis de cualquier programa. Hay dos posibilidades para lograr esa tarea; la primera: programar cada expresión regular para cada lenguaje dentro del programa, hacerlo tantas veces cómo lenguajes haya; la segunda: crear archivos externos que contengan un patrón para cada lenguaje y cargarlo solo cuando sea necesario.
La segunda forma me parece la mas optima, ya que se puede extender la funcionalidad del programa de forma relativamente más rápida que teniendo que compilar el programa cada vez que se quiera agregar un nuevo lenguaje. Para poder almacenar los patrones, decidí usar archivos XML, ya que ofrecen una manera sencilla de almacenar la información y .NET ayuda a manejar estos archivos de manera sencilla.
La aplicación ahora consta de tres partes, dos formularios y una clase, de manera correspondiente, los códigos fuente son los siguientes:
/*Iconos cortesia de:
//https://www.flaticon.com/
//y
//https://www.flaticon.com/authors/dave-gandy
*/
using System;
using System.Drawing;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
namespace SyntaxHighlighter
{
public partial class FrmMain : Form
{
#region Cargar Estilos por default
private Color FontColor1 = (Color)Properties.Settings.Default["ColorRW1"];
private Color FontColor2 = (Color)Properties.Settings.Default["ColorRW2"];
private Color FontColor3 = (Color)Properties.Settings.Default["ColorRW3"];
private Color ColorComments = (Color)Properties.Settings.Default["ColorCom"];
private Color ColorNum = (Color)Properties.Settings.Default["ColorNum"];
private Color ColorStrings = (Color)Properties.Settings.Default["ColorStrings"];
private Color ColorOperator = (Color)Properties.Settings.Default["ColorOp"];
private Color GeneralColor = (Color)Properties.Settings.Default["GeneralFontColor"];
private Font GeneralFont = (Font)Properties.Settings.Default["GeneralFont"];
private string CurrentLang = "Texto plano";
#endregion
public string Comments = "";
public string Numbers = "";
public string Strings = "";
public string Operators = "";
public string ReservedWords3 = "";
public string ReservedWords2 = "";
public string ReservedWords1 = "";
#region Delegados
private delegate void UpadteRTBDelegate(int Start, int End, Color Colores);
private delegate string GetTextDelegate();
#endregion
private void UpdateRTB(int Start, int End, Color Colores)
{
if (RTBMain.InvokeRequired)
RTBMain.Invoke(new UpadteRTBDelegate(UpdateRTB), Start, End, Colores);
else
{
RTBMain.SelectionStart = Start;
RTBMain.SelectionLength = End;
RTBMain.SelectionColor = Colores;
}
}
private string GetText()
{
if (RTBMain.InvokeRequired)
return (string)RTBMain.Invoke(new GetTextDelegate(GetText));
else
return RTBMain.Text;
}
private void DoTheWork()
{
Thread DoWork = new Thread(new ThreadStart(() => ColorizeAll()));
DoWork.Start();
}
private void LoadProfile(string InXMLFile)
{
using (XmlReader XMLR = new XmlTextReader(InXMLFile))
{
try
{
XMLR.ReadToFollowing("Perfil");
XMLR.ReadToFollowing("Lenguaje");
CurrentLang = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("RW1");
ReservedWords1 = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("RW2");
ReservedWords2 = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("RW3");
ReservedWords3 = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("Comentarios");
Comments = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("Numeros");
Numbers = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("Texto");
Strings = XMLR.ReadElementContentAsString();
XMLR.ReadToFollowing("Operadores");
Operators = XMLR.ReadElementContentAsString();
TSSLblLang.Text = CurrentLang;
}
catch (Exception)
{
MessageBox.Show("Parece que el XML no es valido", "Syntax Highlighter M (beta)", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
public FrmMain()
{
InitializeComponent();
}
private void ColorizeAll()
{
Colorize(ReservedWords1, WordTypes.WType1);
Colorize(ReservedWords2, WordTypes.WType2);
Colorize(ReservedWords3, WordTypes.WType3);
Colorize(Numbers, WordTypes.NType);
Colorize(Operators, WordTypes.OpType);
Colorize(Strings, WordTypes.SType);
Colorize(Comments, WordTypes.CType);
}
private void SaveColor(WordTypes Tipo, Color Colores)
{
switch (Tipo)
{
case WordTypes.WType1:
FontColor1 = Colores;
Properties.Settings.Default["ColorRW1"] = Colores;
Properties.Settings.Default.Save();
break;
case WordTypes.WType2:
FontColor2 = Colores;
Properties.Settings.Default["ColorRW2"] = Colores;
Properties.Settings.Default.Save();
break;
case WordTypes.WType3:
FontColor3 = Colores;
Properties.Settings.Default["ColorRW3"] = Colores;
Properties.Settings.Default.Save();
break;
case WordTypes.NType:
ColorNum = Colores;
Properties.Settings.Default["ColorNum"] = Colores;
Properties.Settings.Default.Save();
break;
case WordTypes.OpType:
ColorOperator = Colores;
Properties.Settings.Default["ColorOp"] = Colores;
Properties.Settings.Default.Save();
break;
case WordTypes.SType:
ColorStrings = Colores;
Properties.Settings.Default["ColorStrings"] = Colores;
Properties.Settings.Default.Save();
break;
case WordTypes.CType:
ColorComments = Colores;
Properties.Settings.Default["ColorCom"] = Colores;
Properties.Settings.Default.Save();
break;
case WordTypes.OtherType:
GeneralColor = Colores;
RTBMain.ForeColor = GeneralColor;
Properties.Settings.Default["GeneralFontColor"] = Colores;
Properties.Settings.Default.Save();
break;
default:
break;
}
}
private void Colorize(string Patron, WordTypes Tipo)
{
Color CurrentFontColor = GeneralColor;
switch (Tipo)
{
case WordTypes.WType1:
CurrentFontColor = FontColor1;
break;
case WordTypes.WType2:
CurrentFontColor = FontColor2;
break;
case WordTypes.WType3:
CurrentFontColor = FontColor3;
break;
case WordTypes.CType:
CurrentFontColor = ColorComments;
break;
case WordTypes.NType:
CurrentFontColor = ColorNum;
break;
case WordTypes.SType:
CurrentFontColor = ColorStrings;
break;
case WordTypes.OpType:
CurrentFontColor = ColorOperator;
break;
case WordTypes.OtherType:
CurrentFontColor = GeneralColor;
break;
}
try
{
//Si quitas el comentario siguiente y comentas la linea que sigue, puedes ver lo importante de la funcion GetText()
//MatchCollection wordColl = Regex.Matches(RTBMain.Text, Patron);
MatchCollection wordColl = Regex.Matches(GetText(), Patron);
foreach (Match m in wordColl)
{
UpdateRTB(m.Index, m.Length, CurrentFontColor);
}
}
catch
{
}
}
private void TSBtnOpen_Click(object sender, EventArgs e)
{
using (OpenFileDialog OpDiag = new OpenFileDialog())
{
OpDiag.Filter = "Todos los archivos|*.*|Código fuente C#|*.cs|Arvhivos de texto|*.txt";
OpDiag.Multiselect = false;
DialogResult DiagRes = OpDiag.ShowDialog();
if (DiagRes == DialogResult.OK)
{
RTBMain.Clear();
StreamReader SR = new StreamReader(OpDiag.FileName, Encoding.UTF8);
RTBMain.AppendText(SR.ReadToEnd());
DoTheWork();
}
}
}
private void TSBtnSave_Click(object sender, EventArgs e)
{
using (SaveFileDialog SaveDiag = new SaveFileDialog())
{
SaveDiag.Filter = "Texto enriquecido|*.rtf";
if (SaveDiag.ShowDialog() == DialogResult.OK)
RTBMain.SaveFile(SaveDiag.FileName);
}
}
private void TSBtnFont_Click(object sender, EventArgs e)
{
using (FontDialog FontDiag = new FontDialog())
{
FontDiag.ShowApply = false;
if (FontDiag.ShowDialog() == DialogResult.OK)
{
RTBMain.Font = FontDiag.Font;
Properties.Settings.Default["GeneralFont"] = FontDiag.Font;
Properties.Settings.Default.Save();
DoTheWork();
}
}
}
private void TSBtnColor_Click(object sender, EventArgs e)
{
using (ColorDialog ColorDiag = new ColorDialog())
{
if (ColorDiag.ShowDialog() == DialogResult.OK)
{
SaveColor((WordTypes)TSLBWordTypes.SelectedIndex, ColorDiag.Color);
}
}
}
private void FrmMain_Load(object sender, EventArgs e)
{
RTBMain.Font = GeneralFont;
RTBMain.ForeColor = GeneralColor;
TSLBWordTypes.SelectedIndex = 7;
TSSLblLang.Text = CurrentLang;
}
private void TSBtnReDo_Click(object sender, EventArgs e)
{
DoTheWork();
}
private void TSLBWordTypes_TextChanged(object sender, EventArgs e)
{
}
private void TSBtnSaveLangStyle_Click(object sender, EventArgs e)
{
using (Form2 FrmOptions = new Form2())
{
FrmOptions.ShowDialog();
}
}
private void TSLoadLang_Click(object sender, EventArgs e)
{
using (OpenFileDialog OpDiag = new OpenFileDialog())
{
OpDiag.Filter = "Archivos XML|*.xml";
if (OpDiag.ShowDialog() == DialogResult.OK)
{
LoadProfile(OpDiag.FileName);
}
}
}
}
}
El código del formulario 2
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.Xml;
namespace SyntaxHighlighter
{
public partial class Form2 : Form
{
private string CurrentLang = "Texto plano";
private string Comments = "";
private string Numbers = "";
private string Strings = "";
private string Operators = "";
private string ReservedWords3 = "";
private string ReservedWords2 = "";
private string ReservedWords1 = "";
private void SaveRegEx(string Patron, WordTypes Tipo)
{
switch (Tipo)
{
case WordTypes.WType1:
ReservedWords1 = Patron;
break;
case WordTypes.WType2:
ReservedWords2 = Patron;
break;
case WordTypes.WType3:
ReservedWords3 = Patron;
break;
case WordTypes.NType:
Numbers = Patron;
break;
case WordTypes.OpType:
Operators = Patron;
break;
case WordTypes.SType:
Strings = Patron;
break;
case WordTypes.CType:
Comments = Patron;
break;
case WordTypes.OtherType:
break;
default:
break;
}
}
private string GetRegEx(WordTypes Cual)
{
switch (Cual)
{
case WordTypes.WType1:
return ReservedWords1;
case WordTypes.WType2:
return ReservedWords2;
case WordTypes.WType3:
return ReservedWords3;
case WordTypes.NType:
return Numbers;
case WordTypes.OpType:
return Operators;
case WordTypes.SType:
return Strings;
case WordTypes.CType:
return Comments;
case WordTypes.OtherType:
return "";
default:
return "";
}
}
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
LBWordTypes.SelectedIndex = 0;
TxtLang.Text = CurrentLang;
}
private void BtnSave_Click(object sender, EventArgs e)
{
SaveRegEx(TxtExpression.Text, (WordTypes)LBWordTypes.SelectedIndex);
}
private void LBWordTypes_SelectedIndexChanged(object sender, EventArgs e)
{
TxtExpression.Text = GetRegEx((WordTypes)LBWordTypes.SelectedIndex);
}
private void BtnSaveToFile_Click(object sender, EventArgs e)
{
CurrentLang = TxtLang.Text;
using (SaveFileDialog SavDiag = new SaveFileDialog())
{
SavDiag.Filter = "Archivo XML|*.xml";
if (SavDiag.ShowDialog() == DialogResult.OK)
{
HandleData HD = new HandleData();
HD.SaveProfile(SavDiag.FileName, CurrentLang, CurrentLang, ReservedWords1, ReservedWords2, ReservedWords3, Comments, Numbers, Strings, Operators);
}
}
}
private void TxtExpression_TextChanged(object sender, EventArgs e)
{
SaveRegEx(TxtExpression.Text, (WordTypes)LBWordTypes.SelectedIndex);
}
private void BtnOpen_Click(object sender, EventArgs e)
{
}
}
}
El código de la clase
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace SyntaxHighlighter
{
public enum WordTypes : int
{
WType1 = 0,
WType2,
WType3,
NType,
OpType,
SType,
CType,
OtherType
}
class HandleData
{
public void SaveProfile(string XmlPath, string Lenguaje, string CurrentLang, string ReservedWords1, string ReservedWords2,
string ReservedWords3, string Comments, string Numbers, string Strings, string Operators)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = "\t";
using (XmlWriter XWriter = XmlWriter.Create(XmlPath, settings))
{
XWriter.WriteStartDocument();
XWriter.WriteComment("Syntax Highlighter M (beta)");
XWriter.WriteStartElement("Perfil");
XWriter.WriteElementString("Lenguaje", CurrentLang);
XWriter.WriteElementString("RW1", ReservedWords1);
XWriter.WriteElementString("RW2", ReservedWords2);
XWriter.WriteElementString("RW3", ReservedWords3);
XWriter.WriteElementString("Comentarios", Comments);
XWriter.WriteElementString("Numeros", Numbers);
XWriter.WriteElementString("Texto", Strings);
XWriter.WriteElementString("Operadores", Operators);
XWriter.WriteEndElement();
XWriter.WriteEndDocument();
}
}
}
}
Cómo verás el código aun no está bien ordenado, pero eso se debe a que todavía van a haber cambios importantes por eso veremos la explicación y la presentación de Syntax Highlighter M 1.0 en el siguiente post, por ahora puedes divertirte averiguando cómo es que funciona (tanto el programa cómo el código). La descarga incluye dos archivos XML, uno de ellos contienen las expresiones regulares para el código de C# y el otro medio tiene la parte para resaltar el código de arduino y lo puedes descargar de mi dropbox cómo ya es costumbre.
Los leo luego.
Suscribirse a:
Entradas
(
Atom
)
















No hay comentarios. :
Publicar un comentario