WPF - Ventana sin marco que puede cambiarse de tamaño

Descripción general

Ventana sin marco que puede cambiarse de tamaño, moverse, y cerrarse

[TOC] Tabla de Contenidos


↑↑↑

Introducción

En este artículo se estudia como definir una ventana WPF para que se muestre sin marco y que cumpla las siguientes propiedades:

Aparentemente, y pensando en visiones anteriores, se podría esperar un código bastante complejo, pero en WPF es mucho mas sencillo que lo que puede parecer,

Esta es la ventana que quiero mostrar y sobre la que trabajamos

Falta el texto Alt de la imagen

Imagen de la ventana que genera este código


↑↑↑

En la ventana, Todo el código Xaml

<Window x:Class="WindowEsperaSimple"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="Window Espera"
        WindowStyle="None"
        AllowsTransparency="True"
        Background="Transparent"
        ShowInTaskbar="False"
        MouseDown="Window_MouseDown"
        MouseRightButtonDown="Window_MouseRightButtonDown"
        Height="200" Width="320"
        ResizeMode="CanResizeWithGrip">



    <Window.CommandBindings>
        <!-- Menu Archivo -->
        <CommandBinding Command="ApplicationCommands.Close"        
                        Executed="CloseCommandBinding_Executed"        
                        CanExecute="CloseCommandBinding_CanExecute"/>
    </Window.CommandBindings>

    <Window.InputBindings>
        <!-- Menu Archivo -->
        <KeyBinding Command="ApplicationCommands.Close"  Key="F4" Modifiers="Alt"   />
    </Window.InputBindings>



    <Border BorderBrush="#FFE9DBF9"
            BorderThickness="1"
            HorizontalAlignment="Stretch"
            VerticalAlignment="Stretch"
            CornerRadius="10"
            Background="#FFE9DBF9" >

        <Grid Margin="1">

            <Grid.RowDefinitions>
                <RowDefinition Height="auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>


            <StackPanel    HorizontalAlignment="Right" VerticalAlignment="Center" Orientation="Horizontal">
                <!-- imagen ayuda (negro) arriba a la izquierda -->
                <Viewbox Width="16" Height="16" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
                    <Rectangle Width="16" Height="16" >
                        <Rectangle.ToolTip>
                            <StackPanel  Orientation="Vertical">
                                <TextBlock Text ="Mover la ventana : [Botón izquierdo] del ratón: " />
                                <TextBlock Text ="Cerrar la ventana:" />
                                <TextBlock Text =" - [Botón derecho]   del ratón, O bien," />
                                <TextBlock Text =" - [Alt + F4]."/>
                            </StackPanel>
                        </Rectangle.ToolTip>
                        <Rectangle.Fill>
                            <DrawingBrush>
                                <DrawingBrush.Drawing>
                                    <DrawingGroup>
                                        <DrawingGroup.Children>
                                            <GeometryDrawing Brush="#00FFFFFF" Geometry="F1M16,16L0,16 0,0 16,0z" />
                                            <GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M0,8C0,3.582 3.582,0 8,0 12.418,0 16,3.582 16,8 16,12.418 12.418,16 8,16 3.582,16 0,12.418 0,8" />
                                            <GeometryDrawing Brush="#FF424242" Geometry="F1M11,7C11,8.104,10.102,9,9,9L9,10 7,10 7,9C7,7.896,7.897,7,9,7L9,5.203C8.841,5.115 8.495,5 8,5 7.505,5 7.159,5.115 7,5.203L7,6 5,6 5,5C5,3.841 6.262,3 8,3 9.738,3 11,3.841 11,5z M9,13L7,13 7,11 9,11z M8,1C4.134,1 1,4.134 1,8 1,11.865 4.134,15 8,15 11.866,15 15,11.865 15,8 15,4.134 11.866,1 8,1" />
                                            <GeometryDrawing Brush="#FFF0EFF1" Geometry="F1M9,11L7,11 7,13 9,13z M9,10L7,10 7,9C7,7.896,7.897,7,9,7L9,5.203C8.841,5.115 8.495,5 8,5 7.505,5 7.159,5.115 7,5.203L7,6 5,6 5,5C5,3.841 6.262,3 8,3 9.738,3 11,3.841 11,5L11,7C11,8.104,10.102,9,9,9z" />
                                        </DrawingGroup.Children>
                                    </DrawingGroup>
                                </DrawingBrush.Drawing>
                            </DrawingBrush>
                        </Rectangle.Fill>
                    </Rectangle>
                </Viewbox>
                <!-- /Eof  imagen ayuda (negro) arriba a la izquierda -->
            </StackPanel>


            <Label x:Name="labelTitulo" Grid.Row="1"
                   Margin="10"
                   Content="Espera....   Estoy trabajando (mas o menos) "
                   HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
                   VerticalAlignment="Stretch"  VerticalContentAlignment="Center"
                   Background="{DynamicResource {x:Static SystemColors.InfoBrushKey}}" />

        </Grid>
    </Border>

