5. Interfaces gráficas com VB.NET e VS.NET
Propomos aqui mostrar como construir interfaces gráficas com o VB.NET. Primeiramente, veremos quais são as classes básicas da plataforma .NET que nos permitem construir uma interface gráfica. Inicialmente, não utilizaremos nenhuma ferramenta de geração automática. Em seguida, utilizaremos o Visual Studio.NET (VS.NET), uma ferramenta de desenvolvimento da Microsoft que facilita o desenvolvimento de aplicativos com as linguagens .NET e, em especial, a criação de interfaces gráficas. A versão VS.NET utilizada é a versão em inglês.
5.1. Noções básicas sobre interfaces gráficas
5.1.1. Uma janela simples
Consideremos o código a seguir:
' opções
Option Strict On
Option Explicit On
' espaços de nomes
Imports System
Imports System.Drawing
Imports System.Windows.Forms
' a classe do formulário
Public Class Form1
Inherits Form
' o fabricante
Public Sub New()
' título da janela
Me.Text = "Mon premier formulaire"
' dimensões da janela
Me.Size = New System.Drawing.Size(300, 100)
End Sub
' função de teste
Public Shared Sub Main(ByVal args() As String)
' o formulário é exibido
Application.Run(New Form1)
End Sub
End Class
O código anterior é compilado e, em seguida, executado
A execução exibe a seguinte janela:

Uma interface gráfica geralmente deriva da classe base System.Windows.Forms.Form:
A classe base Form define uma janela básica com botões para fechar, ampliar/reduzir, tamanho ajustável, etc., e gerencia os eventos nesses objetos gráficos. Aqui, especializamos a classe base definindo um título, bem como sua largura (300) e altura (100). Isso é feito em seu construtor:
Public Sub New()
' título da janela
Me.Text = "Mon premier formulaire"
' dimensões da janela
Me.Size = New System.Drawing.Size(300, 100)
End Sub
O título da janela é definido pela propriedade Text e as dimensões pela propriedade Size. Size está definido no espaço de nomes System.Drawing e é uma estrutura. O procedimento Main inicia o aplicativo gráfico da seguinte maneira:
Application.Run(New Form1)
Um formulário do tipo Form1 é criado e exibido; em seguida, o aplicativo fica à espera dos eventos que ocorrem no formulário (cliques, movimentos do mouse, etc.) e executa aqueles que o formulário suporta. Nesse caso, nosso formulário não gerencia nenhum outro evento além daqueles gerenciados pela classe base Form (cliques nos botões de fechar, ampliar/reduzir, alteração do tamanho da janela, movimentação da janela, etc.).
5.1.2. Um formulário com botão
Vamos agora adicionar um botão à nossa janela:
' opções
Option Strict On
Option Explicit On
' espaços de nomes
Imports System
Imports System.Drawing
Imports System.Windows.Forms
' a classe do formulário
Public Class Form1
Inherits Form
' atributos
Private cmdTest As Button
' o construtor
Public Sub New()
' o título
Me.Text = "Mon premier formulaire"
' as dimensões
Me.Size = New System.Drawing.Size(300, 100)
' um botão
' criação
Me.cmdTest = New Button
' posição
cmdTest.Location = New System.Drawing.Point(110, 20)
' tamanho
cmdTest.Size = New System.Drawing.Size(80, 30)
' texto
cmdTest.Text = "Test"
' gerenciador de eventos
AddHandler cmdTest.Click, AddressOf cmdTest_Click
' adição de botão ao formulário
Me.Controls.Add(cmdTest)
End Sub
' gerenciador de eventos
Private Sub cmdTest_Click(ByVal sender As Object, ByVal evt As EventArgs)
' houve um clique no botão — informamos
MessageBox.Show("Clic sur bouton", "Clic sur bouton", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
' função de teste
Public Shared Sub Main(ByVal args() As String)
' exibimos o formulário
Application.Run(New Form1)
End Sub
End Class
Adicionamos um botão ao formulário:
' um botão
' criação
Me.cmdTest = New Button
' posição
cmdTest.Location = New System.Drawing.Point(110, 20)
' tamanho
cmdTest.Size = New System.Drawing.Size(80, 30)
' texto
cmdTest.Text = "Test"
' gerenciador de eventos
AddHandler cmdTest.Click, AddressOf cmdTest_Click
' adição de botão ao formulário
Me.Controls.Add(cmdTest)
A propriedade Location define as coordenadas (110,20) do canto superior esquerdo do botão por meio de uma estrutura Point. A largura e a altura do botão são definidas como (80,30) por meio de uma estrutura Size. A propriedade Text do botão permite definir o texto do botão. A classe “botão” possui um evento Click definido da seguinte forma:
onde EventHandler é uma função “delegada” com a seguinte assinatura:
Isso significa que o manipulador do evento [Click] no botão deverá ter a assinatura do delegado [EventHandler]. Nesse caso, ao clicar no botão cmdTest, o método cmdTest_Click será chamado. Este está definido da seguinte forma, de acordo com o modelo anterior EventHandler:
' gerenciador de eventos
Private Sub cmdTest_Click(ByVal sender As Object, ByVal evt As EventArgs)
' houve um clique no botão — isso é informado
MessageBox.Show("Clic sur bouton", "Clic sur bouton", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
Limita-se a exibir uma mensagem:

A classe é compilada e executada:
dos>vbc /r:system.dll /r:system.drawing.dll /r:system.windows.forms.dll frm2.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4
dos>frm2
A classe MessageBox serve para exibir mensagens em uma janela. Aqui, utilizamos o construtor
Overloads Public Shared Function Show(ByVal owner As IWin32Window,ByVal text As String,ByVal caption As String,ByVal buttons As MessageBoxButtons,ByVal icon As MessageBoxIcon) As DialogResult
text | a mensagem a ser exibida |
legenda | o título da janela |
botões | os botões presentes na janela |
icon | o ícone presente na janela |
O parâmetro buttons pode assumir valores entre as seguintes constantes:
constante | botões |
![]() | |
![]() | |
![]() | |
![]() | |
![]() | |
![]() |
O parâmetro icon pode assumir valores entre as seguintes constantes:
![]() | idem Stop | ||
idem Aviso | ![]() | ||
idem Asterisk | ![]() | ||
![]() | idem Hand | ||
![]() |
O método Show é um método estático que retorna um resultado do tipo System.Windows.Forms.DialogResult, que é uma enumeração:
public enum System.Windows.Forms.DialogResult
{
Abort = 0x00000003,
Cancel = 0x00000002,
Ignore = 0x00000005,
No = 0x00000007,
None = 0x00000000,
OK = 0x00000001,
Retry = 0x00000004,
Yes = 0x00000006,
}
Para saber em qual botão o usuário clicou para fechar a janela do tipo MessageBox, escreveremos:
dim res as DialogResult=MessageBox.Show(..)
if res=DialogResult.Yes then
' ele clicou no botão “Sim”
...
end if
5.2. Criar uma interface gráfica com o Visual Studio.NET
Retomamos alguns dos exemplos vistos anteriormente, criando-os agora com o Visual Studio.NET.
5.2.1. Criação inicial do projeto
- Inicie o VS.NET e selecione a opção Fichier/Nouveau/Projet

- insira as características do seu projeto
![]() |
- selecione o tipo de projeto que deseja criar; neste caso, um projeto VB.NET (1)
- selecione o tipo de aplicativo que você deseja criar, neste caso, um aplicativo do Windows (2)
- indique em qual pasta você deseja colocar a subpasta do projeto (3)
- indique o nome do projeto (4). Esse também será o nome da pasta que conterá os arquivos do projeto
- O nome dessa pasta é exibido em (5)
- Em seguida, são criadas várias pastas e arquivos na pasta i4:
subpastas da pasta projeto1 ![]() |
Desses arquivos, apenas um é relevante: o arquivo form1.cs, que é o arquivo de origem associado ao formulário criado pelo VS.NET. Voltaremos a esse assunto mais tarde.
5.2.2. As janelas da interface do VS.NET
A interface do VS.NET agora exibe alguns elementos do nosso projeto i4:
Temos uma janela de design da interface gráfica:
![]() |
Ao selecionar controles na barra de ferramentas (toolbox 2) e arrastá-los para a área da janela (1), podemos construir uma interface gráfica. Se passarmos o mouse sobre a “toolbox”, ela se amplia e exibe vários controles:

Por enquanto, não estamos usando nenhum deles. Ainda na tela de VS.NET, encontramos a janela do explorador de soluções “Explorer Solution”:

Inicialmente, não utilizaremos muito essa janela. Ela mostra todos os arquivos que compõem o projeto. Apenas um deles nos interessa: o arquivo-fonte do nosso programa, neste caso, Form1.vb. Ao clicar com o botão direito do mouse em Form1.vb, aparece um menu que permite acessar tanto o código-fonte da nossa interface gráfica (Exibir o código) quanto a própria interface gráfica (Criador de visualizações):

É possível acessar essas duas entidades diretamente a partir da janela “Solution Explorer”:
![]() | ![]() |
As janelas abertas “se acumulam” na janela principal de design:

Aqui, Form1.vb[Design] refere-se à janela de design e Form1.vb à janela de código. Basta clicar em uma das abas para alternar entre as janelas. Outra janela importante presente na tela do VS.NET é a janela de propriedades:

As propriedades exibidas na janela são as do controle atualmente selecionado na janela de design gráfico. É possível acessar diferentes janelas do projeto por meio do menu Affichage:

Nele estão as janelas principais que acabaram de ser descritas, bem como seus atalhos de teclado.
5.2.3. Execução de um projeto
Mesmo sem ter escrito nenhum código, já temos um projeto executável. Execute F5 ou Déboguer/Démarrer para executá-lo. Aparece a seguinte janela:

Essa janela pode ser ampliada, minimizada, redimensionada e fechada.
5.2.4. O código gerado pelo VS.NET
Vamos examinar o código (Affichage/Code) do nosso aplicativo:
Public Class Form1
Inherits System.Windows.Forms.Form
#Região “Código gerado pelo Windows Form Designer”
Public Sub New()
MyBase.New()
'Esta chamada é exigida pelo Windows Form Designer.
InitializeComponent()
'Adicione alguma inicialização após a chamada InitializeComponent()
End Sub
'O método substituído Dispose do formulário limpa a lista de componentes.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Exigido pelo Windows Form Designer
Private components As System.ComponentModel.IContainer
'REMARQUE: o procedimento a seguir é exigido pelo Windows Form Designer
'Ela pode ser modificada usando o Windows Form Designer.
'Não a altere usando o editor de código.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
Me.Text = "Form2"
End Sub
#Fim da região
End Class
Uma interface gráfica deriva da classe base System.Windows.Forms.Form:
A classe base Form define uma janela básica com botões de fechar, ampliar/reduzir, tamanho ajustável, etc., e gerencia os eventos nesses objetos gráficos. O construtor do formulário utiliza um método InitializeComponent no qual os controles do formulário são criados e inicializados.
Public Sub New()
MyBase.New()
'Esta chamada é exigida pelo Windows Form Designer.
InitializeComponent()
'Adicione qualquer inicialização após a chamada InitializeComponent()
End Sub
Qualquer outro trabalho a ser realizado no construtor pode ser feito após a chamada ao método InitializeComponent. O método InitializeComponent
Private Sub InitializeComponent()
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 53)
Me.Name = "Form1"
Me.Text = "Form1"
End Sub
define o título da janela “Form1”, sua largura (292) e sua altura (53). O título da janela é definido pela propriedade Text e as dimensões pela propriedade Size. Size está definido no espaço de nomes System.Drawing e é uma estrutura. Para executar esta aplicação, precisamos definir o módulo principal do projeto. Para isso, utilizamos a opção [Projets/Propriétés]:

Em [Objet de démarrage], indicamos [Form1], que é o formulário que acabamos de criar. Para iniciar a execução, utilizamos a opção [Déboguer/Démarrer]:

5.2.5. Compilação em uma janela do DOS
Agora, vamos tentar compilar e executar essa aplicação em uma janela do DOS:
dos>dir form1.vb
14/03/2004 11:53 514 Form1.vb
dos>vbc /r:system.dll /r:system.windows.forms.dll form1.vb
vbc : error BC30420: 'Sub Main' est introuvable dans 'Form1'.
O compilador indica que não encontra a procedimento [Main]. De fato, VS.NET não a gerou. No entanto, já a encontramos nos exemplos anteriores. Ela tem o seguinte formato:
Shared Sub Main()
' inicializa-se o aplicativo
Application.Run(New Form1) ' où Form1 est le formulaire
End Sub
Vamos adicionar o código anterior ao código de [Form1.vb] e recompilar:
dos>vbc /r:system.dll /r:system.windows.forms.dll form2.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4
Form2.vb(41) : error BC30451: Le nom 'Application' n'est pas déclaré.
Application.Run(New Form2)
~~~~~~~~~~~
Desta vez, o nome [Application] não é reconhecido. Isso significa simplesmente que não importamos seu espaço de nomes [System.Windows.Forms]. Vamos adicionar a seguinte instrução:
e, em seguida, recompilemos:
Desta vez, funcionou. Vamos executar:

Um formulário do tipo Form1 é criado e exibido. É possível evitar a inclusão da rotina [Main] utilizando a opção /m do compilador, que permite especificar a classe a ser executada caso ela herde de System.Windows.Form:
A opção /m:form2 indica que a classe a ser executada é a classe com o nome [form2].
5.2.6. Gerenciamento de eventos
Assim que o formulário é exibido, o aplicativo fica à espera dos eventos que ocorrem no formulário (cliques, movimentos do mouse, etc.) e executa aqueles que o formulário gerencia. Neste caso, nosso formulário não gerencia nenhum outro evento além daqueles gerenciados pela classe base Form (cliques nos botões de fechar, ampliar/reduzir, alteração do tamanho da janela, movimentação da janela, etc.). O formulário gerado utiliza um atributo components que não é utilizado em nenhum lugar. O método dispose também não tem utilidade aqui. O mesmo vale para alguns espaços de nomes (Collections, ComponentModel, Data) utilizados e para aquele definido para o projeto projet1. Portanto, neste exemplo, o código pode ser simplificado da seguinte forma:
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Public Class Form1
Inherits System.Windows.Forms.Form
' construtor
Public Sub New()
' construção do formulário com seus componentes
InitializeComponent()
End Sub
Private Sub InitializeComponent()
' tamanho da janela
Me.Size = New System.Drawing.Size(300, 300)
' título da janela
Me.Text = "Form1"
End Sub
Shared Sub Main()
' abrimos o aplicativo
Application.Run(New Form1)
End Sub
End Class
5.2.7. Conclusão
Agora aceitaremos o código gerado pelo VS.NET tal como está e nos limitaremos a adicionar o nosso, principalmente para gerenciar os eventos relacionados aos diferentes campos do formulário.
5.3. Janela com campo de entrada, botão e legenda
5.3.1. Design gráfico
No exemplo anterior, não havíamos inserido componentes na janela. Iniciamos um novo projeto chamado interface2. Para isso, seguimos o procedimento explicado anteriormente para criar um projeto:

Vamos agora criar uma janela com um botão, um rótulo e um campo de entrada:
![]() |
Os campos são os seguintes:
n.º | nome | tipo | função |
1 | lblSaisie | Rótulo | uma descrição |
2 | txtSaisie | TextBox | um campo de preenchimento |
3 | btnAfficher | Botão | para exibir em uma caixa de diálogo o conteúdo do campo de entrada txtSaisie |
Para criar essa janela, proceda da seguinte forma: clique com o botão direito do mouse na janela, fora de qualquer componente, e selecione a opção Properties para acessar as propriedades da janela:

A janela de propriedades aparece então à direita:

Algumas dessas propriedades merecem destaque:
para definir a cor de fundo da janela | |
para definir a cor dos desenhos ou do texto na janela | |
para associar um menu à janela | |
para atribuir um título à janela | |
para definir o tipo de janela | |
para definir a fonte das letras na janela | |
para definir o nome da janela |
Aqui, definimos as propriedades Text e Name:
Campos de entrada e botões - 1 | |
frmSaisiesBoutons |
Usando a barra “Caixa de ferramentas”
- selecione os componentes de que você precisa
- arraste-os para a janela e defina as dimensões corretas
![]() | ![]() |
Depois de escolher o componente na “caixa de ferramentas”, use a tecla “Esc” para ocultar a barra de ferramentas e, em seguida, arraste e dimensione o componente. Repita o procedimento para os três componentes necessários: Label, TextBox, Button. Para alinhar e dimensionar corretamente os componentes, use o menu Format: | ![]() |
O princípio da formatação é o seguinte:
A opção Align permite alinhar componentes | ![]() |
A opção Make Same Size permite que componentes tenham a mesma altura ou a mesma largura: | ![]() |
A opção “Espaçamento horizontal” permite, por exemplo, alinhar horizontalmente os componentes com intervalos de tamanho igual entre eles. O mesmo vale para a opção “Espaçamento vertical”, que permite o alinhamento vertical. A opção “Center in Form” permite centralizar um componente horizontalmente ou verticalmente na janela: | ![]() |
Depois que os componentes estiverem corretamente posicionados na janela, defina suas propriedades. Para isso, clique com o botão direito do mouse no componente e selecione a opção Properties:
Selecione o componente para abrir a janela de propriedades. Nela, altere as seguintes propriedades: nome: lblSaisie, texto: Campo de
Selecione o componente para abrir sua janela de propriedades. Nela, altere as seguintes propriedades: nome: txtSaisie, texto: não preencher
name: cmdAfficher, text: Exibir
text: Entradas e botões - 1 | ![]() |
Podemos executar (Ctrl+F5) nosso projeto para ter uma primeira visão geral da janela em ação: | ![]() |
Feche a janela. Agora precisamos escrever o procedimento associado ao clique no botão Afficher.
5.3.2. Gerenciamento de eventos de um formulário
Vamos examinar o código gerado pelo designer gráfico:
...
Public Class frmSaisiesBoutons
Inherits System.Windows.Forms.Form
' componentes
Private components As System.ComponentModel.Container = Nothing
Friend WithEvents btnAfficher As System.Windows.Forms.Button
Friend WithEvents lblsaisie As System.Windows.Forms.Label
Friend WithEvents txtsaisie As System.Windows.Forms.TextBox
' construtor
Public Sub New()
InitializeComponent()
End Sub
...
' inicialização dos componentes
Private Sub InitializeComponent()
...
End Sub
End Class
Em primeiro lugar, observe-se a declaração específica dos componentes:
- a palavra-chave `Friend` indica que a visibilidade do componente se estende a todas as classes do projeto
- a palavra-chave WithEvents indica que o componente gera eventos. Vamos agora nos concentrar em como gerenciar esses eventos
Exiba a janela de código do formulário (Exibir/código ou F7):
![]() |
A janela acima apresenta duas listas suspensas (1) e (2). A lista (1) é a lista de componentes do formulário:

A lista (2) é a lista de eventos associados ao componente selecionado em (1):

Um dos eventos associados ao componente é exibido em negrito (neste caso, Click). Esse é o evento padrão do componente. O acesso ao manipulador desse evento específico pode ser feito clicando duas vezes no componente na janela de design. O VB.net gera automaticamente o esboço do manipulador de eventos na janela de código e posiciona o usuário nele. O acesso aos manipuladores dos demais eventos é feito na janela de código, selecionando o componente na lista (1) e o evento em (2). O VB.net gera então o esboço do manipulador de evento ou posiciona o cursor sobre ele, caso já tenha sido gerado:
Private Sub btnAfficher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAfficher.Click
...
End Sub
Por padrão, o VB.net C_E nomeia o gerenciador do evento E do componente C. É possível alterar esse nome, se for do nosso interesse. No entanto, isso não é recomendado. Os desenvolvedores do VB geralmente mantêm o nome gerado pelo VB, o que garante a coerência na nomenclatura em todos os programas do VB. A associação do procedimento btnAfficher_Click ao evento Click do componente btnAfficher não é feita pelo nome do procedimento, mas pela palavra-chave handles:
Handles btnAfficher.Click
No exemplo acima, a palavra-chave handles especifica que o procedimento gerencia o evento **Click do componente btnAfficher**. O gerenciador de eventos anterior possui dois parâmetros:
o objeto que originou o evento (neste caso, o botão) | |
um objeto EventArgs que detalha o evento que ocorreu |
Não utilizaremos nenhum desses parâmetros aqui. Resta apenas completar o código. Aqui, queremos exibir uma caixa de diálogo com o conteúdo do campo txtSaisie:
Private Sub btnAfficher_Click(ByVal sender As Object, ByVal e As System.EventArgs)
' exibe-se o texto digitado na caixa de entrada TxtSaisie
MessageBox.Show("texte saisi= " + txtsaisie.Text, "Vérification de la saisie", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
Se executarmos o aplicativo, obtemos o seguinte:

5.3.3. Outro método para gerenciar eventos
Para o botão btnAfficher, o VS.NET gerou o seguinte código:
Private Sub InitializeComponent()
...
'
'btnAfficher
'
Me.btnAfficher.Location = New System.Drawing.Point(102, 48)
Me.btnAfficher.Name = "btnAfficher"
Me.btnAfficher.Size = New System.Drawing.Size(88, 24)
Me.btnAfficher.TabIndex = 2
Me.btnAfficher.Text = "Afficher"
...
End Sub
...
' gerenciador de eventos de clique no botão cmdAfficher
Private Sub btnAfficher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAfficher.Click
...
End Sub
Podemos associar o procedimento btnAfficher_Click ao evento Click do botão btnAfficher de outra maneira:
Private Sub InitializeComponent()
...
'
'btnAfficher
'
Me.btnAfficher.Location = New System.Drawing.Point(102, 48)
Me.btnAfficher.Name = "btnAfficher"
Me.btnAfficher.Size = New System.Drawing.Size(88, 24)
Me.btnAfficher.TabIndex = 2
Me.btnAfficher.Text = "Afficher"
AddHandler btnAfficher.Click, AddressOf btnAfficher_Click
...
End Sub
...
' gerenciador de eventos ao clicar no botão cmdAfficher
Private Sub btnAfficher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
...
End Sub
O procedimento btnAfficher_Click perdeu a palavra-chave Handles, perdendo assim sua associação com o evento btnAfficher.Click. Essa associação agora é feita por meio da palavra-chave AddHandler:
AddHandler btnAfficher.Click, AddressOf btnAfficher_Click
O código acima, que será inserido no procedimento InitializeComponent do formulário, associa ao evento btnAfficher.Click o procedimento denominado btnAfficher_Click. Além disso, o componente btnAfficher não precisa mais da palavra-chave WithEvents:
Friend btnAfficher As System.Windows.Forms.Button
Qual é a diferença entre os dois métodos?
- A palavra-chave `handles` só permite associar um evento a um procedimento no momento do projeto. O projetista sabe de antemão que um procedimento P deve lidar com os eventos E1, E2, ... e escreve o código
Private Sub btnAfficher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) handles E1, E2, ..., En
De fato, é possível que um procedimento gerencie vários eventos.
- A palavra-chave `addhandler` permite associar um evento a um procedimento no momento da execução. Isso é útil em um contexto de produtor-consumidor de eventos. Um objeto produz um evento específico que pode interessar a outros objetos. Estes se inscrevem junto ao produtor para receber o evento (uma temperatura que ultrapassou um limite crítico, por exemplo). Durante a execução do aplicativo, o produtor do evento terá que executar diferentes instruções:
onde E é o evento produzido pelo produtor e Pi são os procedimentos pertencentes aos diferentes objetos consumidores desse evento. Teremos a oportunidade de voltar a abordar uma aplicação produtor-consumidor de eventos em um próximo capítulo.
5.3.4. Conclusão
A partir dos dois projetos estudados, podemos concluir que, uma vez construída a interface gráfica com VS.NET, o trabalho do desenvolvedor consiste em escrever os manipuladores de eventos que deseja gerenciar para essa interface gráfica. A partir de agora, apresentaremos apenas o código desses manipuladores.
5.4. Alguns componentes úteis
Apresentamos agora diversas aplicações que utilizam os componentes mais comuns, a fim de explorar seus principais métodos e propriedades. Para cada aplicação, apresentamos a interface gráfica e o código relevante, especialmente os manipuladores de eventos.
5.4.1. Formulário Form
Começamos apresentando o componente indispensável: o formulário, no qual os componentes são inseridos. Já apresentamos algumas de suas propriedades básicas. Aqui, vamos nos concentrar em alguns eventos importantes de um formulário.
o formulário está sendo carregado | |
o formulário está sendo fechado | |
o formulário está fechado |
O evento Load ocorre antes mesmo de o formulário ser exibido. O evento Closing ocorre quando o formulário está sendo fechado. Ainda é possível interromper esse fechamento por meio de programação. Criamos um formulário com o nome Form1 sem nenhum componente:

Processamos os três eventos anteriores:
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
' carregamento inicial do formulário
MessageBox.Show("Evt Load", "Load")
End Sub
Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
' o formulário está sendo fechado
MessageBox.Show("Evt Closing", "Closing")
' solicitando confirmação
Dim réponse As DialogResult = MessageBox.Show("Voulez-vous vraiment quitter l'application", "Closing", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If réponse = DialogResult.No Then
e.Cancel = True
End If
End Sub
Private Sub Form1_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Closed
' o formulário está sendo fechado
MessageBox.Show("Evt Closed", "Closed")
End Sub
Utilizamos a função MessageBox para sermos notificados sobre os diferentes eventos. O evento Closing ocorrerá quando o usuário fechar a janela. | ![]() |
Em seguida, perguntamos se ele realmente deseja sair do aplicativo: | ![]() |
Se ele responder “Não”, definimos a propriedade Cancel do evento CancelEventArgs que o método recebeu como parâmetro. Se definirmos essa propriedade como False, o fechamento da janela é cancelado; caso contrário, ele prossegue: | ![]() |
5.4.2. rótulos Label e campos de entrada TextBox
Já nos deparamos com esses dois componentes. Label é um componente de texto e TextBox, um componente de campo de entrada. Sua principal propriedade é Text, que designa tanto o conteúdo do campo de entrada quanto o texto do rótulo. Essa propriedade é de leitura/gravação. O evento normalmente utilizado para TextBox é TextChanged, que sinaliza que o usuário alterou o campo de entrada. Aqui está um exemplo que utiliza o evento TextChanged para acompanhar as alterações em um campo de entrada:
![]() |
n.º | tipo | nome | função |
1 | TextBox | txtSaisie | campo de entrada |
2 | Rótulo | lblControle | exibe o texto de 1 em tempo real |
3 | Botão | cmdEffacer | para apagar os campos 1 e 2 |
4 | Botão | cmdQuitter | para sair do aplicativo |
O código relevante deste aplicativo é o dos gerenciadores de eventos:
' clique no botão Sair
Private Sub cmdQuitter_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmdQuitter.Click
' clique no botão “Sair” – o aplicativo é encerrado
Application.Exit()
End Sub
' alteração no campo txtSaisie
Private Sub txtSaisie_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtSaisie.TextChanged
' o conteúdo de TextBox foi alterado — é copiado para o rótulo lblControle
lblControle.Text = txtSaisie.Text
End Sub
' clique no botão “Apagar”
Private Sub cmdEffacer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmdEffacer.Click
' o conteúdo do campo de entrada é apagado
txtSaisie.Text = ""
End Sub
' foi digitada uma tecla
Private Sub txtSaisie_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) _
Handles txtSaisie.KeyPress
' verifica-se qual tecla foi pressionada
Dim touche As Char = e.KeyChar
If touche = ControlChars.Cr Then
MessageBox.Show(txtSaisie.Text, "Contrôle", MessageBoxButtons.OK, MessageBoxIcon.Information)
e.Handled = True
End If
End Sub
Observe a maneira de encerrar o aplicativo no procedimento cmdQuitter_Click: Application.Exit(). O exemplo a seguir utiliza um TextBox de várias linhas:
![]() |
A lista de controles é a seguinte:
n.º | tipo | nome | função |
1 | TextBox | txtMultiLignes | campo de entrada de várias linhas |
2 | TextBox | txtAjout | campo de entrada de uma linha |
3 | Botão | btnAjouter | Adiciona o conteúdo de 2 a 1 |
Para que um TextBox se torne multilinha, defina as seguintes propriedades do controle:
para aceitar várias linhas de texto | |
para definir se o controle terá barras de rolagem (Horizontal, Vertical, Both) ou não (None) | |
se for igual a true, a tecla Enter irá criar uma nova linha | |
se for igual a true, a tecla Tab gerará uma tabulação no texto |
O código relevante é aquele que processa o clique no botão [Ajouter] e aquele que processa a alteração no campo de entrada [txtAjout]:
' eventualmente btnAjouter_Click
Private Sub btnAjouter_Click1(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnAjouter.Click
' adição do conteúdo de txtAjout ao de txtMultilignes
txtMultilignes.Text &= txtAjout.Text
txtAjout.Text = ""
End Sub
' evt txtAjout_TextChanged
Private Sub txtAjout_TextChanged1(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtAjout.TextChanged
' definimos o estado do botão “Adicionar”
btnAjouter.Enabled = txtAjout.Text.Trim() <> ""
End Sub
5.4.3. listas suspensas ComboBox
![]() | ![]() |
Um componente ComboBox é uma lista suspensa acompanhada de um campo de entrada: o usuário pode escolher um item em (2) ou digitar texto em (1). Existem três tipos de ComboBox definidos pela propriedade Style:
lista não suspensa com campo de edição | |
lista suspensa com campo de edição | |
lista suspensa sem campo de edição |
Por padrão, o tipo de um ComboBox é DropDown. Para conhecer a classe ComboBox, digite ComboBox no índice da ajuda (Aide/Index). A classe ComboBox possui um único construtor:
Public Sub New() | cria um objeto ComboBox vazio |
Os elementos do ComboBox estão disponíveis na propriedade Items:
Trata-se de uma propriedade indexada, em que Items(i) designa o elemento i da lista suspensa. Seja C uma lista suspensa e C.Items sua lista de elementos. Temos as seguintes propriedades:
número de elementos do combo | |
elemento i do combo | |
adiciona o objeto o como último elemento da lista suspensa | |
adiciona uma matriz de objetos ao final da lista suspensa | |
adiciona o objeto o na posição i da lista suspensa | |
remove o elemento i da lista suspensa | |
remove o objeto o da lista suspensa | |
exclui todos os elementos da lista suspensa | |
retorna a posição i do objeto o na lista suspensa |
Pode parecer surpreendente que uma lista suspensa possa conter objetos, já que normalmente ela contém cadeias de caracteres. Visualmente, é isso que ocorre. Se um ComboBox contiver um objeto obj, ele exibirá a cadeia obj.ToString(). Vale lembrar que todo objeto possui um método ToString herdado da classe object, que retorna uma sequência de caracteres “representativa” do objeto. O elemento selecionado na lista suspensa C é C.SelectedItem ou C.Items(C.SelectedIndex), onde C.SelectedIndex é o número do elemento selecionado, sendo que esse número começa em zero para o primeiro elemento.
Ao selecionar um elemento na lista suspensa, ocorre o evento SelectedIndexChanged, que pode ser utilizado para ser notificado sobre a alteração na seleção da lista suspensa. No aplicativo a seguir, utilizamos esse evento para exibir o elemento que foi selecionado na lista.

Apresentamos apenas o código relevante da janela. No construtor do formulário, preenchemos a lista suspensa:
Public Sub New()
' criação do formulário
InitializeComponent()
' preenchimento do campo de lista suspensa
cmbNombres.Items.AddRange(New String() {"zéro", "un", "deux", "trois", "quatre"})
' selecionamos o primeiro elemento da lista
cmbNombres.SelectedIndex = 0
End Sub
Processamos o evento SelectedIndexChanged da lista suspensa, que sinaliza um novo item selecionado:
Private Sub cmbNombres_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmbNombres.SelectedIndexChanged
' o elemento selecionado mudou — exibimos
MessageBox.Show("Elément sélectionné : (" & cmbNombres.SelectedItem.ToString & "," & cmbNombres.SelectedIndex & ")", "Combo", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
5.4.4. componente ListBox
Propomos construir a seguinte interface:
![]() |
Os componentes desta janela são os seguintes:
n.º | tipo | nome | função/propriedades |
0 | Form | Form1 | formulário - BorderStyle=FixedSingle |
1 | TextBox | txtSaisie | campo de preenchimento |
2 | Botão | btnAjouter | botão que permite adicionar o conteúdo do campo de entrada 1 à lista 3 |
3 | ListBox | listBox1 | lista 1 |
4 | ListBox | listBox2 | lista 2 |
5 | Botão | btn1TO2 | transfere os itens selecionados da lista 1 para a lista 2 |
6 | Botão | cmd2T0 | faz o inverso |
7 | Botão | btnEffacer1 | esvazia a lista 1 |
8 | Botão | btnEffacer2 | Esvazia a lista 2 |
- O usuário digita um texto no campo 1. Ele o adiciona à lista 1 usando o botão Ajouter (2). O campo de entrada (1) é então esvaziado e o usuário pode adicionar um novo item.
- É possível transferir itens de uma lista para outra selecionando o item a ser transferido em uma das listas e escolhendo o botão de transferência adequado, 5 ou 6. O item transferido é adicionado ao final da lista de destino e removido da lista de origem.
- O usuário pode clicar duas vezes em um item da lista 1. Esse item é então transferido para a caixa de entrada para edição e removido da lista 1.
Os botões ficam ativados ou desativados de acordo com as seguintes regras:
- o botão Ajouter só fica ativado se houver um texto não vazio no campo de entrada
- o botão 5 de transferência da lista 1 para a lista 2 fica ativado apenas se houver um elemento selecionado na lista 1
- o botão 6 de transferência da lista 2 para a lista 1 fica ativado somente se houver um elemento selecionado na lista 2
- os botões 7 e 8 para limpar as listas 1 e 2 só ficam acesos se a lista a ser limpa contiver elementos.
Nas condições acima, todos os botões devem estar desativados ao iniciar o aplicativo. É necessário, portanto, definir a propriedade Enabled dos botões como false. Isso pode ser feito na fase de projeto, o que gerará o código correspondente no método InitializeComponent, ou pode ser feito manualmente no construtor, conforme mostrado abaixo:
Public Sub New()
' criação inicial do formulário
InitializeComponent()
' inicializações complementares
' desativam-se alguns botões
btnAjouter.Enabled = False
btn1TO2.Enabled = False
btn2TO1.Enabled = False
btnEffacer1.Enabled = False
btnEffacer2.Enabled = False
End Sub
O estado do botão Ajouter é controlado pelo conteúdo do campo de entrada. É o evento TextChanged que nos permite acompanhar as alterações nesse conteúdo:
' alteração no campo de entrada de texto
Private Sub txtSaisie_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtSaisie.TextChanged
' o conteúdo de txtSaisie foi alterado
' o botão “Adicionar” só fica ativado se o campo de entrada não estiver vazio
btnAjouter.Enabled = txtSaisie.Text.Trim() <> ""
End Sub
O estado dos botões de transferência depende do fato de um elemento ter sido selecionado ou não na lista que eles controlam:
' alteração do elemento selecionado sem listbox1
Private Sub listBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles listBox1.SelectedIndexChanged
' um elemento foi selecionado
' o botão de transferência de 1 para 2 é ativado
btn1TO2.Enabled = True
End Sub
' alteração do elemento selecionado sem a caixa de lista 2
Private Sub listBox2_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles listBox2.SelectedIndexChanged
' um elemento foi selecionado
' ativar o botão de transferência de 2 para 1
btn2TO1.Enabled = True
End Sub
O código associado ao clique no botão Ajouter é o seguinte:
' clique no botão “Adicionar”
Private Sub btnAjouter_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnAjouter.Click
' adição de um novo elemento à lista 1
listBox1.Items.Add(txtSaisie.Text.Trim())
' limpeza do campo de entrada
txtSaisie.Text = ""
' A Lista 1 não está vazia
btnEffacer1.Enabled = True
' foco volta para a caixa de entrada
txtSaisie.Focus()
End Sub
Destaque para o método Focus, que permite colocar o “foco” em um controle do formulário. O código associado ao clique nos botões Effacer:
' clique no botão Apagar1
Private Sub btnEffacer1_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnEffacer1.Click
' a lista 1 é apagada
listBox1.Items.Clear()
btnEffacer1.Enabled = False
End Sub
' clique no botão Apagar2
Private Sub btnEffacer2_Click(ByVal sender As Object, ByVal e As System.EventArgs)
' a lista 2 é apagada
listBox2.Items.Clear()
btnEffacer2.Enabled = False
End Sub
O código para transferir os elementos selecionados de uma lista para a outra:
' clique no botão btn1to2
Private Sub btn1TO2_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btn1TO2.Click
' transferência do item selecionado da Lista 1 para a Lista 2
transfert(listBox1, listBox2)
' Botões “Apagar”
btnEffacer2.Enabled = True
btnEffacer1.Enabled = listBox1.Items.Count <> 0
' botões de transferência
btn1TO2.Enabled = False
btn2TO1.Enabled = False
End Sub
' clique no botão btn2to1
Private Sub btn2TO1_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btn2TO1.Click
' transferência do item selecionado da Lista 2 para a Lista 1
transfert(listBox2, listBox1)
' botões Apagar
btnEffacer1.Enabled = True
btnEffacer2.Enabled = listBox2.Items.Count <> 0
' botões de transferência
btn1TO2.Enabled = False
btn2TO1.Enabled = False
End Sub
' transferência
Private Sub transfert(ByVal l1 As ListBox, ByVal l2 As ListBox)
' transferência do elemento selecionado da Lista 1 para a Lista 2
' um elemento selecionado?
If l1.SelectedIndex = -1 Then Return
' adicionar à l2
l2.Items.Add(l1.SelectedItem)
' exclusão em l1
l1.Items.RemoveAt(l1.SelectedIndex)
End Sub
Primeiro, criamos um método
Private Sub transfert(ByVal l1 As ListBox, ByVal l2 As ListBox)
que transfere para a lista l2 o elemento selecionado na lista l1. Isso nos permite ter um único método, em vez de dois, para transferir um elemento de listBox1 para listBox2 ou de listBox2 para listBox1. Antes de realizar a transferência, verificamos se há realmente um elemento selecionado na lista l1:
' um elemento selecionado?
If l1.SelectedIndex = -1 Then Return
A propriedade SelectedIndex tem o valor -1 se nenhum elemento estiver selecionado no momento. Nos procedimentos
Private Sub btnXTOY_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnXTOY.Click
é feita a transferência da lista X para a lista Y e altera-se o estado de alguns botões para refletir o novo estado das listas.
5.4.5. caixas de seleção CheckBox, botões de opção ButtonRadio
Propomos escrever o seguinte aplicativo:
![]() |
Os componentes da janela são os seguintes:
n.º | tipo | nome | função |
1 | RadioButton | radioButton1 radioButton2 radioButton3 | 3 botões de opção |
2 | CheckBox | chechBox1 chechBox2 chechBox3 | 3 caixas de seleção |
3 | ListBox | lstValeurs | uma lista |
Se criarmos os três botões de opção um após o outro, eles farão parte, por padrão, de um mesmo grupo. Portanto, quando um está marcado, os outros não estão. O evento que nos interessa para esses seis controles é o evento CheckChanged, que indica que o estado da caixa de seleção ou do botão de opção mudou. Esse estado é representado, nos dois casos, pela propriedade booleana Check, que, quando verdadeira, significa que o controle está marcado. Aqui, utilizamos um único método para tratar os seis eventos CheckChanged, o método affiche:
' exibe
Private Sub affiche(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles checkBox1.CheckedChanged, checkBox2.CheckedChanged, checkBox3.CheckedChanged, _
radioButton1.CheckedChanged, radioButton2.CheckedChanged, radioButton3.CheckedChanged
' exibe o estado do botão de opção ou da caixa de seleção
' é uma caixa de seleção?
If (TypeOf (sender) Is CheckBox) Then
Dim chk As CheckBox = CType(sender, CheckBox)
lstValeurs.Items.Insert(0, chk.Name & "=" & chk.Checked)
End If
' é um botão de opção?
If (TypeOf (sender) Is RadioButton) Then
Dim rdb As RadioButton = CType(sender, RadioButton)
lstValeurs.Items.Insert(0, rdb.Name & "=" & rdb.Checked)
End If
End Sub
A sintaxe TypeOf (remetente) Is CheckBox permite verificar se o objeto sender é do tipo CheckBox. Isso nos permite, em seguida, realizar uma conversão de tipo para o tipo exato de sender. O método affiche grava na lista lstValeurs o nome do componente que originou o evento e o valor de sua propriedade Checked. Durante a execução, observa-se que um clique em um botão de opção provoca dois eventos CheckChanged: um no botão anteriormente marcado, que passa para “desmarcado”, e outro no novo botão, que passa para “marcado”.
5.4.6. reguladores ScrollBar
Existem vários tipos de controladores: o controlador horizontal (hScrollBar), o variador vertical (vScrollBar) e o incrementador (NumericUpDown). | ![]() |
Vamos criar a seguinte aplicação:
![]() |
n.º | tipo | nome | função |
1 | hScrollBar | hScrollBar1 | um variador horizontal |
2 | hScrollBar | hScrollBar2 | um variador horizontal que acompanha as variações do variador 1 |
3 | TextBox | txtValeur | exibe o valor do variador horizontal ReadOnly=true para impedir qualquer entrada |
4 | NumericUpDown | incrementador | permite definir o valor do variador 2 |
- Um controlador ScrollBar permite que o usuário escolha um valor dentro de um intervalo de valores inteiros, representado pela “faixa” do controlador, sobre a qual se move um cursor. O valor do controlador está disponível na propriedade Value.
- Para um controlador horizontal, a extremidade esquerda representa o valor mínimo do intervalo, a extremidade direita o valor máximo e o cursor o valor atual selecionado. Para um controlador vertical, o mínimo é representado pela extremidade superior e o máximo pela extremidade inferior. Esses valores são representados pelas propriedades Minimum e Maximum e têm valores padrão de 0 e 100.
- Um clique nas extremidades do controle deslizante altera o valor em um incremento (positivo ou negativo), dependendo da extremidade clicada, denominada SmallChange, cujo valor padrão é 1.
- Um clique em qualquer lado do cursor altera o valor em um incremento (positivo ou negativo), dependendo da extremidade clicada, denominada LargeChange, cujo valor padrão é 10.
- Ao clicar na extremidade superior de um controle deslizante vertical, seu valor diminui. Isso pode surpreender o usuário comum, que normalmente espera ver o valor “aumentar”. Esse problema é resolvido atribuindo-se um valor negativo às propriedades SmallChange e LargeChange
- Essas cinco propriedades (Value, Minimum, Maximum, SmallChange, LargeChange) estão disponíveis para leitura e gravação.
- O principal evento do inversor é aquele que sinaliza uma alteração de valor: o evento Scroll.
Um componente NumericUpDown está próximo ao variador: ele também possui as propriedades Minimum, Maximum e Value, com valores padrão 0, 100, 0. Mas, neste caso, a propriedade Value é exibida em um campo de entrada que faz parte integrante do controle. O usuário pode alterar esse valor por conta própria, a menos que a propriedade ReadOnly do controle tenha sido definida como verdadeira. O valor do incremento é definido pela propriedade Increment, cujo valor padrão é 1. O principal evento do componente NumericUpDown é aquele que sinaliza uma alteração de valor: o evento ValueChanged. O código relevante da nossa aplicação é o seguinte:
O formulário é formatado durante sua construção:
' construtor
Public Sub New()
' criação inicial do formulário
InitializeComponent()
' atribuímos ao variador 2 as mesmas características do variador 1
hScrollBar2.Minimum = hScrollBar1.Value
hScrollBar2.Minimum = hScrollBar1.Minimum
hScrollBar2.Maximum = hScrollBar1.Maximum
hScrollBar2.LargeChange = hScrollBar1.LargeChange
hScrollBar2.SmallChange = hScrollBar1.SmallChange
' o mesmo vale para o incrementador
incrémenteur.Minimum = hScrollBar1.Value
incrémenteur.Minimum = hScrollBar1.Minimum
incrémenteur.Maximum = hScrollBar1.Maximum
incrémenteur.Increment = hScrollBar1.SmallChange
' atribui-se ao TextBox o valor do variador 1
txtValeur.Text = "" & hScrollBar1.Value
End Sub
O gerenciador que acompanha as variações de valor do inversor 1:
' gerenciamento do variador hscrollbar1
Private Sub hScrollBar1_Scroll(ByVal sender As Object, ByVal e As System.Windows.Forms.ScrollEventArgs) _
Handles hScrollBar1.Scroll
' alteração do valor do variador 1
' seu valor é repassado ao variador 2 e à caixa de texto TxtValeur
hScrollBar2.Value = hScrollBar1.Value
txtValeur.Text = "" & hScrollBar1.Value
End Sub
O gerenciador que monitora as variações de valor do variador 2:
' gerenciamento do variador hscrollbar2
Private Sub hScrollBar2_Scroll(ByVal sender As Object, ByVal e As System.Windows.Forms.ScrollEventArgs) _
Handles hScrollBar2.Scroll
' inibe-se qualquer alteração no variador 2
' forçando-o a manter o valor do variador 1
e.NewValue = hScrollBar1.Value
End Sub
O gerenciador que monitora as variações do controle incrémenteur:
' gerenciamento do incrementador
Private Sub incrémenteur_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles incrémenteur.ValueChanged
' fixa-se o valor do variador 2
hScrollBar2.Value = CType(incrémenteur.Value, Integer)
End Sub
5.5. Eventos do mouse
Ao desenhar em um contêiner, é importante saber a posição do mouse para, por exemplo, exibir um ponto ao clicar. Os movimentos do mouse geram eventos no contêiner em que ele se move.
![]() | ![]() |
o mouse acaba de entrar na área do controle | |
o mouse acabou de sair da área de controle | |
o mouse está se movendo na área de controle | |
Pressão no botão esquerdo do mouse | |
Solte o botão esquerdo do mouse | |
o usuário solta um objeto no controle | |
o usuário entra na área do controle arrastando um objeto | |
o usuário sai da área do controle arrastando um objeto | |
o usuário passa por cima da área do controle ao arrastar um objeto |
Aqui está um programa que ajuda a entender melhor em quais momentos ocorrem os diferentes eventos do mouse:
![]() |
n.º | tipo | nome | função |
1 | Etiqueta | lblPosition | para exibir a posição do mouse no formulário 1, na lista 2 ou no botão 3 |
2 | ListBox | lstEvts | para exibir eventos do mouse diferentes de MouseMove |
3 | Botão | btnEffacer | para apagar o conteúdo de 2 |
Os manipuladores de eventos são os seguintes. Para acompanhar os movimentos do mouse nos três controles, basta escrever um único manipulador:
' eventualmente form1_mousemove
Private Sub Form1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles MyBase.MouseMove, lstEvts.MouseMove, btnEffacer.MouseMove, lstEvts.MouseMove
' movimento do mouse — exibe-se as coordenadas (X, Y) do mouse
lblPosition.Text = "(" & e.X & "," & e.Y & ")"
End Sub
É importante saber que, sempre que o mouse entra na área de um controle, seu sistema de coordenadas muda. Sua origem (0,0) é o canto superior esquerdo do controle em que ele se encontra. Assim, durante a execução, ao passar o mouse do formulário para o botão, percebe-se claramente a mudança nas coordenadas. Para visualizar melhor essas mudanças no domínio do mouse, pode-se utilizar a propriedade Cursor dos controles:

Essa propriedade permite definir a forma do cursor do mouse quando ele entra na área do controle. Assim, em nosso exemplo, definimos o cursor como “Default” para o próprio formulário, “Hand” para a lista 2 e “No” para o botão 3, conforme mostram as capturas de tela abaixo.



No método [InitializeComponent], o código gerado por essas opções é o seguinte:
Me.lstEvts.Cursor = System.Windows.Forms.Cursors.Hand
Me.btnEffacer.Cursor = System.Windows.Forms.Cursors.No
Além disso, para detectar as entradas e saídas do mouse na lista 2, processamos os eventos MouseEnter e MouseLeave dessa mesma lista:
' eventualmente lstEvts_MouseEnter
Private Sub lstEvts_MouseEnter(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles lstEvts.MouseEnter
affiche("MouseEnter sur liste")
End Sub
' evento lstEvts_MouseLeave
Private Sub lstEvts_MouseLeave(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles lstEvts.MouseLeave
affiche("MouseLeave sur liste")
End Sub
' exibe
Private Sub affiche(ByVal message As String)
' a mensagem é exibida no topo da lista de eventos
lstEvts.Items.Insert(0, message)
End Sub

Para processar os cliques no formulário, processamos os eventos MouseDown e MouseUp:
' evento Form1_MouseDown
Private Sub Form1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles MyBase.MouseDown
affiche("MouseDown sur formulaire")
End Sub
' evento Form1_MouseUp
Private Sub Form1_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles MyBase.MouseUp
affiche("MouseUp sur formulaire")
End Sub

Por fim, o código do manipulador de cliques no botão Effacer:
' evento btnEffacer_Click
Private Sub btnEffacer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles btnEffacer.Click
' apaga a lista de eventos
lstEvts.Items.Clear()
End Sub
5.6. Criar uma janela com menu
Vamos ver agora como criar uma janela com menu. Vamos criar a seguinte janela:
![]() |
O controle 1 é um TextBox somente leitura (ReadOnly=true) e tem o nome txtStatut. A árvore do menu é a seguinte:
![]() | ![]() |
As opções de menu são controles, assim como os demais componentes visuais, e possuem propriedades e eventos. Por exemplo, a tabela de propriedades da opção de menu A1:

Duas propriedades são utilizadas em nosso exemplo:
o nome do controle de menu | |
o texto da opção do menu |
As propriedades das diferentes opções de menu do nosso exemplo são as seguintes:
Name | Texto |
mnuA | opções A |
mnuA1 | A1 |
mnuA2 | A2 |
mnuA3 | A3 |
mnuB | opções B |
mnuB1 | B1 |
mnuSep1 | - (separador) |
mnuB2 | B2 |
mnuB3 | B3 |
mnuB31 | B31 |
mnuB32 | B32 |
Para criar um menu, selecione o componente “MainMenu” na barra “ToolBox”:

Assim, obtém-se um menu vazio que é inserido no formulário com campos em branco intitulados “Type Here”. Basta indicar neles as diferentes opções do menu:

Para inserir um separador entre duas opções, como acima entre as opções B1 e B2, posicione o cursor no local do separador no menu, clique com o botão direito e selecione a opção “Insert Separator”:

Se iniciarmos o aplicativo com Ctrl+F5, obtemos um formulário com um menu que, por enquanto, não faz nada. As opções do menu são tratadas como componentes: elas possuem propriedades e eventos. Em [fenêtre de code], selecione o componente mnuA1 e, em seguida, selecione os eventos associados:

Se, no exemplo acima, gerarmos o evento Click, o VS.NET gera automaticamente o seguinte procedimento:
Private Sub mnuA1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles mnuA.Click
....
End Sub
Poderíamos proceder dessa forma para todas as opções do menu. Aqui, o mesmo procedimento pode ser utilizado para todas as opções. Portanto, renomeamos o procedimento anterior para affiche e declaramos os eventos que ele gerencia:
Private Sub affiche(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles mnuA1.Click, mnuA2.Click, mnuB1.Click, mnuB2.Click, mnuB31.Click, mnuB32.Click
' exibe no TextBox o nome do submenu selecionado
txtStatut.Text = (CType(sender, MenuItem)).Text
End Sub
Nesse método, limitamo-nos a exibir a propriedade Text da opção de menu na origem do evento. A origem do evento sender é do tipo object. As opções de menu são do tipo MenuItem; portanto, somos obrigados aqui a realizar uma conversão de tipo de object para MenuItem. Execute o aplicativo e selecione a opção A1 para obter a seguinte mensagem:

O código relevante deste aplicativo, além do do método affiche, é o da construção do menu no construtor do formulário (InitializeComponent):
Private Sub InitializeComponent()
Me.mainMenu1 = New System.Windows.Forms.MainMenu
Me.mnuA = New System.Windows.Forms.MenuItem
Me.mnuA1 = New System.Windows.Forms.MenuItem
Me.mnuA2 = New System.Windows.Forms.MenuItem
Me.mnuA3 = New System.Windows.Forms.MenuItem
Me.mnuB = New System.Windows.Forms.MenuItem
Me.mnuB1 = New System.Windows.Forms.MenuItem
Me.mnuB2 = New System.Windows.Forms.MenuItem
Me.mnuB3 = New System.Windows.Forms.MenuItem
Me.mnuB31 = New System.Windows.Forms.MenuItem
Me.mnuB32 = New System.Windows.Forms.MenuItem
Me.txtStatut = New System.Windows.Forms.TextBox
Me.mnuSep1 = New System.Windows.Forms.MenuItem
Me.SuspendLayout()
'
' mainMenu1
'
Me.mainMenu1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuA, Me.mnuB})
'
' mnuA
'
Me.mnuA.Index = 0
Me.mnuA.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuA1, Me.mnuA2, Me.mnuA3})
Me.mnuA.Text = "Options A"
'
' mnuA1
'
Me.mnuA1.Index = 0
Me.mnuA1.Text = "A1"
'
' mnuA2
'
Me.mnuA2.Index = 1
Me.mnuA2.Text = "A2"
'
' mnuA3
'
Me.mnuA3.Index = 2
Me.mnuA3.Text = "A3"
'
' mnuB
'
Me.mnuB.Index = 1
Me.mnuB.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuB1, Me.mnuSep1, Me.mnuB2, Me.mnuB3})
Me.mnuB.Text = "Options B"
'
' mnuB1
'
Me.mnuB1.Index = 0
Me.mnuB1.Text = "B1"
'
' mnuB2
'
Me.mnuB2.Index = 2
Me.mnuB2.Text = "B2"
'
' mnuB3
'
Me.mnuB3.Index = 3
Me.mnuB3.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuB31, Me.mnuB32})
Me.mnuB3.Text = "B3"
'
' mnuB31
'
Me.mnuB31.Index = 0
Me.mnuB31.Text = "B31"
'
' mnuB32
'
Me.mnuB32.Index = 1
Me.mnuB32.Text = "B32"
'
' txtStatut
'
Me.txtStatut.Location = New System.Drawing.Point(8, 8)
Me.txtStatut.Name = "txtStatut"
Me.txtStatut.ReadOnly = True
Me.txtStatut.Size = New System.Drawing.Size(112, 20)
Me.txtStatut.TabIndex = 0
Me.txtStatut.Text = ""
'
' mnuSep1
'
Me.mnuSep1.Index = 1
Me.mnuSep1.Text = "-"
'
' Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(136, 42)
Me.Controls.Add(txtStatut)
Me.Menu = Me.mainMenu1
Me.Name = "Form1"
Me.Text = "Menus"
Me.ResumeLayout(False)
End Sub
Observe a instrução que associa o menu ao formulário:
Me.Menu = Me.mainMenu1
5.7. Componentes não visuais
Vamos agora nos concentrar em alguns componentes não visuais: eles são utilizados durante o projeto, mas não são visíveis durante a execução.
5.7.1. Caixas de diálogo OpenFileDialog e SaveFileDialog
Vamos construir o seguinte aplicativo:
![]() |
Os controles são os seguintes:
Nº | tipo | nome | função |
1 | TextBox multilinhas | txtTexte | texto digitado pelo usuário ou carregado de um arquivo |
2 | Botão | btnSauvegarder | permite salvar o texto de 1 em um arquivo de texto |
3 | Botão | btnCharger | permite carregar o conteúdo de um arquivo de texto em 1 |
4 | Botão | btnEffacer | apaga o conteúdo de 1 |
São utilizados dois controles não visuais:

