Visual Basic em Português

Página pessoal de Jorge Paulino sobre o Visual Basic (VB.NET, ASP.NET, VB6, VBA) e algumas noticias de tecnologia

VB.NET: Dicas de Programação #8

Movimentação de Controlos em Run-Time

Quando é necessário movimentar controlos com o rato, existem diferentes códigos que necessitam de cálculos, variáveis, etc, de modo a arrastar o controlo de um lugar para o outro, enquanto o botão do rato estiver pressionado.

Se é verdade que não é muito utilizado é verdade que quando é preciso não é um processo muito simples de fazer (pelo menos dá algum trabalho).

A forma mais simples de o fazer (que eu tenha conhecimento) é utilizando o método DefWndProc() que permite enviar mensagens para o sistema. É uma utilização de subclasses que irá fazer o mesmo que o Windows faz quando o utilizador pressiona o rato na barra de título e arrasta-o.

Ora isto permite simplificar uma série de coisas como arrastar um controlo (como por exemplo uma Label ou TextBox) ou mesmo o próprio Form. No caso do Form, e quando este não tem barra de titulo, dá imenso jeito.

Dois exemplos para uma TextBox e o Form

    ' Constantes com a indicação de que o utilizador pressiona 
    ' o botão esquerdo do rato e da barra de titulo do Form
    Const WM_NCLBUTTONDOWN As Integer = &HA1
    Const HTCAPTION As Integer = 2

    ' Movimentação da TextBox no Form
    Private Sub TextBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseDown

        ' Caso esteja a ser pressionado o botão esquerdo
        If e.Button = Windows.Forms.MouseButtons.Left Then

            ' Liberta a captura do rato. Esta captura vai a True
            ' quando o rato é pressionado, e impede a movimentação
            TextBox1.Capture = False

            ' Envia uma mensagem que irá movimentar o controlo
            Dim msg As Message = _ 
                  Message.Create(TextBox1.Handle, WM_NCLBUTTONDOWN, _
                           
New IntPtr(HTCAPTION), IntPtr.Zero)
            Me.DefWndProc(msg)
        End If

    End Sub

   

    ' Movimentação do From (sem comentários uma vez que é igual ao anterior)
    Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown

        If e.Button = Windows.Forms.MouseButtons.Left Then
            Me.Capture = False
            Dim msg As Message = _
                       Message.Create(Me.Handle, WM_NCLBUTTONDOWN, _
 
                    New IntPtr(HTCAPTION), IntPtr.Zero)
            Me.DefWndProc(msg)
        End If

    End Sub


É possível ainda utilizar outras constantes para fazer outras acções, como por exemplo utilizando a HTBOTTOMRIGHT (Const HTBOTTOMRIGHT As Integer = 17) em vez da HTCAPTION, que irá efectuar o resize do Form. A constante HTBOTTOMRIGHT é a indicação de que o utilizador está a fazer o redimencionamento do Form no canto inferior direito.





Manter posição da DataGridView após ordenação

A DataGridView permite ordenar os seus dados de uma forma automática, bastando para isso clicar nos cabeçalhos das colunas. É sem dúvida muito prático e sem recorrer a qualquer código (por parte do utilizador). O que não é prático é que a lista perde a selecção após ordenação, ou seja, após a lista ser ordenada pela coluna X, a selecção actual perde-se.

Para resolver este problema pode-se criar uma walkaround onde é guardado um identificador único da lista (no exemplo um ID) e a índex da coluna. Desta forma é possível ordenar a lista e manter a selecção actual.

    ' Variável que irá guardar a informação do ID seleccionado
    Private currentRowID As Integer

    ' Variável que irá guardar a informação da coluna seleccionada
    Private currentCellIndex As Integer

   

    ''' <summary>
    ''' Pesquisa na lista pelo ID e retorna o index da linha encontrada
    ''' </summary>
    ''' <param name="ID">Número único da lista (ID)</param>
    Function getDGindex(ByVal ID As Integer) As Integer
        Dim dr As DataGridViewRow

        For Each dr In DataGridView1.Rows
            If CType(dr.Cells(0).Value, Integer) = ID Then
                Return dr.Index
            End If
        Next

    End Function

    ' No arranque do form carrega alguns dados para o exemplo
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        ' Criação de uma nova datatable que 
        ' irá servir para preencher a DataGridView
        Dim dt As New DataTable

        ' Criação de algumas colunas
        dt.Columns.Add("ID", GetType(Byte))
        dt.Columns.Add("Description", GetType(String))
        dt.Columns.Add("Random", GetType(Integer))

        ' Criação de um número aleatório
        Dim rnd As New Random
        Dim dr As DataRow   

        ' Insere registos na DataTable
        For x As Byte = 0 To 100
            dr = dt.NewRow
            dr("ID") = x
            dr("Description") = "Item " & x.ToString.PadLeft(3, "0"c)
            dr("Random") = rnd.Next(0, 1000)
            dt.Rows.Add(dr)
        Next

        ' Associa a DataTable à source da DataGridView
        Me.DataGridView1.DataSource = dt

    End Sub

    ' No evento RowLeave guarda o ID e índice da coluna
    Private Sub DataGridView1_RowLeave(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.RowLeave

        If e.RowIndex <> -1 And Not _
                               Me.DataGridView1.Rows(e.RowIndex).IsNewRow Then

           
currentRowID = Me.DataGridView1(0, e.RowIndex).Value
            currentCellIndex = e.ColumnIndex
        End If

    End Sub

   

    ' Após a ordenação verifica a posição anterior e selecciona-a
    Private Sub DataGridView1_Sorted(ByVal sender As Object, ByVal e As System.EventArgs) Handles DataGridView1.Sorted

        Dim index As Integer = getDGindex(currentRowID)

        Me.DataGridView1.CurrentCell = _
                              Me.DataGridView1.Rows(index).Cells(currentCellIndex)

    End Sub

PS: Como sempre, qualquer dúvida, comentário ou correcção ao artigo é sempre bem vinda!

1 comentários:

ze21038 disse...

muito bom, parabéns.



Microsoft Office Especialist

Membro da Comunidade
Experts-Exchange


Administ. da Comunidade
Portugal-a-Programar



Twitter

Artigos no CodeProject

Artigos no CodeProject
Google-Translate-ChineseGoogle-Translate-Portuguese to FrenchGoogle-Translate-Portuguese to GermanGoogle-Translate-Portuguese to ItalianGoogle-Translate-Portuguese to JapaneseGoogle-Translate-Portuguese to EnglishGoogle-Translate-Portuguese to RussianGoogle-Translate-Portuguese to Spanish

Subscrever Novidades

Endereço de Email:

Delivered by FeedBurner

Seguidores

Histórico