Implementación de la técnica Arrastrar y soltar



Descripción general

Visual Basic .NET no permite el empleo automático de arrastrar y soltar. Hay que escribir código que inicie una operación de arrastrar y soltar en el control origen y escribir código apara los eventos contenidos en el control de destino. De hecho, la única propiedad que se encuentra relacionada con arrastrar y soltar AllowDrop se debe definir como True para que un control desencadene eventos cuando trabaje como destino de una operación de arrastrar y soltar.

[TOC] Tabla de Contenidos


↑↑↑

El control de Origen

Normalmente, se entenderá que el usuario pretende iniciar una operación de arrastrar y soltar cuando el ratón abandone un control pero, a la vez, mantenga pulsado uno de los botones del ratón. En estos casos, tenemos que crear una nueva instancia de DataObject y rellenarla con los datos contenidos en el control origen (este paso es idéntico a lo que hace cuando copia datos en el Portapapeles e incluye la posibilidad de almacenar los datos en varios formatos).

En el paso siguiente es definir qué efectos de la técnica «arrastrar y soltar» deseas permitir a los usuarios. Para ello, utilizaremos el valor DragDropEffects expresado en bits (los efectos permitidos son: Copy, Move, Scroll, Link y All) y pasaremos este valor y el objeto DataObject al método DoDragDrop del control, que iniciará realmente la operación de arrastrar y soltar. El método DoDragDrop es síncrono y no regresa del mismo hasta que no haya finalizado la operación de arrastrar y soltar (o que haya sido cancelada). El valor devuelto por este método es otro valor DragDropEffect que es el que comunica qué efecto ha sido elegido por el usuario (copiar, mover o desplazar) o será None si la operación ha sido cancelada; si el efecto seleccionado es Move, deberás eliminar los datos seleccionados del control origen.


↑↑↑

Evento MouseMove

'----------------------------------------------------------------------
'Código para que un control actúe como ORIGEN de un Drag And Drop
'----------------------------------------------------------------------
'----------------------------------------------------------------------
' Evento MouseMove
'----------------------------------------------------------------------
Private Sub FormMain_MouseMove( _
           ByVal sender As Object, _
           ByVal e As System.Windows.Forms.MouseEventArgs) _
           Handles TextBoxUno.MouseMove, TextBoxDos.MouseMove

    ' salir si no se ha pulsado ningún botón
    If e.Button = 0 Then Exit Sub

    '-----------------
    ' recuperar el objeto ORIGEN del movimiento
    ' También se puede utilizar la referencia directa o su nombre
    ' Ejemplo=  Dim txtBoxOrigen As TextBox = TextBoxDos
    '-----------------
    Dim textBoxORIGEN As TextBox = CType(sender, TextBox)

    ' si no hay nada en el control no se puede arrastra nada --> salir
    If textBoxORIGEN.Text.Length = 0 Then Exit Sub

    'Salir si el cursor se encuentra dentro del borde del control
    If e.X >= 0 And e.X < textBoxORIGEN.Width And e.Y >= 0 And e.Y < textBoxORIGEN.Height Then Exit Sub

    ' almacenar todo el texto seleccionado o todo el texto si no hay sleceeikon
    Dim data As New DataObject
    If textBoxORIGEN.SelectionLength > 0 Then
        data.SetData(DataFormats.Text, textBoxORIGEN.SelectedText)
    Else
        data.SetData(DataFormats.Text, textBoxORIGEN.Text)
    End If

    '-----------------------------------------
    ' iniciar la operación de arrastre
    ' El método DoDragDrop es  síncrono y no regresa del mismo hasta que no 
    ' haya finalizado la operación de arrastrar y soltar (o que haya sido cancelada). 
    ' El valor devuelto por este método es otro valor DragDropEffect que 
    ' es el que comunica que efecto ha sido elegido por el usuario 
    ' (copiar mover o desplazar) o será None si la operación ha sido cancelada. 
    ' Si el efecto es Move, deberá eliminar los datos seleccionad del control origen
    '-----------------------------------------
    Dim effect As DragDropEffects = DragDropEffects.Copy Or DragDropEffects.Move
    effect = textBoxORIGEN.DoDragDrop(data, effect)

    ' Borrar el texto si es una operacion de desplazamiento
    If effect = DragDropEffects.Move Then
        If textBoxORIGEN.SelectionLength > 0 Then
            textBoxORIGEN.SelectedText = String.Empty
        Else
            textBoxORIGEN.Clear()
        End If
    End If
