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 #4

DataGridView – Sequência de Movimento (Após tecla ENTER)

 

A DataGridView tem como movimento após a tecla ENTER, de linha em linha, e não de coluna em coluna. Quando se está a preencher registos, em que se preenche um registo de cada vez, é prático que o utilizador após pressionar a tecla ENTER desloque a selecção para a coluna seguinte e não para o próximo registo (próxima linha).

 

Para conseguirmos alterar este comportamento podemos, no evento KeyDown, verificar qual a tecla pressionada e alterá-la. No entanto, e se a célula estiver a ser editada, é necessário fazer o override à ProcessCmdKey.

 

Fica um exemplo de como fazer:

 

 Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean

 

    ' Verifica se a tecla pressionada foi a ENTER e se a célula está a ser editada

    If keyData = Keys.Enter And Me.DataGridView1.IsCurrentCellInEditMode Then

 

      ' Executa um TAB

      SendKeys.Send("{TAB}")

      ' Ignora a tecla pressionada

      Return True

 

    Else

      ' Executa o processo normal

      Return MyBase.ProcessCmdKey(msg, keyData)

    End If

 

  End Function

 

 

  ' Quando é pressionada uma tecla

  Private Sub DataGridView1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles DataGridView1.KeyDown

 

    ' Verifica se a tecla é a ENTER

    If e.KeyCode = Keys.Enter Then

 

      ' Desabilita a tecla pressionada

      e.SuppressKeyPress = True

 

      With Me.DataGridView1

 

        ' Caso seja a ultima coluna salta para a primeira da próxima linha

        If .CurrentCell.ColumnIndex = .ColumnCount - 1 Then

 

          ' Caso não seja a última linha

          If .CurrentRow.Index < .RowCount - 1 Then

            .CurrentCell = .Item(0, .CurrentRow.Index + 1)

          End If

 

        Else

          ' Move para a próxima coluna

          .CurrentCell = .Item(.CurrentCell.ColumnIndex + 1, .CurrentRow.Index)

        End If

 

      End With

    End If

 

  End Sub

 

 

@@IDENTITY – Verificando Registo Inserido

 

Quando se inserem registos, é frequente necessitarmos do último número de identificação inserido (ID) para mostrarmos ao utilizador ou para utilizarmos na inserção de outros registos. Por exemplo se inserirmos um novo utilizador e de seguida usarmos o seu número de registo para inserir a sua lista de favoritos, temos de efectuar os seguintes passos:

 

1 – Inserir o registo do utilizador

2 – Verificar-mos qual o registo inserido (ID)

3 – Inserir os favoritos utilizando o ID recolhido

 

Para simplificar este processo podemos utilizar o comando T-SQL - @@IDENTITY - que retorna o valor gerado pelo SQL Statement. Ou seja, no momento que inserimos o registo, verificamos qual o número do registo inserido.

 

Fica aqui um exemplo de como simplificar este processo:

 

    ' Texto de ligação à base de dados

    Dim myConnectionString As String = _

        "Data Source=.\SQLEXPRESS;AttachDbFilename='c:\MYDATABASE.MDF';" & _

        ";Integrated Security=True;User Instance=True"

 

    ' Comando que irá inserir dados na tabela "MyTable" em que o campo "username" será

    ' passados através de parâmetros e retornará o ID do registo inserido

    Dim SQL As String = "INSERT INTO myTable([username]) VALUES (@username); Select @@IDENTITY;"

 

    ' Cria uma nova ligação à base de dados

    Dim connection As New SqlConnection(myConnectionString)

 

    ' Criação do comando indicando a instrução e a ligação

    Dim command As New SqlCommand(SQL, connection)

    command.Parameters.Add("@username", SqlDbType.VarChar).Value = "teste"

    connection.Open()

 

    ' Insere o registo e guarda na variável IdRegistoInserido o ID

    Dim IdRegistoInserido As Integer = command.ExecuteScalar()

    Debug.WriteLine("Registo Inserido: " + IdRegistoInserido.ToString)

 

    ' Fecha a ligação e limpa as variáveis

    connection.Close()

    connection = Nothing

    command = Nothing

 

 

Deste modo reduzimos um processo, de verificação do registo inserido, melhorando a performace da aplicação.

 

 

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


VB6: Posicionamento e Redimensionamento de Controlos

O VB.NET tem uma  propriedade nos controlos que permite-os redimensionar e posicionar no formulário através da opção Anchor. Este ancoramento permite que um controlo aumente/diminua ou desloque-se quando o formulário é redimensionado, melhorando bastante esteticamente e funcionalmente a aplicação.