Quando selecionados no “ToolBox” e inseridos no formulário, eles são posicionados em uma área separada na parte inferior do formulário. Os componentes “Dialog” são selecionados no “ToolBox”:

O código do botão Effacer é simples:
Private Sub btnEffacer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnEffacer.Click
' a caixa de entrada é apagada
txtTexte.Text = ""
End Sub
A classe SaveFileDialog é definida da seguinte forma:

Ela deriva de vários níveis de classe. Dentre essas inúmeras propriedades e métodos, destacaremos os seguintes:
os tipos de arquivos disponíveis na lista suspensa de tipos de arquivos da caixa de diálogo | |
o número do tipo de arquivo proposto por padrão na lista acima. Começa em 0. | |
a pasta exibida inicialmente para salvar o arquivo | |
o nome do arquivo de backup indicado pelo usuário | |
método que exibe a caixa de diálogo de salvamento. Retorna um resultado do tipo DialogResult. |
O método ShowDialog exibe uma caixa de diálogo semelhante à seguinte:
![]() |
lista suspensa criada a partir da propriedade Filter. O tipo de arquivo proposto por padrão é definido por FilterIndex | |
pasta atual, definida por InitialDirectory caso essa propriedade tenha sido preenchida | |
nome do arquivo escolhido ou digitado diretamente pelo usuário. Estará disponível na propriedade FileName | |
botões Salvar/Cancelar. Se o botão Enregistrer for utilizado, a função ShowDialog retorna o resultado DialogResult.OK |
O procedimento de salvamento pode ser escrito da seguinte forma:
Private Sub btnSauvegarder_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnSauvegarder.Click
' salva-se o campo de entrada em um arquivo de texto
' configura-se a caixa de diálogo savefileDialog1
saveFileDialog1.InitialDirectory = Application.ExecutablePath
saveFileDialog1.Filter = "Fichiers texte (*.txt)|*.txt|Tous les fichiers (*.*)|*.*"
saveFileDialog1.FilterIndex = 0
' exibe-se a caixa de diálogo e recupera-se seu resultado
If saveFileDialog1.ShowDialog() = DialogResult.OK Then
' recupera-se o nome do arquivo
Dim nomFichier As String = saveFileDialog1.FileName
Dim fichier As StreamWriter = Nothing
Try
' abre-se o arquivo para gravação
fichier = New StreamWriter(nomFichier)
' escreva o texto aqui
fichier.Write(txtTexte.Text)
Catch ex As Exception
' problema
MessageBox.Show("Problème à l'écriture du fichier (" + ex.Message + ")", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
Finally
' fecha-se o arquivo
Try
fichier.Close()
Catch
End Try
End Try
End If
End Sub
- Associa-se a pasta inicial à pasta que contém o executável do aplicativo:
- Definimos os tipos de arquivos a serem apresentados
Observe-se a sintaxe dos filtros: filtro1|filtro2|..|filtroi, com filtroi = Texto|modelo de arquivo. Aqui, o usuário poderá escolher entre arquivos *.txt e *.*.
- Definimos o tipo de arquivo a ser exibido no início
Aqui, os arquivos do tipo *.txt serão exibidos em primeiro lugar para o usuário.
- A caixa de diálogo é exibida e seu resultado é recuperado
If saveFileDialog1.ShowDialog() = DialogResult.OK Then
- Enquanto a caixa de diálogo está exibida, o usuário não tem mais acesso ao formulário principal (caixa de diálogo chamada modal). O usuário define o nome do arquivo a ser salvo e sai da caixa de diálogo clicando no botão “Salvar”, no botão “Cancelar” ou fechando a caixa de diálogo. O resultado do método ShowDialog é DialogResult.OK apenas se o usuário tiver usado o botão Enregistrer para sair da caixa de diálogo.
- Feito isso, o nome do arquivo a ser criado está agora na propriedade FileName do objeto saveFileDialog1. Chega-se então à criação clássica de um arquivo de texto. Nele, escreve-se o conteúdo de TextBox: txtTexte.Text, ao mesmo tempo em que se gerencia as exceções que possam ocorrer.
A classe OpenFileDialog é muito semelhante à classe SaveFileDialog e deriva da mesma linhagem de classes. Dessas propriedades e métodos, destacaremos os seguintes:
os tipos de arquivos disponíveis na lista suspensa de tipos de arquivos da caixa de diálogo | |
o número do tipo de arquivo proposto por padrão na lista acima. Começa em 0. | |
a pasta exibida inicialmente para a busca do arquivo a ser aberto | |
o nome do arquivo a ser aberto indicado pelo usuário | |
método que exibe a caixa de diálogo de salvamento. Retorna um resultado do tipo DialogResult. |
O método ShowDialog exibe uma caixa de diálogo semelhante à seguinte:
![]() |
lista suspensa criada a partir da propriedade Filter. O tipo de arquivo proposto por padrão é definido por FilterIndex | |
pasta atual, definida por InitialDirectory caso essa propriedade tenha sido preenchida | |
nome do arquivo escolhido ou digitado diretamente pelo usuário. Estará disponível na propriedade FileName | |
botões Abrir/Cancelar. Se o botão Ouvrir for utilizado, a função ShowDialog retorna o resultado DialogResult.OK |
O procedimento de abertura pode ser escrito da seguinte forma:
Private Sub btnCharger_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnCharger.Click
' carrega-se um arquivo de texto na caixa de entrada
' configura-se a caixa de diálogo openfileDialog1
openFileDialog1.InitialDirectory = Application.ExecutablePath
openFileDialog1.Filter = "Fichiers texte (*.txt)|*.txt|Tous les fichiers (*.*)|*.*"
openFileDialog1.FilterIndex = 0
' exibe-se a caixa de diálogo e obtém-se seu resultado
If openFileDialog1.ShowDialog() = DialogResult.OK Then
' recupera-se o nome do arquivo
Dim nomFichier As String = openFileDialog1.FileName
Dim fichier As StreamReader = Nothing
Try
' abre-se o arquivo para leitura
fichier = New StreamReader(nomFichier)
' lê-se todo o arquivo e ele é colocado no TextBox
txtTexte.Text = fichier.ReadToEnd()
Catch ex As Exception
' problema
MessageBox.Show("Problème à la lecture du fichier (" + ex.Message + ")", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
Finally
' fecha-se o arquivo
Try
fichier.Close()
Catch
End Try
End Try
End If
End Sub
- Define-se a pasta inicial como a pasta que contém o executável do aplicativo:
- Definem-se os tipos de arquivos a serem apresentados
- Define-se o tipo de arquivo a ser exibido no início
Nesse caso, os arquivos do tipo *.txt serão exibidos em primeiro lugar ao usuário.
- A caixa de diálogo é exibida e seu resultado é recuperado
If openFileDialog1.ShowDialog() = DialogResult.OK Then
Enquanto a caixa de diálogo está exibida, o usuário não tem mais acesso ao formulário principal (caixa de diálogo chamada modal). O usuário define o nome do arquivo a ser aberto e sai da caixa de diálogo clicando no botão Abrir, no botão Cancelar ou fechando a caixa. O resultado do método ShowDialog é DialogResult.OK apenas se o usuário tiver usado o botão Ouvrir para sair da caixa de diálogo.
- Feito isso, o nome do arquivo a ser criado agora está na propriedade FileName do objeto openFileDialog1. Passa-se então para a leitura clássica de um arquivo de texto. Observe o método que permite ler um arquivo na íntegra:
- o conteúdo do arquivo é colocado no TextBox txtTexte. As exceções que possam ocorrer são tratadas.
5.7.2. Caixas de diálogo FontColor e ColorDialog
Damos continuidade ao exemplo anterior, apresentando dois novos botões:
![]() |
N.º | tipo | nome | função |
6 | Botão | btnCouleur | para definir a cor dos caracteres do TextBox |
7 | Botão | btnPolice | para definir a fonte do TextBox |
Inserimos no formulário um controle ColorDialog e um controle FontDialog:

As classes FontDialog e ColorDialog possuem um método ShowDialog análogo ao método ShowDialog das classes OpenFileDialog e SaveFileDialog. O método ShowDialog da classe ColorDialog permite selecionar uma cor:

Se o usuário fechar a caixa de diálogo com o botão OK, o resultado do método ShowDialog é DialogResult.OK e a cor selecionada está na propriedade Color do objeto ColorDialog utilizado. O método ShowDialog da classe FontDialog permite selecionar uma fonte:

Se o usuário fechar a caixa de diálogo com o botão OK, o resultado do método ShowDialog é DialogResult.OK e a fonte selecionada está na propriedade Font do objeto FontDialog utilizado. Temos os elementos para processar os cliques nos botões Couleur e Police:
Private Sub btnCouleur_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnCouleur.Click
' escolha de uma cor de texto
If colorDialog1.ShowDialog() = DialogResult.OK Then
' altera-se a propriedade forecolor do TextBox
txtTexte.ForeColor = colorDialog1.Color
End If
End Sub
Private Sub btnPolice_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnPolice.Click
' escolha de uma fonte
If fontDialog1.ShowDialog() = DialogResult.OK Then
' alterar a propriedade font do TextBox
txtTexte.Font = fontDialog1.Font
End If
End Sub
5.7.3. Timer
Propomos aqui escrever o seguinte aplicativo:
![]() |
n.º | Tipo | Nome | Função |
1 | TextBox, ReadOnly=true | txtChrono | exibe um cronômetro |
2 | Botão | btnArretMarche | botão de parar/iniciar o cronômetro |
3 | Temporizador | timer1 | componente que emite um evento a cada segundo |
O cronômetro em funcionamento:

O cronômetro parado:

Para alterar a cada segundo o conteúdo de TextBox e txtChrono, precisamos de um componente que gere um evento a cada segundo, evento esse que poderemos interceptar para atualizar a exibição do cronômetro. Esse componente é o Timer:

Depois que esse componente for instalado no formulário (na seção de componentes não visuais), um objeto do tipo Timer é criado no construtor do formulário. A classe System.Windows.Forms.Timer é definida da seguinte forma:

Dentre suas propriedades, destacaremos apenas as seguintes:
número de milissegundos após o qual um evento Tick é emitido. | |
o evento gerado ao final de Interval milissegundos | |
torna o temporizador ativo (true) ou inativo (false) |
No nosso exemplo, o temporizador se chama timer1 e timer1.Interval está definido para 1000 ms (1 s). O evento Tick ocorrerá, portanto, a cada segundo. O clique no botão Parar/Iniciar é processado pelo seguinte procedimento:
Private Sub btnArretMarche_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnArretMarche.Click
' parar ou continuar?
If btnArretMarche.Text = "Marche" Then
' anotamos a hora de início
début = DateTime.Now
' exibimos a hora
txtChrono.Text = "00:00:00"
' inicia-se o cronômetro
timer1.Enabled = True
' alterar o texto do botão
btnArretMarche.Text = "Arrêt"
' fim
Return
End If '
If btnArretMarche.Text = "Arrêt" Then
' parada do cronômetro
timer1.Enabled = False
' alterar o texto do botão
btnArretMarche.Text = "Marche"
' fim
Return
End If
End Sub
Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles timer1.Tick
' passou um segundo
Dim maintenant As DateTime = DateTime.Now
Dim durée As TimeSpan = DateTime.op_Subtraction(maintenant, début)
txtChrono.Text = "" + durée.Hours.ToString("d2") + ":" + durée.Minutes.ToString("d2") + ":" + durée.Seconds.ToString("d2")
End Sub
O texto do botão Parar/Iniciar é “Parar” ou “Iniciar”. Portanto, é necessário verificar esse texto para saber o que fazer.
- No caso de “Ligar”, registra-se a hora de início em uma variável global do objeto formulário, o temporizador é iniciado (Enabled=true) e o texto do botão muda para “Desligar”.
- No caso de “Parar”, o temporizador é desativado (Enabled=false) e o texto do botão passa a ser “Ligar”.
Public Class Timer1
Inherits System.Windows.Forms.Form
Private WithEvents timer1 As System.Windows.Forms.Timer
Private WithEvents btnArretMarche As System.Windows.Forms.Button
Private components As System.ComponentModel.IContainer
Private WithEvents txtChrono As System.Windows.Forms.TextBox
Private WithEvents label1 As System.Windows.Forms.Label
' variáveis de instância
Private début As DateTime
O atributo début acima é reconhecido em todos os métodos da classe. Resta-nos tratar o evento Tick no objeto timer1, evento que ocorre a cada segundo:
Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles timer1.Tick
' um segundo se passou
Dim maintenant As DateTime = DateTime.Now
Dim durée As TimeSpan = DateTime.op_Subtraction(maintenant, début)
txtChrono.Text = "" + durée.Hours.ToString("d2") + ":" + durée.Minutes.ToString("d2") + ":" + durée.Seconds.ToString("d2")
End Sub
Calcula-se o tempo decorrido desde o momento em que o cronômetro foi iniciado. Obtemos um objeto do tipo TimeSpan que representa um intervalo de tempo. Esse intervalo deve ser exibido no cronômetro no formato hh:mm:ss. Para isso, utilizamos as propriedades Hours, Minutes, Seconds do objeto TimeSPan, que representam, respectivamente, as horas, minutos e segundos da duração que exibimos no formato ToString("d2") para obter uma exibição com 2 dígitos.
5.8. O exemplo IMPOTS
Retomamos a aplicação IMPOTS, já abordada duas vezes. Agora, adicionamos a ela uma interface gráfica:
![]() |
Os controles são os seguintes
n.º | tipo | nome | função |
RadioButton | rdOui | marcado se for casado | |
RadioButton | rdNon | marcado se solteiro | |
NumericUpDown | incEnfants | número de filhos do contribuinte Mínimo=0, Máximo=20, Incremento=1 | |
TextBox | txtSalaire | salário anual do contribuinte em F | |
TextBox | txtImpots | valor do imposto a pagar ReadOnly=true | |
Botão | btnCalculer | inicia o cálculo do imposto | |
Botão | btnEffacer | Restaura o formulário ao seu estado inicial ao carregar | |
Botão | btnQuitter | para sair do aplicativo |
Regras de funcionamento
- o botão “Calcular” permanece desativado enquanto não houver nada no campo do salário
- se, ao iniciar o cálculo, verificar-se que o salário está incorreto, o erro é sinalizado:

O programa está apresentado abaixo. Ele utiliza a classe impot, criada no capítulo sobre classes. Uma parte do código gerado automaticamente pela classe VS.NET não foi reproduzida aqui.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
' opções
Option Explicit On
Option Strict On
' espaços de nomes
Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Data
' classe de formulário
Public Class frmImpots
Inherits System.Windows.Forms.Form
Private WithEvents label1 As System.Windows.Forms.Label
Private WithEvents rdOui As System.Windows.Forms.RadioButton
Private WithEvents rdNon As System.Windows.Forms.RadioButton
Private WithEvents label2 As System.Windows.Forms.Label
Private WithEvents txtSalaire As System.Windows.Forms.TextBox
Private WithEvents label3 As System.Windows.Forms.Label
Private WithEvents label4 As System.Windows.Forms.Label
Private WithEvents groupBox1 As System.Windows.Forms.GroupBox
Private WithEvents btnCalculer As System.Windows.Forms.Button
Private WithEvents btnEffacer As System.Windows.Forms.Button
Private WithEvents btnQuitter As System.Windows.Forms.Button
Private WithEvents txtImpots As System.Windows.Forms.TextBox
Private components As System.ComponentModel.Container = Nothing
Private WithEvents incEnfants As System.Windows.Forms.NumericUpDown
' tabelas de dados necessárias para o cálculo do imposto
Private limites() As Decimal = {12620D, 13190D, 15640D, 24740D, 31810D, 39970D, 48360D, 55790D, 92970D, 127860D, 151250D, 172040D, 195000D, 0D}
Private coeffR() As Decimal = {0D, 0.05D, 0.1D, 0.15D, 0.2D, 0.25D, 0.3D, 0.35D, 0.4D, 0.45D, 0.55D, 0.5D, 0.6D, 0.65D}
Private coeffN() As Decimal = {0D, 631D, 1290.5D, 2072.5D, 3309.5D, 4900D, 6898.5D, 9316.5D, 12106D, 16754.5D, 23147.5D, 30710D, 39312D, 49062D}
' objeto de imposto
Private objImpôt As impot = Nothing
Public Sub New()
InitializeComponent()
' inicialização do formulário
btnEffacer_Click(Nothing, Nothing)
btnCalculer.Enabled = False
' criação de um objeto de imposto
Try
objImpôt = New impot(limites, coeffR, coeffN)
Catch ex As Exception
MessageBox.Show("Impossible de créer l'objet impôt (" + ex.Message + ")", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error)
' desativa-se o campo de entrada do salário
txtSalaire.Enabled = False
End Try 'try-catch
End Sub
Protected Overloads Sub Dispose(ByVal disposing As Boolean)
....
End Sub
Private Sub InitializeComponent()
Me.btnQuitter = New System.Windows.Forms.Button
Me.groupBox1 = New System.Windows.Forms.GroupBox
Me.btnEffacer = New System.Windows.Forms.Button
Me.btnCalculer = New System.Windows.Forms.Button
Me.txtSalaire = New System.Windows.Forms.TextBox
Me.label1 = New System.Windows.Forms.Label
Me.label2 = New System.Windows.Forms.Label
Me.label3 = New System.Windows.Forms.Label
Me.rdNon = New System.Windows.Forms.RadioButton
Me.txtImpots = New System.Windows.Forms.TextBox
Me.label4 = New System.Windows.Forms.Label
Me.rdOui = New System.Windows.Forms.RadioButton
Me.incEnfants = New System.Windows.Forms.NumericUpDown
Me.groupBox1.SuspendLayout()
CType(Me.incEnfants, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
....
End Sub 'InitializeComponent
Public Shared Sub Main()
Application.Run(New frmImpots)
End Sub 'Main
Private Sub btnEffacer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnEffacer.Click
' Limpar o formulário
incEnfants.Value = 0
txtSalaire.Text = ""
txtImpots.Text = ""
rdNon.Checked = True
End Sub 'btnEffacer_Click
Private Sub txtSalaire_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtSalaire.TextChanged
' estado do botão “Calcular”
btnCalculer.Enabled = txtSalaire.Text.Trim() <> ""
End Sub 'txtSalaire_TextChanged
Private Sub btnQuitter_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnQuitter.Click
' fim do aplicativo
Application.Exit()
End Sub 'btnQuitter_Click
Private Sub btnCalculer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnCalculer.Click
' O salário está correto?
Dim intSalaire As Integer = 0
Try
' recuperação do salário
intSalaire = Integer.Parse(txtSalaire.Text)
' deve ser >=0
If intSalaire < 0 Then
Throw New Exception("")
End If
Catch ex As Exception
' mensagem de erro
MessageBox.Show(Me, "Salaire incorrect", "Erreur de saisie", MessageBoxButtons.OK, MessageBoxIcon.Error)
' foco no campo com erro
txtSalaire.Focus()
' seleção do texto do campo de entrada
txtSalaire.SelectAll()
' retorno à interface visual
Return
End Try 'try-catch
' o salário está correto — calcula-se o imposto
txtImpots.Text = "" & CLng(objImpôt.calculer(rdOui.Checked, CInt(incEnfants.Value), intSalaire))
End Sub 'btnCalculer_Click
End Class
Utilizamos aqui o arquivo de montagem impots.dll, resultado da compilação da classe impots do capítulo 2. Vale lembrar que esse arquivo de montagem pode ser gerado no modo de console por meio do comando
Esse comando gera o arquivo impots.dll, chamado de assembly. Esse assembly pode ser utilizado posteriormente em diversos projetos. Aqui, em nosso projeto sob VS.NET, utilizamos a janela de propriedades do projeto:

Para adicionar uma referência (um conjunto), clicamos com o botão direito do mouse no conjunto-chave “Referências” acima, selecionamos a opção [Ajouter une référence] e indicamos o conjunto [impots.dll], que nos certificamos de colocar na pasta do projeto:
dos>dir
01/03/2004 14:39 9 250 gui_impots.vb
01/03/2004 14:37 4 096 impots.dll
01/03/2004 14:41 12 288 gui_impots.exe
Depois de incluir o assembly [impots.dll] no projeto, a classe [impots] passa a ser reconhecida pelo projeto. Antes disso, ela não era reconhecida. Outro método é incluir o código-fonte impots.vb no projeto. Para isso, na janela de propriedades do projeto, clica-se com o botão direito do mouse no projeto, seleciona-se a opção [Ajouter/Ajouter un élément existant] e indica-se o arquivo impots.vb.















