End Sub


↑↑↑

El control de Destino

Veamos ahora el código para obtener un control que actúe como destino de la operación de arrastrar y soltar. Los controles que puedan ejercer las labores de destino de la operación de arrastrar y soltar pueden recibir cuatro eventos : DragEnter (el ratón está entrando en el área cliente del control), DragOver (el ratón se está moviendo dentro del control), DragLeave (el ratón está abandonando el control) y DragDrop (el botón del ratón se ha liberado sobre el control). Recuerda que debes configurar la propiedad AllowDrop del control destino como True; en caso contrario, no se desencadenará nunca ninguno de estos eventos .

Los eventos DragEnter, DragOver y DragDrop reciben un objeto DragEventArgs como segundo argumento. Podemos conocer con él los detalles relacionados con la operación de arrastrar y soltar que se esté realizando sin más que consultar sus propiedades de sólo lectura: AllowedEffect (un valor expresado en bits que especifica qué acciones se encuentran disponibles), Data (la instancia DataObject que contienen los datos), KeyState (el estado de las teclas Mayús, Ctrl y Alt y de los botones del ratón) y X e Y (la posición del cursor en coordenadas clientes). La propiedad KeyState expresada en bits no se corresponden con cualquier valor enumerado, por lo que deberá utilizar constantes numéricas: 1 (botón izquierdo), 2 (botón derecho), 4 (tecla Mayús), 8 (tecla Ctrl), 16 (botón central) y 32 (tecla Alt).

La única propiedad que se puede rescribir es Effect, a la que podrá asignar un valor que refleje qué operaciones va a aceptar el control destino. El evento DragEnter, comprobará el formato de los datos que se están arrastrando, los efectos disponibles y el estado de las teclas y de los botones del ratón. Para aceptar la operación de arrastrar y soltar, hay que asignar un valor distinto a None a la propiedad Effect. El siguiente procedimiento muestra la forma en que podrá implementar un controlador de eventos DragEnter que funcione correctamente con un control TextBox


↑↑↑

Evento DragEnter

'----------------------------------------------------------------------
' Evento DragEnter
'----------------------------------------------------------------------
Private Sub Form1_DragEnter( _
         ByVal sender As Object, ByVal e As DragEventArgs) _
         Handles TextBoxUno.DragEnter, TextBoxDos.DragEnter

    ' Drag & Drop, comprobar con DataFormats
    If e.Data.GetDataPresent(DataFormats.FileDrop) Then
        e.Effect = DragDropEffects.Copy
    End If

    ' If the Ctrl key was pressed during the drag operation then perform
    ' a Copy. If not, perform a Move.
    If (e.Data.GetDataPresent(DataFormats.Text)) Then
        Select Case e.KeyState
            Case 1
                'No key pressed
                e.Effect = e.AllowedEffect And DragDropEffects.Move
            Case 9
                'CONTROL key pressed
                e.Effect = e.AllowedEffect And DragDropEffects.Copy
            Case Else
                e.Effect = DragDropEffects.None
        End Select
    End If
End Sub

También podemos utilizar el evento DragEnter para cambiar el aspecto del control destino (por ejemplo, dibujando un borde especial a su alrededor o modificando su color de fondo). Observa que si realizas alguna de esas operaciones ( cambio de color, etc) hay que restaurar el aspecto original en los controladores de eventos DragLeave y DragDrop.

Cuando el ratón se esté moviendo dentro del área cliente del control destino, recibirá eventos DragOver, pero sólo necesitará atrapar este evento si desea proporcionar distintos efectos de arrastrar y soltar (o desactivar completamente la operación de arrastrar y soltar) para cada una de las áreas que existan en el control.

El evento DragDrop es donde se escribe el código que administre el procesamiento real de los datos. Como vemos en el ejemplo siguiente, obtener los datos que se están soltando resulta similar a efectuar una operación de pegado:


↑↑↑