O Visual Basic 6 não tem esta possibilidade de uma forma automática sendo necessário recorrer a cálculos para o fazer. Uma das opções mais comuns que os programadores utilizam para ultrapassar este processo demorado e normalmente complexo é retirar a possibilidade de aumentar o tamanho do formulário. Mas isto não é algo que o utilizador esteja habituado em ambiente Windows nem é algo que traga valor acrescentado à aplicação.

Uma das hipóteses que resolve este problema é utilizando as classes clsAutoPositioner.cls e clsAutoPositionerItem.cls. Estas classes são de código livre, encontram-se disponíveis na Internet e permitem efectuar com grande facilidade este processo. Podem ver o exemplo inicial (Figura 1) e o resultado final (Figura 2) .

 
   (Figura 1)



    (Figura 2)

Para as utilizarem é necessário criar duas classes com o seguinte código:

clsAutoPositioner.cls

‘ ***
‘ *** Início da classe clsAutoPositioner
‘ ***
Option Explicit

Dim m_oAssignments As New Collection

Public Function AddAssignment(ctl As Object, ctlRelative As Object, tPosType As tPOSITION_TYPE)

Dim x As New clsAutoPositionerItem
Set x.oCTL = ctl
Set x.oREL = ctlRelative
x.tPosType = tPosType

Select Case x.tPosType
    Case tCONTAINER_RELATIVE_POS_RIGHT
            x.lValue = x.oREL.Width - x.oCTL.Left
    Case tCONTAINER_RELATIVE_POS_BOTTOM
            x.lValue = x.oREL.Height - x.oCTL.Top
    Case tCONTAINER_WIDTH_DELTA_RIGHT
            x.lValue = x.oREL.Width - (x.oCTL.Left + x.oCTL.Width)
    Case tCONTAINER_HEIGHT_DELTA_BOTTOM
            x.lValue = x.oREL.Height - (x.oCTL.Top + x.oCTL.Height)
    Case tCONTROL_RELATIVE_SAME_POS_VERTICAL
            x.lValue = x.oCTL.Left - x.oREL.Left
    Case tCONTROL_RELATIVE_SAME_POS_HORIZONTAL
            x.lValue = x.oCTL.Top - x.oREL.Top
End Select

m_oAssignments.Add x

End Function

     

Public Function RefreshPositions()
Dim i As Long
Dim x As clsAutoPositionerItem
Dim erg As Long

For i = 1 To m_oAssignments.Count
    Set x = m_oAssignments.Item(i)

    Select Case x.tPosType
        Case tCONTAINER_RELATIVE_POS_RIGHT
            erg = x.oREL.Width - x.lValue
            If (erg > 0) Then x.oCTL.Left = erg
        Case tCONTAINER_RELATIVE_POS_BOTTOM
            erg = x.oREL.Height - x.lValue
            If (erg > 0) Then x.oCTL.Top = erg
        Case tCONTAINER_WIDTH_DELTA_RIGHT
            erg = x.oREL.Width - x.oCTL.Left - x.lValue
            If (erg > 0) Then x.oCTL.Width = erg
        Case tCONTAINER_HEIGHT_DELTA_BOTTOM
            erg = x.oREL.Height - x.oCTL.Top - x.lValue
            If (erg > 0) Then
                x.oCTL.Height = erg
            Else
                erg = erg
            End If           

        Case tCONTROL_RELATIVE_SAME_POS_VERTICAL
            erg = x.oREL.Left + x.lValue
            x.oCTL.Left = erg
        Case tCONTROL_RELATIVE_SAME_POS_HORIZONTAL
            erg = x.oREL.Top + x.lValue
            x.oCTL.Top = erg
    End Select
Next

End Function     

clsAutoPositionerItem.cls

‘ ***
‘ *** Início da classe clsAutoPositionerItem
‘ ***
Public Enum tPOSITION_TYPE
    tCONTAINER_RELATIVE_POS_RIGHT
    tCONTAINER_RELATIVE_POS_BOTTOM
    tCONTAINER_WIDTH_DELTA_RIGHT
    tCONTAINER_HEIGHT_DELTA_BOTTOM
    tCONTROL_RELATIVE_SAME_POS_VERTICAL
    tCONTROL_RELATIVE_SAME_POS_HORIZONTAL
End Enum

Public oCTL As Object
Public <?xml namespace="" ns="urn:schemas-microsoft-com:office:smarttags" prefix="st1" ?>oRELAs Object
Public tPosType As tPOSITION_TYPE
Public lValue As tPOSITION_TYPE