</Window>

↑↑↑

En la ventana, Todo el código VB

''' <summary>
'''  Ventana simple que muestra el mensaje de espera
''' </summary>
Public Class WindowEsperaSimple

#Region "Eventos de la ventana"

    ' se usa para mover la ventana pulsando el botón izquierdo del ratón
    Private Sub Window_MouseDown(sender As Object, e As MouseButtonEventArgs)
        Me.DragMove()
        e.Handled = True
    End Sub

    ' se usa para CERRAR la ventana pulsando el botón derecho del ratón
    Private Sub Window_MouseRightButtonDown(sender As Object, e As MouseButtonEventArgs)
        Me.Close()
        e.Handled = True
    End Sub


    ' se usa para cerrar la ventana usando el comando, llamándolo con algún botón
    ' en este caso concerto se activa con el juego de teclas [Alt + F4]
    Private Sub CloseCommandBinding_Executed(sender As Object, e As ExecutedRoutedEventArgs)
        Me.Close()
        e.Handled = True
    End Sub

    ' el comando siempre se puede ejecutar
    Private Sub CloseCommandBinding_CanExecute(sender As Object, e As CanExecuteRoutedEventArgs)
        e.CanExecute = True
        e.Handled = True
    End Sub

    ' al inicializarse la ventana se marca el semáforo
    Private Sub WindowEsperaSimple_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
        _ZIsClosed = False
    End Sub

    ' al cerrarse la ventana se marca el semáforo
    Private Sub WindowEsperaSimple_Closing(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles Me.Closing
        _ZIsClosed = True
    End Sub

#End Region


#Region "Property necesaria para open / close ventana"

    '   '--------------------------------
    '   ' Apunte táctico
    '   '--------------------------------
    '   ' [ZIsClosed] indica:
    '   ' [True],  la ventana esta cerrada o es nothing  
    '   ' [False], la ventana esta visible
    '   ' la razón de este semáforo, es que cuando se cierra la ventana [CloseVentanaEspera]
    '   ' y se iguala la instancia a [Nothing], realmente no esta [Nothing] 
    '   ' hasta dentro de un rato (cosas del recolector de basura),y cuando se abre,
    '   ' da un error. La forma que se me ha ocurrido de evitarlo es esa, poniendo un semáforo.
    '   ' Un problema parecido ocurre al cerrar la ventana
    '   '--------------------------------
    '   ' se da valor en los eventos del formulario [Closing] y [Initialized]

    ''' <summary>
    '''  Indica si la ventana esta cerrada o no
    ''' </summary>
    ''' <returns>
    '''  [True],  la ventana esta cerrada (o es nothing)
    '''  [False], la ventana esta visible
    ''' </returns>
    ''' <remarks>
    ''' se da valor en los eventos del formulario [Closing] y [Initialized]
    ''' </remarks>
    Friend ReadOnly Property ZIsClosed As Boolean = False

#End Region


#Region "Código [VentanaEspera] para copiar en las clases clientes"

    '    ''' <summary>
    '    '''  variable que contiene el objeto ventana
    '    ''' </summary>
    '    Private WithEvents campoObjWinEspera As WindowEsperaSimple

    '    ''' <summary>
    '    ''' Proceso para abrir la ventana
    '    ''' solo se abre una ventana
    '    ''' </summary>
    '    Public Sub VentanaEsperaAbrir()
    '        ' si la ventana no esta activa
    '        If campoObjWinEspera Is Nothing OrElse
    '           campoObjWinEspera.ZIsClosed = True Then
    '            ' --------------------------------
    '            ' Instanciarla
    '            campoObjWinEspera = New WindowEsperaSimple With {
    '                            .Owner = Me,
    '                            .WindowStartupLocation = WindowStartupLocation.CenterOwner
    '            }
    '            'Mostrar la ventana
    '            campoObjWinEspera.Show()
    '        End If
    '    End Sub

    '    ''' <summary>
    '    ''' Proceso para cerrar la ventana
    '    ''' </summary>
    '    Public Sub VentanaEsperaCerrar()
    '        ' si la ventana no esta cerrada
    '        If Not (campoObjWinEspera Is Nothing) Then
    '            ' cerrar la ventana
    '            campoObjWinEspera.Close()
    '        End If
    '    End Sub

    '    ''' <summary>
    '    '''  Cierre de la ventana de espera
    '    ''' </summary>
    '    Private Sub CloseVentanaEspera()
    '        If Not (campoObjWinEspera Is Nothing) Then
    '            If campoObjWinEspera.ZIsClosed = False Then
    '                ' si cierro un objeto ya cerrado o NULL da error
    '                campoObjWinEspera.Close()
    '            End If
    '            '        '-------
    '            '        ' NOTA
    '            '        ' En el evento [VentanaEspera.Closed] Que esta un poco mas abajo :-)
    '            '        ' se da el valor NULL a la ventana --> campoObjWinEspera = Nothing
    '            '    End If
    '        End If
    '    End Sub


    '    ''' <summary>
    '    '''  Evento que se produce cuando se esta cerrando la venta espera
    '    '''  ' lo que hago es declararla NULL
    '    ''' </summary>
    '    Private Sub VentanaEspera_Closed(sender As Object, e As EventArgs) Handles campoObjWinEspera.Closed
    '        campoObjWinEspera = Nothing
    '    End Sub
