C# comportamiento de ComboBox enlazado a datos


Algo de lo que siempre me olvido cada vez que me pongo a tocar código en C# con VS2008.

Cuando creamos un orígen de datos desde un objeto, para luego arrastrar un ComboBox desde Data Sources hacia el formulario, deberemos setear algunas propiedades de datos enlazados a fin de evitar comportamientos extraños en el combo (por ejemplo: no libera el foco al hacer click o inmediatamente luego de cambiar el valor del combo vuelve al valor anterior).

En propiedades–>DataBindings–>Text dejamos en blanco la propiedad.

En propiedades–>DataBindings–>SelectedItem dejamos en blanco la propiedad.

En propiedades–>DataBindings–>SelectedValue establecemos la propiedad al campo del objeto a enlazar.

 

Instalar Servidor SVN en Maquina Virtual Windows Azure / Visual SVN on Windows Azure Virtual Machine


Hace unos días descubrí un servicio de Microsoft para Emprendedores, (gracias Daniel Levi), llamado BizSpark,  que puede resultarnos muy útil en entornos de desarrollo, dado que nos proporciona software para desarrollo sin costo, hosting, entre otros beneficios.

Adicionalmente, obtenemos una cuenta de Windows Azure, donde podemos configurar una máquina virtual con buenos recursos a nuestra disposición y sin costo.

Sin embargo, no pasará mucho tiempo, antes de preguntarnos como hacemos para instalar un servidor svn en dicha cuenta, así que acá dejo una guía de configuración de un servidor svn en un servidor virtual Windows Azure (Gracias Marco Pasin – Microsoft SW Artchitect):

windowsazure_visualsvnquickstart

Enjoy !

C#: Añadir ToolTip Text a un botón / Set ToolTip for a Button


Instanciamos un objeto ToolTip y, dentro de un evento MouseHover, establecemos el texto que queremos que aparezca al pasar por arriba del botón:

System.Windows.Forms.ToolTip ToolTip1 = new System.Windows.Forms.ToolTip();

public frmABMC() 
{
    InitializeComponent();
    this.btnCerrar.MouseHover += new EventHandler(btnCerrar_MouseHover);
}

void btnCerrar_MouseHover(object sender, EventArgs e)
{
    ToolTip1.SetToolTip(this.btnCerrar, "Cerrar");
}

Registrar OCX en Windows 64 bits


Si tenemos un OCX para 32 bits que necesitamos utilizar en un Windows de 64 bits, no vamos a poder registrarlo normalmente con regsvr32.

Resulta que en los sistemas Windows de 64 bits, todo lo que necesitemos registrar de 32 bits debe ir en la carpeta windowssyswow64 (en vez de windowssystem32)

Una vez copiado el ocx a esta carpeta, ejecutamos el regsvr32 como siempre. Por ejemplo, para el ocx de las impresoras fiscales Hasar:

regsvr32 c:windowssyswow64Fiscal051122.ocx

Recordar siempre ejecutar el cmd como Administrador, sinó el regsvr32 dará error.

problema de click doble en textbox enlazado a datos / must click twice to edit textbox


Algo que me ha pasado en C# NET, trabajando con controles enlazados es que teniendo un combo box enlazado a datos y con su contenido cargado, si hago un click sobre cualquier textbox del mismo formulario sin tocar el combo, accedo a completar texto en dicho control sin problemas.

Pero… si antes selecciono un valor del combo box, al querer cargar luego un texto en el textbox, debo hacer dos clicks en el textbox para poder cargar.

No les ha pasado nunca ?

Bueno, la unica solución que le encontré a este problema es colocar un evento SelectedIndexChanged en el combobox, y en ese evento colocar una llamada a cambiar el foco al control textbox cada vez que se cambia el indice del combobox.

La pérdida del foco en el combobox, equivaldría al primer click. Con lo que al hacer un click en el textbox obtengo un comportamiento normal.

Que enrosque no? supongo que solo me entenderá el que alguna vez se topó con esto.

Si le encuentran alguna otra solución me avisan !

Configuración Regional y de Idioma en SQL Server


Después de luchar un par de horas con la configuración de un servidor de base de datos sql server, dejo este pequeño recordatorio sobre la configuración necesaria para no tener inconvenietes al grabar fechas desde una aplicación desarrollada en C# .NET

Las fechas, tienen el formato Español – Argentina: dd/mm/aaaa con la hora seteada en HH:mm:ss (sin el am o pm)

Es muy común obtener un error como este al intentar grabar una fecha:

The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.

Para evitar estos inconvenientes, verificar lo siguiente:

1) En el servidor, utilizando el SQL Server Management Studio, vamos a Seguridad –> Inicios de Sesión y verificamos que el usuario con que estamos conectando a la base de datos, tenga como idioma predeterminado spanish.

2) En el servidor, donde se aloja la base de datos, configuramos en Panel de Control –> Configuración Regional y de Idioma: Español – > Argentina

2) En la maquina cliente, configuramos en Panel de Control –> Configuración Regional y de Idioma: Español – > Argentina

3) Verifiquemos que la cadena de conexión de nuestra aplicación utilice ese usuario.