Para as implementar, e após a criação destas classes num projecto, deverão utilizar o seguinte código (com as adaptações necessárias):

‘ Declaração de uma variável a nível do form privada
Private m_oAutoPos As New clsAutoPositioner     

‘ No evento load do form define-se quais os controlos e que são afectados
‘ e que acção é efectuada (posicionamento e/ou redimensionamento)
Private Sub Form_Load()

  With m_oAutoPos
  ‘ posição relativo à direita
  .AddAssignment Me.Command1, Me, tCONTAINER_RELATIVE_POS_RIGHT

   ' Redimensionamento horizontal
  .AddAssignment Me.Command2, Me, tCONTAINER_WIDTH_DELTA_RIGHT

  ‘ Redimensionamento vertical
 .AddAssignment Me.Command3, Me, tCONTAINER_HEIGHT_DELTA_BOTTOM

 ' Posição relativo em baixo
.AddAssignment Me.Command4, Me, tCONTAINER_RELATIVE_POS_BOTTOM

   ' Redimensionamento horizontal e vertical
 .AddAssignment Me.Command5, Me, tCONTAINER_WIDTH_DELTA_RIGHT
 .AddAssignment Me.Command5, Me, tCONTAINER_HEIGHT_DELTA_BOTTOM
 End With

End Sub

‘ Quando é alterado o tamanho do form
Private Sub Form_Resize()
    m_oAutoPos.RefreshPositions
End Sub

‘ Limpa da memória a variável
Private Sub Form_Unload(Cancel As Integer)
    Set m_oAutoPos = Nothing
End Sub

Estas classes e este processo permitem melhorar a aplicação e dar ao utilizador algo que normalmente está habituado em ambiente Windows. É verdade que no VB.NET esta funcionalidade está disponível através de uma das propriedades dos controlos, mas no VB6, e com poucas linhas de código, pode-se também implementar.


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


VB.NET: Personalizando o CrystalReportViewer

Os relatórios são parte importante de uma aplicação e a utilização dos Crystal Reports, disponíveis na maioria nas versões do Visual Studio 2005, ajuda muito neste processo. É uma ferramenta poderosa, embora com diversas limitações na versão .NET, mas mesmo assim com inúmeras possibilidades e simplicidade de utilização.

O CystalReportViewer é uma ferramenta do Crystal Report que permite pré-visualizar o relatório antes de ser impresso ou exportado para diversos formatos disponíveis, como é o caso de *.pdf, *.xls, *.doc, etc. No entanto o CystalReportViewer é totalmente em Inglês e não existe a possibilidade de modifica-lo em design mode ou modo de edição.

O CystalReportViewer é composto pelos seguintes componentes:

     ReportGroupTree – Árvore de relatórios
     PageView – Onde se encontra o relatório
     Splitter – Divisão entre o PageView e ReportGroupTree
     StatusBar – Barra onde são mostradas algumas informações sobre o relatório
     ToolStrip – Barra de Ferramentas onde se encontram os botões

alt

Em modo runtime ou quando o programa está a executar, é possível personalizar grande parte dos componentes do CystalReportViewer. Ficam aqui alguns exemplos de personalizações possíveis, mostrando um pouco o que se pode e como se pode modificá-lo.

Esconder o botão “Main Menu”

Os relatórios aparecem por defeito com um TabControl e com uma TabPage por cada relatório visível. Estas TabPages servem para selecionar o relatório mas na grande maioria das vezes existem apenas um relatório. Nestes casos podemos “esconder” o botão e embora não seja possível na realidade esconder, é possível reduzir o tamanho de modo a este não ser visível.

 

        ' Faz um ciclo em todos os controlos do CrystalReportViewer1
        For Each ctrl As Control In Me.CrystalReportViewer1.Controls

            ' Se o controlo for do tipo PageView, ou seja, onde
            ' se encontra os relatórios e o TabControl
            If TypeOf ctrl Is PageView Then   

                ' Atribui a uma variável o primeiro controlo
                Dim tabCtrl As TabControl = CType(ctrl.Controls(0), TabControl)

                ' Define o tamanho como fixo
                tabCtrl.SizeMode = TabSizeMode.Fixed

                ' Define o tamanho em altura para 1
                tabCtrl.ItemSize = New Size(0, 1)

                Exit For

            End If

        Next

Alterar o nome do botão “Main Menu”