Evento DragDrop

'----------------------------------------------------------------------
' Evento DragDrop
'----------------------------------------------------------------------
Private Sub Form1_DragDrop( _
            ByVal sender As Object, _
            ByVal e As DragEventArgs) _
            Handles TextBoxUno.DragDrop, TextBoxDos.DragDrop

    ' recuperar el objeto DESTINO del movimiento
    ' Tambien se puede utilizar la referencia directa o su nombre
    ' Ejemplo: Dim textBoxDESTINO As TextBox = TextBoxUno
    Dim textBoxDESTINO As TextBox = CType(sender, TextBox)

    '----------------------------------------------------
    ' Arrastar un nombre de fichero de una ventana de windows
    '----------------------------------------------------
    'If e.Data.GetDataPresent("FileDrop") Then
    If e.Data.GetDataPresent(DataFormats.FileDrop) Then
        ' http://www.elguille.info/NET/vs2005/como/ejecutar_acceso_directo.aspx
        '------------------------------------------------------------------------

        '------------------------------------------------------
        ' PARTE UNO - Este codigo genera el nombre completo del fichero
        '             y lo muestra en el control TextBox
        '             Ejemplo c:\uno\dos\tres\fichero.jpg
        '------------------------------------------------------
        ' Efecto Visual del cursor (en este caso no se permite el mover)
        e.Effect = DragDropEffects.Copy

        Dim nombreCompletoFichero As String = String.Empty
        nombreCompletoFichero = CType(e.Data.GetData(DataFormats.FileDrop, True), String())(0)
        'TextBoxNombreFichero.Text = CType(e.Data.GetData("FileDrop", True), String())(0)
        textBoxDESTINO.Text = nombreCompletoFichero

        ''------------------------------------------------------
        '' PARTE DOS - Este codigo abre el fichero, lo lee y muestra 
        ''             su contendio en un TextBox llamado TextBoxContenido
        ''------------------------------------------------------
        'Dim sr As System.IO.StreamReader
        'Try
        '    sr = New System.IO.StreamReader(nombreCompletoFichero, System.Text.Encoding.Default)
        '    TextBoxContenido.Text = sr.ReadToEnd()
        '    sr.Close()
        '    'Cursor al final
        '    TextBoxContenido.SelectionStart = TextBoxContenido.Text.Length
        '    TextBoxContenido.ScrollToCaret()
        'Catch ex As Exception
        '    TextBoxContenido.Text = "Error al abrir el fichero:" & Environment.NewLine & ex.Message
        'End Try

    End If


    '----------------------------------------------------
    ' Arrastar un texto de un textBox
    '----------------------------------------------------
    If (e.Data.GetDataPresent(DataFormats.Text, True)) Then

        ' Efecto Visual del cursor
        ' Decidir si es una copia o un desplazamiento
        If CType((e.KeyState And 9), Boolean) Then
            e.Effect = DragDropEffects.Copy
        Else
            e.Effect = DragDropEffects.Move
        End If

        ' pegar el texto
        textBoxDESTINO.Text = e.Data.GetData(DataFormats.Text).ToString
    End If

End Sub


↑↑↑

Evento QueryContinueDrag

El evento QueryContinueDrag se recibe porel control origen cuando la operación de arrastrar y soltar se esté realizando. Este evento recibe un objeto QueryContinueDragEventArgs, que expone las propiedades KeyState, EscapePressed y Action. El código deberá comprobar las teclas pulsadas y si el usuario ha pulsado la tecla Esc. También deberá asignar uno de los siguientes valores enumerados de DragAction a la propiedad Action: Continue (valor predeterminado), Drop o Cancel. Veamos una implementación típica de este evento:

'----------------------------------------------------------------------
' Evento QueryContinueDrag
'----------------------------------------------------------------------
Private Sub FormMain_QueryContinueDrag( _
           ByVal sender As Object, _
           ByVal e As System.Windows.Forms.QueryContinueDragEventArgs) _
           Handles TextBoxUno.QueryContinueDrag, TextBoxDos.QueryContinueDrag

    If e.EscapePressed Then e.Action = DragAction.Cancel
End Sub

↑↑↑

A.2.Enlaces

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