Crear reportes rápidos con Crystal Reports en Visual Studio Net


Un recordatorio para algo de uso frecuente: Como crear reportes enlazados rapidamente a través de un xml que contenga la estructura de los campos a imprimir.

Asumo que tenemos cargado un dataset ds con una tabla llamada Table1 con los datos que queremos imprimir.

Por otro lado, lo que debemos hacer es crear un formulario (llamarlo por ejemplo FrmReportes) y colocarle un control CrystalReportViewer. A este control le ponemos como nombre CrvReportes.

En dicho formulario creamos una sobrecarga sobre el constructor para pasarle el reporte como parámetro:

public FrmReportes(CrystalDecisions.CrystalReports.Engine.ReportDocument Reporte)
  {
     InitializeComponent();
     this.CrvReportes.ReportSource = Reporte;
     this.CrvReportes.Show();
     this.ShowDialog();
  }

Ahora bien, para generar el reporte, debemos primero generar el xml con la estructura de los campos a imprimir:

 DataSet ds = new DataSet();
 ds.Tables.Add (controlador.GetAllDt()); //ejemplo de carga del dataset
 ds.WriteXml(@"c:temprepo.xml", ,XmlWriteMode.WriteSchema);  //el path debe tener permisos de scritura

Una vez generado el xml y almacenado en algún lugar del disco con permisos de escritura, vamos en el menú de Visual Studio a Project –> Add Component (Proyecto –> Añadir Componente) y agregamos el componente Crystal Report colocandole como nombre, por ejemplo RptReporte.rpt

Seleccionamos tipo de reporte “Reporte en Blanco” y luego, en el menú del explorador de campos, buscaremos la opción Crear nueva conexión –> Archivos de Base de Datos y nos permitirá seleccionar el archivo repo.xml creado anteriormente.

De esta manera podremos seleccionar de Table1 los campos de nuestro dataset a agregar al reporte.

Solo nos queda pendiente llamar al formulario contenedor del reporte pasandole como parametro el reporte:

CrystalDecisions.CrystalReports.Engine.ReportDocument mirepo;
mirepo = new RptReporte();
//asignamos el dataset para que actualice los datos:
mirepo.Database.Tables["Table1"].SetDataSource(ds);
//llamamos al contenedor
FrmReportes FrmRepor = new FrmReportes(mirepo);

Ojo: Es importante definir la estructura de página del reporte para impresoras genericas, a fin de que no genere problemas al imprimir en distintos modelos de impresora.
Esto lo hacemos haciendo click derecho sobre una sección o sobre el fondo del reporte –> Design –> Printer Setup –> Tildamos “No Printer”.
Allí mismo podemos predeterminar si la página va apaisada o no.

Captura Teclas / Keylogger en C# independiente del foco de la aplicación


Este es un capturador de teclas independiente de si la aplicación tiene el foco o no. Trabaja en modo consola, pero puede adaptarse a diversas necesidades.

using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace atrapateclas
{
    class Program
    {
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private const int WM_SYSKEYDOWN = 0x0104;
        private static LowLevelKeyboardProc _proc = HookCallback;
        private static IntPtr _hookID = IntPtr.Zero;

        static void Main(string[] args)
        {
            _hookID = SetHook(_proc);
            Application.Run();
            UnhookWindowsHookEx(_hookID);
        }

        private static IntPtr SetHook(LowLevelKeyboardProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
                    GetModuleHandle(curModule.ModuleName), 0);
            }
        }

        private delegate IntPtr LowLevelKeyboardProc(
            int nCode, IntPtr wParam, IntPtr lParam);

        private static IntPtr HookCallback(
            int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN))
            //if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
            {
                int vkCode = Marshal.ReadInt32(lParam);
                //if (Keys.C == (Keys)vkCode && Keys.Control == Control.ModifierKeys)
                //verifico que se presione CTRL + F1:
                if (Keys.F1 == (Keys)vkCode && Keys.Control == Control.ModifierKeys)
                    Console.WriteLine((Keys)vkCode);
            }
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook,
            LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
            IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);
    }
}

 

Tortoise Global Ignore Pattern


Aquí tenemos un patrón de exclusión para el Tortoise, para todos aquellos que trabajan con .NET de manera de filtrar carpetas, librerías, y demás archivos innecesarios a la hora de controlar versionado de código fuente.

*.resources *.o *.lo *.la *.al .libs *.so *.so.[0-9]* *.a *.pyc *.pyo *.rej *~ #*# .#* .*.swp .DS_Store App.config *.[Aa][Cc][Uu] *.[Dd][Ll][Ll] *.[Ee][Xx][Ee] *.wif *.adb *.evt *.lks *.mnu *.prd *.wrk *.xfd CopyLib Screen Report Resource BackUp backup DocData docdata List list *.bak *.BAK *.tmp *.TMP *.stf *.LOG *.log obj *.OBJ [bB]in [oO]bj Backup cab _UpgradeReport_Files debug [rR]elease *.suo *.[Mm][Ss][Ii] *.[Zz][Ii][Pp] *.[Rr][Aa][Rr] *.[Cc][Ss][Vv] logs