Este exemplo é semelhante ao anterior, apenas mudando o tipo de controlo. Desta vez, e para alterar o nome de “Main Menu” para outro à nossa escolha, devemos selecionar uma TabPage do TabControl.

        ' Faz um ciclo em todos os controlos do CrystalReportViewer1
        For Each ctrl As Control In Me.CrystalReportViewer1.Controls

            ' Se o controlo for do tipo PageView, ou seja, onde
            ' se encontra os relatórios e o TabControl
            If TypeOf ctrl Is PageView Then

                ' Atribui a uma variável o primeiro controlo da primeira TabPage
                Dim tabPag As TabPage = CType(ctrl.Controls(0), TabControl).TabPages(0)

                ' Altera o nome visível
                tabPag.Text = "Relatório"

                Exit For

            End If

        Next

   

Adicionar controlos à Barra de Ferramentas

De modo a personalizar o CystalReportViewer é possível adicionar controlos, remove-los, modificar os existentes, etc. Este exemplo mostra com inserir um ToolStripButton e uma ToolStripLabel à barra de ferramentas.

        For Each ctrl As Control In Me.PtCrystalReportViewer2.Controls
            If TypeOf ctrl Is Windows.Forms.ToolStrip Then

                Dim ts As ToolStrip = CType(ctrl, ToolStrip)

                ' Cria um novo botão e define algumas propriedades
                Dim btnSave As New ToolStripButton
                btnSave.Text = "Gravar no Disco"
                btnSave.BackColor = Color.SeaGreen
                btnSave.ForeColor = Color.White

                ' Adiciona o botão
                ts.Items.Add(btnSave)

                ' Cria uma nova label e define o texto
                Dim lblLink As New ToolStripLabel
                lblLink.Text = "http://vbtuga.blogspot.com"

                ' Define como link e alinha-a à direita
                lblLink.IsLink = True
                lblLink.Alignment = ToolStripItemAlignment.Right

                ' Adiciona a ToolStripLabel
                ts.Items.Add(lblLink)

                ' Define quando for efectuado um clique em cada
                ' um dos objectos irá ser executado o sub DoWork
                AddHandler btnSave.Click, AddressOf DoWork
                AddHandler lblLink.Click, AddressOf DoWork

                Exit For

            End If

        Next

Depois para executar o código quando for clicado nos novos controlos:

    ' Verifica qual controlo em que foi efectuado o clique
    Private Sub DoWork(ByVal sender As System.Object, ByVal e As System.EventArgs)

        If TypeOf sender Is ToolStripButton Then

            ' Se for no botão 
            Debug.WriteLine("Pressionado o botão 'Gravar'")

        ElseIf TypeOf sender Is ToolStripLabel Then

            ' Se for no label
            Debug.WriteLine("Carregado no link ...")

        End If

    End Sub

   

CystalReportViewer personalizado em Português

Finalmente, e utilizando um pouco do que foi mostrado anteriormente, e incluindo mais algumas funcionalidades como renomear todos os ToolTips (textos de ajuda), remover algumas opções, criar uma nova barra de estado em Português (indicação da página e total de páginas) são algumas das alterações que estão efectuadas.

Existem ainda algumas personalizações possíveis em design mode como o StatusBarStyle e StatusBarStyle (System, Professional) e DisplayMainMenu, que permite esconder o botão “Main Menu” quando o relatório for iniciado.

Podem testar, verificar o código, solicitar ou apresentar melhorias ao controlo personalizado:

          Dowload (inclui dll e projecto de demonstração): CrystalReportViewerPT

Nota: Este controlo encontrasse em testes e é apenas uma demonstração, pelo que deverá ser testado e validado antes da sua utilização.

 

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


VB.NET: Utilização de Overrides

O overrides ou sobreposição é uma propriedade ou procedimento/função herdado da classe base. Ou seja a possibilidade de alterar acções ou propriedades da classe, mas com uma capacidade mais abrangente e com muito menos limitações. Existem algumas operações que só podem ser feitas desta forma.

   