#End Region


End Class

↑↑↑

A) Que sea una ventana sin marco

Para quitar el marco solamente hay que poner en la definición de la ventana las siguientes atributos:

        WindowStyle="None"
        AllowsTransparency="True"
        Background="Transparent"
        ShowInTaskbar="False"

↑↑↑

B) Que se pueda cerrar

Podemos usar varias alternativas,


↑↑↑

B1) Definir un botón y en el escuchador de su evento [Clic]

En el evento debe estar la instruccion [Me.Close]. No me molesto en escribirlo, escribir este código es más fácil que la tabla del uno :-))


↑↑↑

B2) Definir un comando Y asignarle un juego de teclas

Por ejemplo [ATL + F4] para que se cierre la ventana. El código necesario es el siguiente:

En la ventana, código Xaml

    <Window.CommandBindings>
        <!-- Menu Archivo -->
        <CommandBinding Command="ApplicationCommands.Close"        
                        Executed="CloseCommandBinding_Executed"        
                        CanExecute="CloseCommandBinding_CanExecute"/>
    </Window.CommandBindings>

    <Window.InputBindings>
        <!-- Menu Archivo -->
        <KeyBinding Command="ApplicationCommands.Close"  Key="F4" Modifiers="Alt"   />
    </Window.InputBindings>

En el código VB

    ' se usa para cerrar la ventana usando el comando, llamándolo con algún botón
    ' en este caso concerto se activa con el juego de teclas [Alt + F4]
    Private Sub CloseCommandBinding_Executed(sender As Object, e As ExecutedRoutedEventArgs)
        Me.Close()
        e.Handled = True
    End Sub

    ' el comando siempre se puede ejecutar
    Private Sub CloseCommandBinding_CanExecute(sender As Object, e As CanExecuteRoutedEventArgs)
        e.CanExecute = True
        e.Handled = True
    End Sub

↑↑↑

B3) Pulsar el botón derecho del ratón para que se cierre la ventana

El código necesario es el siguiente:

En la ventana, código Xaml

        MouseRightButtonDown="Window_MouseRightButtonDown"

En el código VB

    ' se usa para CERRAR la ventana pulsando el botón derecho del ratón
    Private Sub Window_MouseRightButtonDown(sender As Object, e As MouseButtonEventArgs)
        Me.Close()
        e.Handled = True
    End Sub

↑↑↑

C) Que se pueda mover

Para ello pulsaremos el botón izquierdo del ratón y mientras lo mantengamos pulsado la ventana se moverá, para ello hace falta definir el evento [] y su escuchador (lisener) correspondiente []

En la ventana, código Xaml

        MouseDown="Window_MouseDown"

En el código VB

    ' se usa para mover la ventana pulsando el botón izquierdo del ratón
    Private Sub Window_MouseDown(sender As Object, e As MouseButtonEventArgs)
        Me.DragMove()
        e.Handled = True
    End Sub

↑↑↑

D) Que se pueda cambiar su tamaño

En la ventana, código Xaml

        ResizeMode="CanResizeWithGrip">
Ventana con el control Grip

Ventana con el control Grip, que permite el cambio de tamaño

En el código VB

No hace falta escribir código, porque esta instrucción muestra en la parte inferior derecha de e la venta un control [Grip], con toda la funcionalidad de arrastrar la ventana para cambiar su tamaño.

Y eso es todo ( de momento)


↑↑↑

A.2.Enlaces

[Para saber mas]
[Grupo de documentos]
[Documento Index]
[Documento Start]
[Imprimir el Documento]
© 1997 - - La Güeb de Joaquín
Joaquín Medina Serrano
Ésta página es española

Codificación
Fecha de creación 2008-01-28T18:16:07Z
Última actualización
[HTML5 Desarrollado usando CSS3]