• ¿Quieres aprender a programar usando .NET Core sin instalar nada?

    Pues eso… me he metido en la página de instalación del .NET Core 3.0 SDK y he visto un botón con el enlace «Get Started» (ver la figura 1) y me ha llevado a la página de .NET Tutorial – Hello World in 10 minutes y en la parte de la izquierda he visto un botón con el texto Try .NET in your browser (ver figura 2) y lo he pulsado… y me ha llevado a una página en la que te va explicando las cosas básicas para crear una aplicación de consola, empezando con el clásico «Hello World!» (ver figura 3) que después ha pasado al «Hello Guillermo!» (o tu nombre) y ha seguido haciendo cambios y enseñando algunas cosas, que al menos yo ya había leído, pero así lo he tenido más claro (ver figura 4)…. bueno, es curioso más que nada… y no acaba ahí la cosa (yo no he seguido) pero se ve que sigue con otras cosas como trabajar con números, aunque esta vez ha cambiado el formato, pero básicamente es en el mismo tono (ver figuras 5 y 6), así que… te lo recomiendo ya que las cosas que incluyen son:

    Análisis de las operaciones matemáticas con enteros
    Análisis sobre el orden de las operaciones
    Información sobre los límites y la precisión de los enteros
    Operaciones con el tipo double
    Operaciones con tipos de punto fijo

    Eso sí, todo con puntos y comas… Smile

    Las capturas

    Figura 1. Get Started en la página de descarga del .NET Core 3.0 SDK
    Figura 1. Get Started en la página de descarga del .NET Core 3.0 SDK

    Figura 1.

    Figura 2. El tutorial con el botón de Try .NET in your browser
    Figura 2. El tutorial con el botón de Try .NET in your browser

    Figura 2.

    Figura 3. El tutorial de .NET In-Browser
    Figura 3. El tutorial de .NET In-Browser

    Figura 3.

    Figura 4. String Interpolation
    Figura 4. String Interpolation

    Figura 4.

    Figura 5. Aquí acaba el tutorial .NET In-Browser
    Figura 5. Aquí acaba el tutorial .NET In-Browser

    Figura 5.

    Figura 6. El tutorial de C# sigue con el compilador In-Browser
    Figura 6. El tutorial de C# sigue con el compilador In-Browser

    Los enlaces:

    Espero que si no te es de utilidad al menos te relaje un poco… jajajaja

    Nos vemos.
    Guillermo

  • Recomendaciones para adaptar los controles (y la fuente) en aplicaciones WPF (2ª parte el código para C#)

    Pues eso… lo prometido es deuda… aquí tienes el código para C# de las Recomendaciones para adaptar los controles (y la fuente) en aplicaciones WPF.
    También te enseñaré el código XAML modificado o rectificado desde la última vez, es decir, desde que ayer publiqué el original Winking smile

    Esta es la ventana de la aplicación en modo diseño (figura 1).

    Figura 1. La ventana principal en modo diseño
    Figura 1. La ventana principal en modo diseño

    Los cambios en el código XAML que he puesto son menores, para que los botones de seleccionar de los paneles superiores no se peguen demasiado a las esquinas de la derecha, para ello he cambiado el valor de Padding del control GroupBox y he reducido el margen (Margin) de la parte izquierda de los botones. También he puesto el ancho de la primera columna del ListView a 220, ya que hay espacio suficiente (la ventana principal tiene asignado un valor mínimo de 830 de ancho.

    Por si te sirve de ayuda, sobre todo si has usado padding y margin en los estilos CSS.

    Comentarte que los valores de Padding y Margin en Xaml se refieren a las posiciones:
    left, top, right, bottom,
    a diferencia de las usadas en los estilos CSS, que hacen referencia a:
    top right bottom left.
    De nada Be right back

    Aquí tienes el código XAML (del diseñador de WPF) del panel superior izquierdo, el de la derecha es prácticamente igual.

    <GroupBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="1" 
              Header="Unidad 1" Margin="0" Padding="0,0,4,0">
        <Grid DockPanel.Dock="Top" Margin="0" >
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="30"/>
                <RowDefinition Height="4"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Label Content="Directorio:" Grid.ColumnSpan="1" Margin="0,4,0,0" />
            <TextBox Name="txtDir1" Grid.Row="0" Grid.Column="1" 
                     Grid.ColumnSpan="3" Grid.RowSpan="1"
                     Margin="0,6,0,0" KeyDown="txtDir1_KeyDown"
                     TextWrapping="NoWrap" Text="S:\iPhone"/>
            <Button Name="btnSel1" Content=" Seleccionar... " 
                    Grid.Column="4" Grid.ColumnSpan="1"
                    Margin="4,6,0,0" Click="BtnSel_Click" />
            <ListView Name="lvFics1" Grid.Row="2"
                      Grid.ColumnSpan="5" Grid.RowSpan="1" 
                      Margin="0,8,0,0">
                <ListView.View>
                    <GridView >
                        <GridViewColumn Header="Archivo" Width="220"
                                        DisplayMemberBinding="{Binding Nombre}"/>
                        <GridViewColumn Header="Fecha" Width="Auto"
                                        DisplayMemberBinding="{Binding Fecha}"/>
                    </GridView>
                </ListView.View>
            </ListView>
        </Grid>
    </GroupBox>
    

    El ListView (concretamente cada GridViewColumn) definen un enlace (Binding) a Nombre y Fecha, de esa forma podremos agregar a cada elemento del ListView un objeto definido por nosotros (ItemFic) con esas dos propiedades y se asignarán correctamente a cada una de las columnas del ListView.

    Esta es la definición de las clases ItemFic y ItemDir, esta última la usaré para mostrar el nombre del directorio del ListView definido en el panel inferior.

    El método llenar es el que se encarga de asignar los elementos a los ListView.

    class ItemDir
    {
        public string Nombre { get; set; }
    }
    
    class ItemFic : ItemDir
    {
        public DateTime Fecha { get; set; }
    }
    
    /// <summary>
    /// Llenar un listview con los ficheros del directorio
    /// </summary>
    private void llenar(ListView lvFiles, string dir)
    {
        lvFiles.Items.Clear();
        var dirI = new sio.DirectoryInfo(dir);
        if (dirI.Exists == false)
            return;
    
        foreach (var fi in dirI.GetFiles())
        {
            var lvi = new ItemFic() { Nombre = fi.Name, Fecha = fi.LastWriteTime };
            lvFiles.Items.Add(lvi);
        }
    }
    

    Nota:
    sio es un alias al espacio de nombres System.IO ya que Path también está definido en System.Windows.Shapes y así no tenemos conflictos de nombres, al menos si usas C#, ya que al crear un proyecto WPF se añade esa importación de espacios de nombres.

    Cambiar el tamaño de la ventana principal y las letras

    Para gestionar el cambio de tamaño de la ventana y las letras de cada control he añadido un par de menús a la aplicación.

    Recuerda que para que los tamaños de las letras (FontSize) se hagan medio-automáticamente, tal como lo hago en esta aplicación, deben tener el valor predeterminado de las fuentes, es decir, NO añadas ningún valor a las fuentes de los controles o de los contenedores, si no, no funcionará.

    Este es el código XAML de la definición de los menús.

    <Menu x:Name="menu" Grid.Row="0" Grid.Column="0" 
          Grid.ColumnSpan="2" 
          Height="24" Margin="0,0,0,4">
        <MenuItem x:Name="mnuCambiarFuente" 
                  Header="_Tamaño y Fuente">
            <MenuItem Header="Tamaño _Ventana">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <Label Content="Cambiar tamaño" 
                           ToolTip="Puedes usar un valor negativo para reducir" />
                    <TextBox x:Name="txtTamañoVentana" Text="0,2" 
                             Grid.Column="1" Width="40"
                             Margin="8,6,0,0"/>
                    <Button x:Name="btnAplicar" Content=" Aplicar " 
                            Click="BtnAplicarVentana_Click"
                            Grid.Column="2" Margin="8,6,0,0" />
                </Grid>
            </MenuItem>
            <MenuItem Header="Tamaño _Fuente">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <Label Content="Cambiar tamaño" 
                           ToolTip="Puedes usar un valor negativo para reducir" />
                    <TextBox x:Name="txtTamañoFuente" Text="1,0" 
                             Grid.Column="1" Width="40"
                             Margin="8,6,0,0"/>
                    <Button x:Name="btnAplicarFuente" Content=" Aplicar " 
                            Click="BtnAplicarFuente_Click"
                            Grid.Column="2" Margin="8,6,0,0" />
                </Grid>
            </MenuItem>
        </MenuItem>
    
     </Menu>
    

    Aquí tienes el código de C# para cambiar el tamaño de las fuentes, se suma o sustrae el valor que indiquemos (si este último es negativo), y en el tamaño de la ventana principal añadimos (o restamos) el porcentaje indicado.

    private double meHeight;
    private double meWidth;
    private double meFontSize;
    
    private void BtnAplicarVentana_Click(object sender, RoutedEventArgs e)
    {
        // Para cambiar el tamaño a partir del valor inicial
        if (meHeight == 0)
            meHeight = this.Height;
        if (meWidth == 0)
            meWidth = this.Width;
    
        double d = 0;
        double.TryParse(txtTamañoVentana.Text, out d);
        this.Height = nuevoTamaño(meHeight, d);
        this.Width = nuevoTamaño(meWidth, d);
    }
    
    private void BtnAplicarFuente_Click(object sender, RoutedEventArgs e)
    {
        if (meFontSize == 0)
            meFontSize = this.FontSize;
        double d = 0;
        double.TryParse(txtTamañoFuente.Text, out d);
        this.FontSize = meFontSize + d;
    }
    
    
    private double nuevoTamaño(double actual, double incremento)
    {
        return actual * incremento + actual;
    }
    

    Quitar el botón maximizar de la ventana usando API

    Para terminar, te mostraré el código para quitar el botón de maximizar la ventana, ya que WPF no tiene opciones para ocultar ese botón, salvo que cambiemos el tipo de ventana, pero en este caso yo la tengo definida asignando a la propiedad ResizeMode el valor CanResizeWithGrip. Por tanto, puedo maximizar, minimizar, cambiar el tamaño, etc.

    Pero siempre queda bien eso de que el usuario no pueda maximizar de golpe, si quiere la ventana más grande, que le cambie el tamaño poco a poco Winking smile

    // --------------------------------------------------------------------------
    // Código para quitar el botón de maximizar
    // Adaptado de la versión de C# publicada en:
    // https://stackoverrun.com/es/q/5101958
    // 
    [DllImport("user32.dll")]
    private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
    
    [DllImport("user32.dll")]
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
    
    private const int GWL_STYLE = -16;
    private const int WS_MAXIMIZEBOX = 0x10000;
    
    private void Window_SourceInitialized(object sender, EventArgs e)
    {
        var hwnd = new WindowInteropHelper((Window)sender).Handle;
        var value = GetWindowLong(hwnd, GWL_STYLE);
        SetWindowLong(hwnd, GWL_STYLE, (int)(value & ~WS_MAXIMIZEBOX));
    }
    

    Los eventos, SourceInitialized y otros, están definidos en el código Xaml de la aplicación.

    Height="500" Width="850"
    MinHeight="460" MinWidth="830"
    WindowStartupLocation="CenterScreen"
    ResizeMode="CanResizeWithGrip"
    
    SourceInitialized="Window_SourceInitialized"
    
    Loaded="MainWindow_Loaded">
    

    Y esto es todo lo que quería contarte usando los puntos y comas In love

    Te recomiendo que te leas lo escrito en la primera parte, ya que aunque el código mostrado es para Visual Basic, las explicaciones, particularmente para el código XAML, te van a servir, seguro Smile

    Y para que vayas a la otra página, allí está el enlace para descargar el zip con el código completo, tanto para Visual Basic como para C#.

    Nos vemos.
    Guillermo

  • Ejemplo de expresión regular para cambiar un texto

    Pues eso… que acabo de publicar los emoticonos de Open Live Writer y quiero tener a mano la lista de iconos, pero simplificada, me explico, en el código HTML generado por OLW lo hace usando una clase para cada emoticono y yo lo quiero sin esa clase.

    El texto con la clase quedaría algo así:

    <img class="wlEmoticon wlEmoticon-smile" alt="Smile"
         src="http://www.elguillemola.com/img/emoticons/wlEmoticon-smile.png">

    Y yo quiero quitar la definición de la clase para que quedara de esta otra forma:

    <img alt="Smile" 
         src="http://www.elguillemola.com/img/emoticons/wlEmoticon-smile.png">

    Es decir quitar todas las definiciones de class (cada dibujito tiene una) Winking smile

    He usado el editor TextPad para buscar y reemplazar usando expresiones regulares y el código de búsqueda y reemplazo es el siguiente:

    He buscado:

    img class=\"*([^\"]*)\"

    Y he puesto:

    img

    Es decir, he buscado desde img (espacio) class (signo igual) (comillas dobles) y todo lo que haya hasta la siguiente comillas dobles y finalmente le agrego otras comillas dobles, si no, me devolvería el texto sin incluir las comillas de cierre.

    Nota:
    Las comillas dobles hay que indicarlas con \»

    Y esto es todo… es que he buscado ejemplos simples de sustitución con textos y no había casi nada, salvo lo publicado en mi sitio (¿Cómo no? Smile with tongue out)

    Espero que te sea de utilidad.

    Nos vemos.
    Guillermo