De C#, y porqué el tamaño sí importa

Resúltose que estabamos probando una mejora a la aplicación de Factúralo tú mismo, cuando nos hablaron para una solicitud de soporte… algo extraña.

En todos los sistemas que habíamos probado la aplicación, esta nueva actualización se realizó sin problemas. Era una actualización, a decir verdad, mucho más estética que de funcionalidad: se cambió un poco el look de la aplicación, para que fuera más concordante con los estándares de UI actuales (digamos, íconos más bonitos, etc). Pero bueno, a uno de nuestros usuarios, este movimiento le causo el siguiente horror:

************** Texto de la excepción **************

System.ComponentModel.Win32Exception (0x80004005): El parámetro no es correcto

en System.Drawing.Icon.Initialize(Int32 width, Int32 height)

en System.Drawing.Icon..ctor(SerializationInfo info, StreamingContext context)

La absoluta irreproducibilidad del error (y que se note que lo intenté, en los 3 equipos de los que pude echar mano el fin de semana) me llevó a considerar el problema un *extraño* más, y dejarlo como otro caso para la araña. Sin embargo, hoy me hablaron diciendo que el caso se había esparcido – sí, es correcto – a otro equipo de cómputo. La única característica definitoria para ambos? Netbooks.

Pues me puse a investigar. Evidentemente el problema hacía alusión a íconos, pero… a cúales? Ay de mí si eran los que había agregado… tendría que deshacer el trabajo de la semana. Pero sin desánimo me puse a buscar, y al final resultó ser el ícono de la aplicación. Sí, un simple ícono… con los siguientes parámetros:

WIDTH:700
HEIGHT:699

¬¬ Ok, eso podría ser. Pero porqué los demás sistemas se actualizaban sin problemas? Aparentemente, hay versiones de Windows que ejercen de manera más estricta el tamaño de los íconos – o mejor dicho, Vista/7 se ajustan dinámicamente aunque les avientes una barbaridad como aquella, y lo redimensionan automáticamente.

Algo nuevo aprendí hoy XD

Cómo utilizar DLLs externos en un programa de C#

…Después de la catarsis…

Hace poquito escribí acerca de mi alegría en obtener una rápida y eficiente solución a un problema que me estaba preocupando, específicamente de cómo copiar de manera segura archivos utilizando C#. Me encontré una biblioteca que hace justamente eso, utilizando el buen y viejo SCP. En pruebas todo estaba bien, terminé otras actualizaciones al proyecto, y como siempre, lo subí a un servidor donde la versión más nueva es descargable por los usuarios del sistema (o en resumen: “actualicé el servidor de actualizaciones”).

…Y que me avisan – esto no sirve. Terriblemente apenado, revisé inmediatamente la situación (ERT: 10 mins) y descubrí que C# me mostraba un error horrible a la hora de querer actualizar:

"[...]El archivo XXXX ya existe."

Mmm… huh? Pues claro que ya existe, babas. Era uno de los archivos .DLL que agregué para utilizar su funcionamiento. Pero… porqué se quejaba el instalador de ello?

La moraleja en versión breve es: lo agregué dos veces. Primero lo agregué como archivo al proyecto (Proyecto | | Incluir recurso existente) y luego agregué la referencia (Referencias | Agregar referencia). El manifiesto se confundió y chilló sin tregua.

Lección aprendida: Si vas a agregar un DLL externo, solo tienes que agregarlo como referencia. No es necesario agregarlo como archivo – Visual Studio se encarga de incluirlo con tu proyecto en el deployment.

Scp y C#

Hay veces que la vida te hace sentir inseguro, triste, alicaído, dolido y débil…

Then again, hay veces que… bueno, un video dice más que 1M palabras:

El código relevante:

Scp bule = new Scp(servidor, user, pass);
bule.Connect(puerto);
bule.Put(archivo origen, archivo destino);

Y la biblioteca relevante:

http://www.tamirgal.com/blog/page/SharpSSH.aspx

😀

Extraer nombres de rutinas en códigos fuente tipo C

Bien dicen que la necesidad es la madre de la invención.

Tenía que extraer todos los nombres de rutinas de las diferentes clases de C# que he estado trabajando. Después de buscar en Visual Studio por alguna opción que me permitiera hacer esto de manera sencilla – y vaya que busqué – me desesperé y pensé… finalmente son texto plano, no? Las clases, esto es.

Pues, ¡claro que lo son! Y entonces awk viene muy al caso. El siguiente script sirve para cualquier código fuente tipo C (rutinas con parámetros entre paréntesis, código de la rutina entre llaves) – siempre y cuando las llaves no estén nunca en la misma línea que el nombre de la rutina (una práctica relativamente común). Ejemplo de lo que sirve:

modificador modificador RUTINA(parámetros si los hay)
{
...
}

o también

modificador modificador RUTINA(parámetros si los hay)
{...}

o cualquier combinación entre ellas. Luego entonces, el script:

awk 'BEGIN{x=0;} {if($0 ~ /{/) x=x+1; if($0 ~ /}/) x=x-1; if(x==0 && $0 !~ /}/) print $0;}'

Nótese que esto no nos quita los modificadores, solo el código intermedio. Si queremos quitar todo lo demás, podemos utilizar sed – pero después de 10 minutos de jugar con él me doy cuenta que no es trivial (al menos ahorita ¬¬) y lo dejo para otro post – o como dijeran mis libros de la prepa: “Queda como ejercicio para el lector”.

🙂

Yujú!

Misión: rotar una imagen para su impresión en C# (counter-clockwise 90º)

Tiempo estimado de completado: 1-3 horas (dependiendo de lo que Dios Google me dijera)

Resultados preeliminares de búsqueda (re: Google):

Already done

Tiempo real de completado: 5 minutos

YUJU!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Poniendo colores de fondo diferentes a diferentes elementos de un ComboBox

Los comboBox son un control que permite seleccionar uno (y solo uno) de una lista de elementos. Algunos lenguajes los nombran dropDownBox, en HTMl es una etiqueta SELECT, etc.

En la familia .NET, no existe forma “sencilla” (objeto.propiedad) de cambiar el color de fondo para diferentes elementos. Pero con un poquito de investigación, descubrí que es posible redefiniendo el método que se encarga de dibujar cada elemento de la lista, en el control. Esto se logra:

1. Modificando la propiedad DrawMode del control, de “Normal” a “OwnerDrawFixed” u “OwnerDrawVariable” (este último es útil si se quiere modificar el tamaño de los elementos, de otra forma Fixed nos funciona perfecto).

2. Agregando un método al evento DrawItem del control.

3. Poniendo en ese método algo como:

private void _DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
Graphics g = e.Graphics;
switch ()
{
case 0:
g.FillRectangle(new SolidBrush(Color.LightGreen), e.Bounds);
break;
case 4:
g.FillRectangle(new SolidBrush(Color.LightCoral), e.Bounds);
break;
case 8:
g.FillRectangle(new SolidBrush(Color.LightYellow), e.Bounds);
break;
case 12:
g.FillRectangle(new SolidBrush(Color.LightBlue), e.Bounds);
break;
default:
g.FillRectangle(new SolidBrush(Color.LightGray), e.Bounds);
break;
}
string text = ((ComboBox)sender).Items[e.Index].ToString();
Brush brush = Brushes.Black;
e.Graphics.DrawString(text, ((Control)sender).Font, brush, e.Bounds.X, e.Bounds.Y);
e.DrawFocusRectangle();
}

🙂