Por exemplo, a tecla TAB não é possível detectar ou modificar nos eventos KeyUp, KeyDown ou KeyPress de qualquer controlo. Para se efectuar desta forma era necessário utilizar o PreviewKeyDown e o KeyDown em conjunto, o que além de não ser prático e mais confuso. Este código simplesmente não trabalha:

   

   ' No controlo TextBox1 quando a tecla está pressionada (em baixo)

    Private Sub TextBox1_KeyDown(ByVal sender As System.Object, _

                                 ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown

   

        ' Caso a tecla seja TAB

        If e.KeyCode = Keys.Tab Then

            ' Ignora a tecla pressionada

            e.SuppressKeyPress = True

        End If

   

    End Sub

   

Para conseguir capturar a tecla antes de ela actuar e de uma forma simples pode-se usar, por exemplo, a função ProcessTabKey. Desta forma já é possível modificar o comportamento da tecla TAB e é executada independentemente do controlo seleccionado.

   

Neste caso estamos a bloquear a utilização da tecla TAB quando o TextBox1 estiver seleccionado.

   

    ' Quando é pressionada a tecla TAB

    Protected Overrides Function ProcessTabKey(ByVal forward As Boolean) As Boolean

   

        ' Se o controlo TextBox1 estives seleccionado

        If TextBox1.Focused Then

            ' Ignora a tecla pressionada

            Return True

        Else

            ' Executa o TAB para o próximo controlo

            Return MyBase.ProcessTabKey(forward)

        End If

   

    End Function

   

   

Nos forms com muitos controlos, especialmente quando servem para registo de dados, é pratico utilizar as teclas para saltar de controlo em controlo. A tecla que faz esta função é a tecla TAB ou Shift+TAB, que salta para o próximo ou anterior, de acordo com TabIndex definido. O TabIndex é uma propriedade, disponível na maioria dos controlos, que define qual a ordem de tabulação a executar. Ou seja, quando o form inicia é seleccionado o TabIndex com menor valor (normalmente o 0) e ao carregarmos na tecla TAB irá saltar para o próximo (normalmente o 1).

   

Mas a tecla TAB não é na realidade muito prática e muitos programadores, para melhorar a navegabilidade, utilizam a tecla Enter ou as cursoras KeyUp ou KeyDdown. Para simplificar este processo pode-se utilizar o overrides de funções, neste caso utilizando o ProcessCmdKey.

   

Por exemplo, para saltar de controlo em controlo utilizando as teclas cursoras, pode-se utilizar o seguinte código:

   

   

       ‘ Verifica quando é pressionado uma tecla

    Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean

   

        '  Se a tecla for a cursora Up ou Down

        If keyData = Keys.Up Or keyData = Keys.Down Then

              ‘ Selecciona o próximo controlo (de acordo com o TabIndex)

              Me.SelectNextControl(Me.ActiveControl, (keyData = Keys.Down), True, True, True)

        End If

   

        Return MyBase.ProcessCmdKey(msg, keyData)

   

    End Function

   

   

Mas podem-se também alterar algumas das propriedades de cada objecto/classe. O seguinte exemplo mostra como alterar o função do método ToString().

   

' Construção da Classe de Carros

Public Class Carro

   

    ' Sempre que é executado o método ToString() é mostrado

    ' a Marca – Modelo e não a simples conversão para string

    Public Overrides Function ToString() As String

        Return Me._Marca & " - " + Me._Modelo

    End Function

   

    ' Define uma propriedade para a Marca

    Private _Marca As String

    Public Property Marca() As String

        Get

            Return _Marca

        End Get

        Set(ByVal value As String)

            _Marca = value

        End Set

    End Property

   

    ' Define uma propriedade para o Modelo

    Private _Modelo As String

    Public Property Modelo() As String

        Get

            Return _Modelo

        End Get

        Set(ByVal value As String)

            _Modelo = value

        End Set

    End Property

End Class

   

   

Depois, e para mostrar o funcionamento da alteração do overrides da função ToString()

   

   

       ' Cria uma nova instância da classe Carro

        Dim clsCarro As New Carro

   

        ' Define a Marca e o Modelo do exemplo

        clsCarro.Marca = "Ford"

        clsCarro.Modelo = "Fiesta"

   

        ' Mostra o resultado que neste caso é "Ford - Fiesta" mas sem a

        ' utilização do Overrides apareceria WindowsApplication1.Carro

        Debug.WriteLine(clsCarro.ToString)

   

   

Em resumo e de uma forma genérica, o overrides permite alterar propriedades ou procedimentos/funções de uma classe e efectuar algumas operações apenas possíveis desta forma. No entanto é necessário ter algum cuidado na sua utilização, pois alterar funções que já se conhece poderá originar alguns problemas no código.



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



Microsoft Office Especialist

Membro da Comunidade
Experts-Exchange


Administ. da Comunidade
Portugal-a-Programar



Twitter

Artigos no CodeProject

Artigos no CodeProject

Subscrever Novidades

Endereço de Email:

Delivered by FeedBurner

Seguidores

Histórico