Índice de la sección dedicada a .NET (en el Guille) Cómo... en .NET

Mover un formulario sin barra de títulos
(incluso pulsando en cualquier control)

Código para Visual Basic.NET (VB.NET)

Código para C Sharp (C#)


Publicado el 07/Ene/2005
Actualizado el 07/Ene/2005
Autor: Guillermo 'guille' Som


Este truco nos servirá para mover un formulario al pulsar en cualquier parte del mismo, incluso en cualquier control que tenga dicho formulario.

El hecho de que el formulario tenga o no barra de títulos no es algo relevante, ya que lo que aquí te muestro (como siempre para VB y C#) funciona indistintamente de que el formulario tenga o no borde o barra de títulos, lo que que ocurre es que es más "evidente" usar este tipo de código cuando el formulario no tiene dónde "agarrarse".

 

 

El truco o el método que utilizaré aquí es el que hace años te mostré para el VB clásico y que recientemente publiqué para el Windows XP. En dicho código usamos la función SendMessage del API de Windows para "ordenarle" al formulario de que se mueva, esa orden se la daremos normalmente cuando movamos el ratón mientras mantenemos pulsado el botón izquierdo del mismo, aunque el código lo podemos usar cuando nos apetezca, pero básicamente es más obvio en esas circunstancias.

La declaración de las funciones del API se pueden hacer al estilo "clásico" de VB6, cambiando los tipos de datos, pero debido a que te mostraré también cómo hacerlo en C#, lo más lógico es hacer dichas declaraciones al estilo de .NET, incluso podemos declararlas como Sub (void en C#), ya que realmente el valor devuelto por las funciones no los tendremos en cuenta.
Aquí tienes las declaraciones de las constantes y las funciones del API para VB, (para C# las puedes ver más abajo).

Private Const WM_SYSCOMMAND As Integer = &H112&
Private Const MOUSE_MOVE As Integer = &HF012&
'
' Declaraciones del API al estilo .NET
<System.Runtime.InteropServices.DllImport("user32.DLL", EntryPoint:="ReleaseCapture")> _
Private Shared Sub ReleaseCapture()
End Sub
'
<System.Runtime.InteropServices.DllImport("user32.DLL", EntryPoint:="SendMessage")> _
Private Shared Sub SendMessage( _
        ByVal hWnd As System.IntPtr, ByVal wMsg As Integer, _
        ByVal wParam As Integer, ByVal lParam As Integer _
        )
End Sub

Para utilizar estas funciones del API, he creado un método al que llamaremos cada vez que queramos que el formulario se mueva.

' función privada usada para mover el formulario actual
Private Sub moverForm()
    ReleaseCapture()
    SendMessage(Me.Handle, WM_SYSCOMMAND, MOUSE_MOVE, 0)
End Sub

Este método normalmente lo llamaremos desde el evento MouseMove del control que queramos usar para mover el formulario.

' podemos usar el mismo procedimiento de evento para mover
Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
                Handles MyBase.MouseMove, Label1.MouseMove, GroupBox1.MouseMove, PictureBox1.MouseMove
    If e.Button = MouseButtons.Left Then
        moverForm()
    End If
End Sub

 

Aquí tienes una captura del formulario en tiempo de diseño, en el que he añadido un Label, un PictureBox y un GroupBox, los cuales podremos usar para mover el formulario, además de pulsando en el propio formulario.


El formulario en tiempo de diseño

 

Y esto es todo... como ves nada del otro mundo..., una vez que se sabe cómo hacerlo.

Aquí tienes el ZIP con el código completo tanto para VB como C#:
MoverFormularioSinCaption.zip 26.7 KB

 

Nos vemos.
Guillermo


Código para Visual Basic.NET (VB.NET)El código para VB .NET

 

'------------------------------------------------------------------------------
' Prueba de mover un formulario sin barra de textos (ni bordes)     (07/Ene/05)
' Usando API de Windows
'
' ©Guillermo 'guille' Som, 2005
'------------------------------------------------------------------------------
Imports System
Imports System.Windows.Forms

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Código generado por el Diseñador de Windows Forms "
    ' ... código del diseñador de Windows (no mostrado)
#End Region
    '
    ' Declaraciones del API de Windows (y constantes usadas para mover el form)
    '
    Private Const WM_SYSCOMMAND As Integer = &H112&
    Private Const MOUSE_MOVE As Integer = &HF012&
    '
    '' Declaraciones "clásicas" de VB6
    'Private Declare Function ReleaseCapture Lib "user32" () As Integer
    'Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
    '        (ByVal hWnd As System.IntPtr, ByVal wMsg As Integer, _
    '        ByVal wParam As Integer, ByVal lParam As Integer) As Integer
    '
    ' Declaraciones del API al estilo .NET
    <System.Runtime.InteropServices.DllImport("user32.DLL", EntryPoint:="ReleaseCapture")> _
    Private Shared Sub ReleaseCapture()
    End Sub
    '
    <System.Runtime.InteropServices.DllImport("user32.DLL", EntryPoint:="SendMessage")> _
    Private Shared Sub SendMessage( _
            ByVal hWnd As System.IntPtr, ByVal wMsg As Integer, _
            ByVal wParam As Integer, ByVal lParam As Integer _
            )
    End Sub
    '
    ' función privada usada para mover el formulario actual
    Private Sub moverForm()
        ReleaseCapture()
        SendMessage(Me.Handle, WM_SYSCOMMAND, MOUSE_MOVE, 0)
    End Sub
    '
    Private Sub btnCerrar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCerrar.Click
        Me.Close()
    End Sub
    '
    ' podemos usar el mismo procedimiento de evento para mover
    Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
                    Handles MyBase.MouseMove, Label1.MouseMove, GroupBox1.MouseMove, PictureBox1.MouseMove
        If e.Button = MouseButtons.Left Then
            moverForm()
        End If
    End Sub
End Class

 


Código para C Sharp (C#)El código para C#

 

//-----------------------------------------------------------------------------
// Prueba de mover un formulario sin barra de textos (ni bordes)    (07/Ene/05)
// Usando API de Windows
//
// ©Guillermo 'guille' Som, 2005
//-----------------------------------------------------------------------------
using System;
using System.Windows.Forms;

public class Form1 : System.Windows.Forms.Form
{
    public Form1()
    {
        //
        // Necesario para admitir el Diseñador de Windows Forms
        //
        InitializeComponent();

        //
        // TODO: agregar código de constructor después de llamar a InitializeComponent
        //
        // Estas "asignaciones" suelen estar en el cuerpo del código oculto
        // del diseñador de Windows, pero lo pongo fuera para que se vea
        // que realmente capturamos todo el código en la misma función
        this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseMove);
        this.Label1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseMove);
        this.PictureBox1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseMove);
        //
        // La "captura" del evento MouseMove del GroupBox
        // no aparece en la lista del diseñador de formularios de C#
        this.GroupBox1.MouseMove += new MouseEventHandler(Form1_MouseMove);
    }
    //
    #region Código generado por el Diseñador de Windows Forms
    // Código del diseñador de formularios (no mostrado)
    #endregion
    //
    /// <summary>
    /// Punto de entrada principal de la aplicación.
    /// </summary>
    [STAThread]
    static void Main() 
    {
        Application.Run(new Form1());
    }
    //
    // Declaraciones del API de Windows (y constantes usadas para mover el form)
    //
    const int WM_SYSCOMMAND = 0x112;
    const int MOUSE_MOVE = 0xF012;
    //
    // Declaraciones del API
    [System.Runtime.InteropServices.DllImport("user32.DLL", EntryPoint="ReleaseCapture")]
    private extern static void ReleaseCapture();
    //
    [System.Runtime.InteropServices.DllImport("user32.DLL", EntryPoint="SendMessage")]
    private extern static void SendMessage(System.IntPtr hWnd, int wMsg, int wParam, int lParam);
    //
    // función privada usada para mover el formulario actual
    private void moverForm() 
    {
        ReleaseCapture();
        SendMessage(this.Handle, WM_SYSCOMMAND, MOUSE_MOVE, 0);
    }  
    //
    //
    private void btnCerrar_Click(object sender, System.EventArgs e)
    {
        this.Close();
    }
    // podemos usar el mismo procedimiento de evento para mover
    private void Form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
    {
        moverForm();
    }
}

 


la Luna del Guille o... el Guille que está en la Luna... tanto monta...