Você está na página 1de 228

Contents

Windows Forms
Guia de introdução ao Windows Forms
Visão geral dos Windows Forms
Criando um novo formulário do Windows Forms
Como: criar um aplicativo do Windows Forms na linha de comando
Coordenadas do Windows Forms
Criando manipuladores de eventos no Windows Forms
Visão geral sobre eventos
Visão geral de manipuladores de eventos
Como: criar manipuladores de eventos em tempo de execução para o Windows
Forms
Como: conectar vários eventos a um único manipulador de eventos no Windows
Forms
Ordem dos eventos em formulários do Windows Forms
Ajustar o tamanho e a escala do Windows Forms
Como: redimensionar o Windows Forms
Dimensionamento automático no Windows Forms
Como: responder a alterações no esquema de fontes em um aplicativo do
Windows Forms
Suporte a alto a DPI no Windows Forms
Alterando a aparência do Windows Forms
Como: alterar as bordas do Windows Forms
Controles de Windows Forms
Entrada do usuário no Windows Forms
Entrada do usuário em um aplicativo do Windows Forms
Entrada do teclado em um aplicativo do Windows Forms
Como a entrada do teclado funciona
Usando eventos do teclado
Como: modificar a entrada do teclado para um controle padrão
Como: determinar qual tecla modificadora foi pressionada
Como: manipular a entrada do teclado no nível do formulário
Entrada do mouse em um aplicativo do Windows Forms
Como a entrada do mouse funciona no Windows Forms
Eventos do mouse no Windows Forms
Como: distinguir entre cliques e cliques duplos
Ponteiros do mouse no Windows Forms
Captura do mouse no Windows Forms
Funcionalidade de arrastar e soltar no Windows Forms
Como: simular eventos de mouse e teclado no código
Como: manipular eventos de entrada do usuário em controles do Windows Forms
Validação da entrada do usuário no Windows Forms
Caixas de diálogo no Windows Forms
Como: exibir caixas de diálogo para o Windows Forms
Associação de dados do Windows Forms
Associação de dados e o Windows Forms
Fontes de dados com suporte do Windows Forms
Interfaces relacionadas à associação de dados
Notificação de alteração na associação de dados do Windows Forms
Como: aplicar o padrão PropertyNameChanged
Como: criar um controle associado e formatar os dados exibidos
Como: criar um controle associado simples em um Windows Form
Como: assegurar que vários controles associados à mesma fonte de dados
permaneçam sincronizados
Como: assegurar que a linha selecionada em uma tabela filho permaneça na posição
correta
Como: implementar a interface IListSource
Como: implementar a interface INotifyPropertyChanged
Como: implementar a interface ITypedList
Como: navegar por dados nos Windows Forms
Segurança do Windows Forms
Visão geral da Segurança do Windows Forms
Acesso mais seguro a arquivos e dados no Windows Forms
Impressão mais segura no Windows Forms
Considerações adicionais sobre Segurança do Windows Forms
Implantação do ClickOnce para o Windows Forms
Aprimoramentos de acessibilidade com o .NET Core 3.0
Como: acessar coleções indexadas por chave no Windows Forms
Aprimorando aplicativos do Windows Forms
Windows Forms
03/02/2020 • 3 minutes to read • Edit Online

Como os formulários são a unidade base do seu aplicativo, é essencial dedicar certo planejamento às suas funções
e design. Um formulário é basicamente uma tela em branco que você, como desenvolvedor, aprimora com
controles para criar uma interface do usuário e com código para manipular os dados. Para esse fim, o Visual Studio
fornece um ambiente de desenvolvimento integrado (IDE) para auxiliar na escrita de código, bem como um
conjunto de controle rico escrito com o .NET Framework. Complementando a funcionalidade desses controles com
seu código, você poderá desenvolver as soluções que precisa com rapidez e facilidade.

Nesta seção
Introdução ao Windows Forms
Fornece links para tópicos sobre como aproveitar a capacidade dos Windows Forms para exibir dados, manipular
entradas do usuário e implantar seus aplicativos com facilidade e com uma segurança mais robusta.
Aprimorando aplicativos do Windows Forms
Fornece links para tópicos sobre como aprimorar seu Windows Forms com uma variedade de recursos.

Seções Relacionadas
Controles dos Windows Forms
Contém links para tópicos que descrevem os controles de Windows Forms e mostram como implementá-los.
Associação de dados do Windows Forms
Contém links para tópicos que descrevem a arquitetura de associação de dados dos Windows Forms.
Visão geral de elementos gráficos
Discute como criar elementos gráficos, desenhar texto e manipular imagens gráficas como objetos usando a
implementação avançada da interface de design gráfico do Windows.
Segurança e implantação do ClickOnce
Discute os princípios da implantação do ClickOnce.
Diferenças de programação entre o Windows Forms e o MFC
Discute as diferenças entre aplicativos MFC e o Windows Forms.
Acessando dados no Visual Studio
Discute os aspectos da incorporação da funcionalidade de acesso a dados nos seus aplicativos.
Aplicativos dos Windows Forms
Discute o processo de depuração para aplicativos criados com o modelo de projeto de Aplicativos do Windows,
bem como alterar as configurações de Depuração e Versão.
Primeira olhada na implantação no Visual Studio
Descreve o processo pelo qual você distribui um componente ou aplicativo concluído para ser instalado em outros
computadores.
Compilando aplicativos de console
Descreve as noções básicas de criação de um aplicativo de console usando a classe Console.
Guia de introdução ao Windows Forms
03/02/2020 • 3 minutes to read • Edit Online

Com o Windows Forms você pode criar aplicativos potentes baseados em Windows. Os tópicos a seguir mostram
a fundo como aproveitar a capacidade dos Windows Forms para exibir dados, manipular entradas do usuário e
implantar seus aplicativos com facilidade e maior segurança.

Nesta seção
Visão geral dos Windows Forms
Contém uma visão geral dos aplicativos Windows Forms e smart client.
Criando um novo Windows Form
Contém links para tópicos que descrevem conceitos básicos para criar aplicativos nos Windows Forms.
Criando manipuladores de eventos no Windows Forms
Contém links para tópicos que descrevem como criar manipuladores de eventos nos Windows Forms.
Ajustando o tamanho e a escala dos Windows Forms
Contém links para tópicos que descrevem como ajustar o tamanho e a escala dos Windows Forms.
Alterando a aparência dos Windows Forms
Contém links para tópicos que mostram como mudar a aparência dos aplicativos dos Windows Forms.
Controles dos Windows Forms
Contém links para tópicos que descrevem e mostram como usar Windows Forms controles e componentes do.
Entrada do usuário no Windows Forms
Contém links para tópicos que descrevem e mostram como administrar entradas do usuário nos aplicativos dos
Windows Forms.
Caixas de diálogo nos Windows Forms
Contém links para tópicos que descrevem as diferentes caixas de diálogos para uso nos Windows Forms.
Associação de dados do Windows Forms
Contém links para tópicos que descrevem a arquitetura de vinculação de dados dos Windows Forms e como usá-
la nos aplicativos dos Windows Forms.
Segurança do Windows Forms
Contém links para tópicos que descrevem como compilar aplicativos para Windows Forms com segurança
reforçada.
Implantação do ClickOnce para Windows Forms
Contém links para tópicos que descrevem como implantar facilmente aplicativos para Windows Forms.
Como acessar coleções indexadas por chave nos Windows Forms
Demonstra como acessar coleções com chaves ao invés de índices.

Seções Relacionadas
Aprimorando aplicativos do Windows Forms
Contém links para tópicos que descrevem conceitos mais avançados para criar aplicativos para Windows Forms.
Visão geral de Windows Forms
03/02/2020 • 14 minutes to read • Edit Online

A visão geral a seguir descreve as vantagens dos aplicativos cliente inteligentes, os principais recursos de
programação dos Windows Forms e como você pode usar o Windows Forms para criar clientes inteligentes que
atendem às necessidades de empresas e usuários finais de hoje.

Aplicativos Windows Forms e Smart Client


Com o Windows Forms, você desenvolve clientes inteligentes. Clientes inteligentes são aplicativos graficamente
ricos que são fáceis de implantar e atualizar, podem funcionar quando eles estão conectados ou desconectados da
Internet e podem acessar recursos no computador local de maneira mais segura do que os aplicativos tradicionais
baseados no Windows.
Crie interfaces de usuário sofisticadas e interativas
Windows Forms é uma tecnologia de cliente inteligente para o .NET Framework, um conjunto de bibliotecas
gerenciadas que simplificam tarefas comuns de aplicativos, como leitura e gravação no sistema de arquivos.
Quando você usa um ambiente de desenvolvimento como o Visual Studio, pode criar Windows Forms aplicativos
de cliente inteligente que exibem informações, solicitam a entrada de usuários e se comunicam com computadores
remotos em uma rede.
nos Windows Forms, um formulário é uma superfície visual na qual são exibidas informações para o usuário.
Normalmente, os aplicativos dos Windows Forms são compilados com o acréscimo de controles a formulários e de
respostas de desenvolvimento a ações do usuário, como cliques do mouse ou pressionamentos de teclas. Um
controle é um elemento discreto de interface do usuário que exibe dados ou aceita a entrada de dados.
Quando um usuário executa alguma ação em seu formulário ou em um de seus controles, a ação gera um evento.
O seu aplicativo reage a esses eventos usando código e os processa quando eles acontecem. Para obter mais
informações, consulte Criando manipuladores de eventos nos Windows Forms.
O Windows Forms contém uma variedade de controles que podem ser adicionados aos formulários: controles que
exibem caixas de texto, botões, caixas suspensas, botões de opção e até mesmo páginas da Web. Para obter uma
lista de todos os controles que podem ser usados em um formulário, consulte Controles que podem ser usados
nos Windows Forms. Se um controle existente não atender às suas necessidades, Windows Forms também dará
suporte à criação de seus próprios controles personalizados usando a classe UserControl.
O Windows Forms tem controles avançados de interface do usuário que emulam recursos em aplicativos de alta
tecnologia, como o Microsoft Office. Ao usar o ToolStrip e o controle de MenuStrip, você pode criar barras de
ferramentas e menus que contêm texto e imagens, exibir submenus e hospedar outros controles, como caixas de
texto e caixas de combinação.
Com o Designer de formulários do Windows do tipo "arrastar e soltar" no Visual Studio, você pode facilmente
criar Windows Forms aplicativos. Basta selecionar os controles com o seu cursor e adicioná-los no local do
formulário desejado. O designer oferece ferramentas como linhas de grade e linhas de alinhamento para facilitar o
alinhamento dos controles. E se você usar o Visual Studio ou compilar na linha de comando, poderá usar os
controles FlowLayoutPanel, TableLayoutPanel e SplitContainer para criar layouts de formulário avançados em
menos tempo.
Por fim, se você precisar criar seus próprios elementos personalizados de interface do usuário, o namespace
System.Drawing conterá uma grande seleção de classes para processar linhas, círculos e outras formas
diretamente em um formulário.
NOTE
Os controles dos Windows Forms não são projetados para a realização de marshaling entre domínios de aplicativo. Por esse
motivo, a Microsoft não dá suporte à passagem de um controle de Windows Forms em um limite de AppDomain, mesmo
que o tipo base Control de MarshalByRefObject pareça indicar que isso é possível. Os aplicativos dos Windows Forms que
têm vários domínios de aplicativo têm suporte, desde que nenhum controle dos Windows Forms seja passado entre limites
de domínio de aplicativo.

Criar formulários e controles


Para obter informações passo a passo sobre como usar esses recursos, consulte os seguintes tópicos da Ajuda.

DESC RIÇ Ã O TÓ P IC O DA A JUDA

Usando controles em formulários Como Adicionar Controles ao Windows Forms

Usando o controle de ToolStrip Como criar um ToolStrip básico com itens padrão usando o
designer

Criando gráficos com System.Drawing Introdução à Programação de Elementos Gráficos

Criando controles personalizados Como herdar da classe UserControl

Exibir e manipular dados


Muitos aplicativos precisam exibir dados obtidos de um banco de dados, de um arquivo XML, de um serviço Web
XML ou de outra fonte de dados. Windows Forms fornece um controle flexível chamado de controle de
DataGridView para exibir esses dados tabulares em um formato de linha e coluna tradicional, para que cada parte
dos dados ocupe sua própria célula. Ao usar DataGridView, você pode personalizar a aparência de células
individuais, bloquear linhas e colunas arbitrárias em vigor e exibir controles complexos dentro de células, entre
outros recursos.
A conexão a fontes de dados pela rede é uma tarefa simples com clientes inteligentes dos Windows Forms. O
componente BindingSource representa uma conexão com uma fonte de dados e expõe métodos para associação
de dados a controles, navegando até os registros anteriores e seguintes, editando registros e salvando as
alterações de volta na fonte original. O controle BindingNavigator fornece uma interface simples sobre o
componente BindingSource para que os usuários naveguem entre os registros.
É possível criar facilmente controles de associação de dados usando a janela Fontes de Dados. A janela exibe fontes
de dados como bancos de dados, serviços Web e objetos em seu projeto. Você pode criar controles de associação
de dados ao arrastar itens dessa janela para os formulários do seu projeto. Você também pode associar controles
existentes a dados ao arrastar objetos da janela Fontes de Dados para eles.
Outro tipo de vinculação de dados que você pode gerenciar nos Windows Forms é chamado de configurações. A
maioria dos aplicativos de cliente inteligente deve manter algumas informações sobre seu estado de tempo de
execução, como o último tamanho de formulário conhecido e reter dados de preferência do usuário, como os
locais padrão para os arquivos salvos. O recurso de configuração de aplicativo lida com esses requisitos ao
oferecer uma forma fácil de armazenar ambos os tipos de configuração no computador cliente. Depois de definir
essas configurações usando o Visual Studio ou um editor de código, as configurações são mantidas como XML e
são automaticamente lidas de volta na memória em tempo de execução.
Exibir e manipular dados
Para obter informações passo a passo sobre como usar esses recursos, consulte os seguintes tópicos da Ajuda.
DESC RIÇ Ã O TÓ P IC O DA A JUDA

Usando o componente BindingSource Como associar controles dos Windows Forms ao componente
BindingSource usando o designer

Trabalhando com fontes de dados ADO.NET Como classificar e filtrar dados ADO.NET com o componente
BindingSource dos Windows Forms

Usando a janela de Fontes de Dados Associando controles do Windows Forms a dados no Visual
Studio

Usando configurações de aplicativo Como criar configurações de aplicativo

Implantar aplicativos em computadores cliente


Depois de escrever o seu aplicativo, você precisa enviá-lo para seus usuários para que eles possam instalá-lo e
executá-lo em seus próprios computadores cliente. Ao usar a tecnologia ClickOnce, você pode implantar seus
aplicativos de dentro do Visual Studio usando apenas alguns cliques e fornecer aos usuários uma URL apontando
para seu aplicativo na Web. O ClickOnce gerencia todos os elementos e dependências em seu aplicativo e garante
que o aplicativo esteja instalado corretamente no computador cliente.
Os aplicativos ClickOnce podem ser configurados para serem executados somente quando o usuário estiver
conectado à rede ou para serem executados online e offline. Quando você especifica que um aplicativo deve dar
suporte à operação offline, o ClickOnce adiciona um link ao seu aplicativo no menu Iniciar do usuário. O usuário
pode, em seguida, abrir o aplicativo sem usar a URL.
Quando você atualiza o seu aplicativo, publica um novo manifesto de implantação e uma nova cópia do seu
aplicativo em seu servidor Web. O ClickOnce detectará que há uma atualização disponível e atualizará a instalação
do usuário; nenhuma programação personalizada é necessária para atualizar assemblies antigos.
Implantar aplicativos ClickOnce
Para obter uma introdução completa ao ClickOnce, consulte segurança e implantação do ClickOnce. Para
informações passo a passo sobre como usar esses recursos, consulte os seguintes tópicos da Ajuda,

DESC RIÇ Ã O TÓ P IC O DA A JUDA

Implantando um aplicativo usando o ClickOnce Como publicar um aplicativo ClickOnce usando o Assistente
de Publicação

Passo a passo: implantando um aplicativo ClickOnce


manualmente

Atualizando uma implantação do ClickOnce Como gerenciar atualizações para um aplicativo ClickOnce

Gerenciando a segurança com o ClickOnce Como habilitar configurações de segurança do ClickOnce

Outros controles e recursos


Existem muitos outros recursos dos Windows Forms que tornam as tarefas comuns de implementação mais fáceis
e rápidas, como o suporte à criação de caixas de diálogo, impressão, adição da Ajuda e de documentação e
localização do seu aplicativo para diversos idiomas. Além disso, Windows Forms se baseia no robusto sistema de
segurança do .NET Framework. Com esse sistema, você pode liberar aplicativos mais seguros a seus clientes.
Implementar outros controles e recursos
Para obter informações passo a passo sobre como usar esses recursos, consulte os seguintes tópicos da Ajuda.
DESC RIÇ Ã O TÓ P IC O DA A JUDA

Imprimindo o conteúdo de um formulário Como Imprimir Elementos Gráficos nos Windows Forms

Como Imprimir um Arquivo de Texto de Várias Páginas nos


Windows Forms

Saiba mais sobre a segurança dos Windows Forms Visão geral da segurança dos Windows Forms

Consulte também
Introdução ao Windows Forms
Criando um novo Windows Form
Visão geral do controle ToolStrip
Visão geral do controle DataGridView
Visão geral do componente BindingSource
Visão Geral das Configurações do Aplicativo
Segurança e implantação do ClickOnce
Criando um novo formulário do Windows Forms
23/10/2019 • 2 minutes to read • Edit Online

Este tópico contém links para tópicos que descrevem como criar seu primeiro aplicativo de formulários do
Windows. Além disso, os tópicos nesta seção apresentam algumas das vocabulário básico e diretrizes que você
deve compreender quando você começa a criar um aplicativo Windows Forms. Para saber mais sobre aplicativos
do Windows Forms, os controles que você pode usar neles, eventos e manipulação de eventos e como lidar com a
entrada do usuário, consulte a lista de tópicos relacionados.

Nesta seção
Coordenadas dos formulários do Windows.
Descreve as coordenadas de cliente e da tela.
Como: Criar um aplicativo de formulários do Windows da linha de comando
Descreve como criar um formulário básico do Windows e compilá-lo na linha de comando.

Referência
Form
Descreve essa classe e contém links para todos os seus membros.
Control
Descreve essa classe e contém links para todos os seus membros.

Seções relacionadas
Manipulando a entrada do usuário
Contém links para tópicos que discutem a entrada do usuário e como tratá-la em aplicativos de formulários do
Windows.
Criando manipuladores de eventos no Windows Forms
Contém links para tópicos que descrevem como manipular eventos em aplicativos do Windows Forms.
Alterando a aparência dos Windows Forms
Contém links para tópicos que mostram como mudar a aparência dos aplicativos dos Windows Forms.
Controles dos Windows Forms por função
Contém links para tópicos que descrevem os controles que você pode usar em aplicativos do Windows Forms.
Como: Criar um aplicativo do Windows Forms a
partir da linha de comando
20/03/2020 • 6 minutes to read • Edit Online

Os procedimentos a seguir descrevem as etapas básicas que devem ser concluídas para criar e executar um
aplicativo do Windows Forms na linha de comando. Há um suporte abrangente para esses procedimentos no
Visual Studio. Veja também o Passo a Passo: Hospedando um controle de formulários do Windows no WPF.

Procedimento
Criar o formulário
1. Em um arquivo de código Imports using vazio, digite as seguintes declarações ou instruções:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms

2. Declare uma Form1 classe nomeada que herda da classe Formulário:

public class Form1 : Form

Public Class Form1


Inherits Form

3. Crie um construtor sem Form1 parâmetros para .


Mais código será adicionado ao construtor em um procedimento subsequente.

public Form1() {}

Public Sub New()

End Sub

4. Adicione o método Main à classe.


a. Aplique STAThreadAttribute o método Main C# para especificar que o aplicativo Windows Forms é
um apartamento com um único segmento. (O atributo não é necessário no Visual Basic, uma vez que
o Windows forma aplicativos desenvolvidos com o Visual Basic usar um modelo de apartamento
com um threaded por padrão.)
b. Chamada EnableVisualStyles para aplicar estilos do sistema operacional à sua aplicação.
c. Crie uma instância do formulário e execute-o.

[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}

Public Shared Sub Main()


Application.EnableVisualStyles()
Application.Run(New Form1())

End Sub
End Class

Compilar e executar o aplicativo


1. No prompt de comando do .NET Framework, navegue até o diretório em que a classe Form1 foi criada.
2. Compile o formulário.
Se você estiver usando o C#, digite: csc form1.cs

-or-

Se estiver usando Visual Basic, digite: vbc form1.vb

3. No prompt de comando, digite: Form1.exe

Adicionando um controle e manipulando um evento


As etapas do procedimento anterior demonstraram como criar um formulário básico do Windows Forms que
compila e executa. O procedimento a seguir mostra como criar e adicionar um controle ao formulário e manipular
um evento para o controle. Para obter mais informações sobre os controles que podem ser adicionados a
formulários do Windows Forms, consulte Controles do Windows Forms.
Além de entender como criar aplicativos do Windows Forms, é necessário compreender a programação baseada
em eventos e como tratar a entrada do usuário. Para obter mais informações, consulte Criando Manipuladores de
Eventos no Windows Forms e Tratando a Entrada do Usuário
Declarar um controle de botão e manipular o evento de clique
1. Declare um controle de botão chamado button1 .
2. Na construtora, crie o botão Sizee Location Text defina suas propriedades e propriedades.
3. Adicione o botão ao formulário.
O exemplo de código a seguir demonstra como declarar o controle do botão:
public Button button1;
public Form1()
{
button1 = new Button();
button1.Size = new Size(40, 40);
button1.Location = new Point(30, 30);
button1.Text = "Click me";
this.Controls.Add(button1);
button1.Click += new EventHandler(button1_Click);
}

Public WithEvents button1 As Button

Public Sub New()


button1 = New Button()
button1.Size = New Size(40, 40)
button1.Location = New Point(30, 30)
button1.Text = "Click me"
Me.Controls.Add(button1)

End Sub

4. Crie um método Click para lidar com o evento para o botão.


5. No manipulador de eventos MessageBox do clique, exiba um com a mensagem" Hello World".
O exemplo de código a seguir demonstra como lidar com o evento de clique do controle do botão:

private void button1_Click(object sender, EventArgs e)


{
MessageBox.Show("Hello World");
}

Private Sub button1_Click(ByVal sender As Object, _


ByVal e As EventArgs) Handles button1.Click
MessageBox.Show("Hello World")
End Sub

6. Associe o Click evento com o método que você criou.


O exemplo de código a seguir demonstra como associar o evento ao método.

button1.Click += new EventHandler(button1_Click);

Private Sub button1_Click(ByVal sender As Object, _


ByVal e As EventArgs) Handles button1.Click

7. Compile e execute o aplicativo, conforme descrito no procedimento anterior.

Exemplo
O exemplo de código a seguir é o exemplo completo dos procedimentos anteriores:
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace FormWithButton
{
public class Form1 : Form
{
public Button button1;
public Form1()
{
button1 = new Button();
button1.Size = new Size(40, 40);
button1.Location = new Point(30, 30);
button1.Text = "Click me";
this.Controls.Add(button1);
button1.Click += new EventHandler(button1_Click);
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Hello World");
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
}
}

Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms

Public Class Form1


Inherits Form
Public WithEvents button1 As Button

Public Sub New()


button1 = New Button()
button1.Size = New Size(40, 40)
button1.Location = New Point(30, 30)
button1.Text = "Click me"
Me.Controls.Add(button1)

End Sub

Private Sub button1_Click(ByVal sender As Object, _


ByVal e As EventArgs) Handles button1.Click
MessageBox.Show("Hello World")
End Sub

<STAThread()> _
Shared Sub Main()
Application.EnableVisualStyles()
Application.Run(New Form1())

End Sub
End Class

Confira também
Form
Control
Alterando a aparência dos Windows Forms
Aprimorando aplicativos do Windows Forms
Introdução ao Windows Forms
Coordenadas do Windows Forms
03/02/2020 • 3 minutes to read • Edit Online

O sistema de coordenadas para um Windows Form é baseado nas coordenadas de dispositivo e a unidade básica
de medida de desenho no Windows Forms é a unidade do dispositivo (normalmente, o pixel). Pontos na tela são
descritos por pares de coordenadas x e y, com as coordenadas x aumentando para a direita e coordenadas y
aumentando de cima para baixo. O local de origem, em relação à tela, variará dependendo se você está
especificando as coordenadas de tela ou de cliente.

Coordenadas de tela
Um Aplicativo do Windows Forms especifica a posição de uma janela na tela em coordenadas de tela. Para
coordenadas de tela, a origem é o canto superior esquerdo da tela. A posição completa de uma janela geralmente
é descrita por uma estrutura de Rectangle que contém as coordenadas de tela de dois pontos que definem os
cantos superior esquerdo e inferior direito da janela.

Coordenadas de cliente
Um Aplicativo do Windows Forms especifica a posição dos pontos em um formulário ou controle usando
coordenadas de cliente. A origem das coordenadas de cliente é o canto superior esquerdo da área de cliente do
controle ou formulário. Coordenadas de cliente garantem que um aplicativo pode usar valores de coordenadas
consistentes ao desenhar em um formulário ou controle, independentemente da posição do formulário ou
controle na tela.
As dimensões da área do cliente também são descritas por uma estrutura de Rectangle que contém as
coordenadas do cliente para a área. Em todos os casos, a coordenada superior esquerda do retângulo está incluída
na área de cliente, enquanto a coordenada inferior direita é excluída. Operações de elementos gráficos não incluem
bordas direita e inferiores de uma área de cliente. Por exemplo, o método FillRectangle preencherá a borda direita
e inferior do retângulo especificado, mas não incluirá essas bordas.

Mapeamento de um tipo de coordenada para outro


Ocasionalmente, pode ser recomendável mapear das coordenadas de tela para as coordenadas de cliente. Você
pode fazer isso facilmente usando os métodos PointToClient e PointToScreen disponíveis na classe Control. Por
exemplo, a propriedade MousePosition de Control é relatada em coordenadas da tela, mas talvez você queira
convertê-las em coordenadas do cliente.

Consulte também
PointToClient
PointToScreen
Criando manipuladores de eventos no Windows
Forms
03/02/2020 • 2 minutes to read • Edit Online

Um manipulador de eventos é um procedimento no seu código que determina quais ações são executadas
quando ocorre um evento, por exemplo, quando o usuário clica em um botão ou uma fila de mensagens recebe
uma mensagem. Quando um evento é gerado, o manipulador ou manipuladores de eventos que receberão o
evento são executados. Os eventos podem ser atribuídos a vários manipuladores e os métodos que manipulam
os eventos particulares podem ser alterados dinamicamente. Você também pode usar o Designer de Formulários
do Windows no Visual Studio para criar manipuladores de eventos.

Nesta seção
Visão geral de eventos
Explica o modelo de evento e a função das classes delegate.
Visão geral do manipulador de eventos
Descreve como manipular eventos.
Como criar manipuladores de eventos em tempo de execução para Windows Forms
Fornece instruções para responder a eventos de sistema ou de usuário de forma dinâmica.
Como: conectar vários eventos a um único manipulador de eventos no Windows Forms
Fornece instruções para atribuir a mesma funcionalidade a vários controles por meio de eventos.
Ordem de eventos em Windows Forms
Descreve a ordem em que os eventos são gerados em controles Windows Forms.
Como criar manipuladores de eventos usando o designer Descreve como usar o Designer de Formulários do
Windows para criar manipuladores de eventos.

Seções Relacionadas
Eventos
Fornece links para tópicos sobre como manipular e gerar eventos usando o .NET Framework.
Solucionando problemas de manipuladores de eventos herdados no Visual Basic
Lista problemas comuns que ocorrem com os manipuladores de eventos em componentes herdados.
Visão geral sobre eventos (Windows Forms)
03/02/2020 • 6 minutes to read • Edit Online

Um evento é uma ação a qual você pode responder ou "manipular", no código. Os eventos podem ser gerados
por uma ação do usuário, como o clicar do mouse ou pressionar de uma tecla, pelo código de programa ou pelo
sistema.
Os aplicativos controlados por eventos executam código em resposta a um evento. Cada formulário e controle
expõe um conjunto predefinido de eventos com base nos quais você pode programar. Se um desses eventos
ocorre e não há código no manipulador de evento associado, esse código é invocado.
Os tipos de eventos gerados por um objeto variam, mas muitos tipos são comuns à maioria dos controles. Por
exemplo, a maioria dos objetos lidará com um evento Click. Se um usuário clicar em um formulário, o código no
manipulador de eventos Click do formulário é executado.

NOTE
Muitos eventos ocorrem com outros eventos. Por exemplo, enquanto o evento DoubleClick ocorre, os eventos
MouseDown, MouseUp e Click ocorrem.

Para obter informações sobre como gerar e consumir um evento, consulte eventos.

Classes delegate e suas funções


Delegados são classes comumente usadas dentro do .NET Framework para criar mecanismos de manipulação de
eventos. Delegados são quase equivalentes a ponteiros de função, comumente C++ usados no Visual e em outras
linguagens orientadas a objeto. No entanto, diferente dos ponteiros de função, as classes delegate são orientadas
a objeto, fortemente tipadas e seguras. Além disso, quando um ponteiro de função contém apenas uma referência
a uma função particular, uma classe delegate consiste em uma referência a um objeto, e as referências a um ou
mais métodos dentro do objeto.
Esse modelo de evento usa delegados para associar eventos aos métodos que são usados para tratá-los. A classe
delegate permite que outras classes se registrem para a notificação de eventos, especificando um método de
manipulador. Quando o evento ocorre, a classe delegate chama o método associado. Para obter mais informações
sobre como definir delegados, consulte eventos.
Essas classes podem ser associadas a um único método ou a vários métodos, o que chamamos de multicasting.
Ao criar um delegado para um evento, você (ou o Windows) normalmente cria um evento de multicast. Uma rara
exceção pode ser um evento que resulta em um procedimento específico (como a exibição de uma caixa de
diálogo) que não repetiria logicamente várias vezes por evento. Para obter informações sobre como criar um
delegado de multicast, consulte como combinar delegados (delegados de multicast).
Uma classe delegate multicast mantém uma lista de invocação dos métodos aos quais ela está associada. Essa
classe é compatível com um método Combine para adicionar um método à lista de invocação e um método
Remove para removê-lo.
Quando um evento é registrado pelo aplicativo, o controle gera o evento invocando a classe delegate para esse
evento. A classe delegate chama o método vinculado. No caso mais comum (uma classe delegate multicast) a
classe chama cada método associado da lista de invocação, que fornece uma notificação de um para muitos. Essa
estratégia significa que o controle não precisa manter uma lista de objetos de destino para notificação de eventos,
a classe delegate lida com todo o registro e notificação.
Essas classes também permitem que vários eventos sejam associados ao mesmo método, permitindo uma
notificação muitos para um. Por exemplo, um evento de clique de botão e um evento de clique de comando de
menu podem invocar a mesma classe delegate, que chama um único método para lidar com esses eventos
separados da mesma maneira.
O mecanismo de associação usado com essas classes é dinâmico: uma classe delegate pode ser associada em
tempo de execução a qualquer método cuja assinatura corresponda à assinatura do manipulador de eventos.
Com esse recurso, você pode configurar ou alterar o método associado de acordo com uma condição e anexar
dinamicamente um manipulador de eventos a um controle.

Consulte também
Criando manipuladores de eventos no Windows Forms
Visão geral de manipuladores de eventos
Visão geral de manipuladores de eventos (Windows
Forms)
20/03/2020 • 2 minutes to read • Edit Online

Um manipulador de eventos é um método que está associado a um evento. Quando o evento é gerado, o código
no manipulador de eventos é executado. Cada manipulador de eventos fornece dois parâmetros que permitem
manipular o evento corretamente. O exemplo a seguir mostra Button um Click manipulador de eventos para um
evento de controle.

Private Sub button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles button1.Click

End Sub

private void button1_Click(object sender, System.EventArgs e)


{

private:
void button1_Click(System::Object ^ sender,
System::EventArgs ^ e)
{

No primeiro parâmetro, sender , fornece uma referência ao objeto que gerou o evento. No exemplo acima, o
segundo parâmetro, e , passa um objeto específico para o evento que está sendo manipulado. Consultando as
propriedades do objeto (e, às vezes, seus métodos), é possível obter informações como o local do mouse para
eventos de mouse ou dados que estão sendo transferidos em eventos do tipo "arrastar e soltar".
Normalmente, cada evento produz um manipulador de eventos com um tipo de objeto de evento diferente para
o segundo parâmetro. Alguns manipuladores de eventos, MouseDown MouseUp como aqueles para os eventos e
eventos, têm o mesmo tipo de objeto para o segundo parâmetro. Para esses tipos de eventos, você pode usar o
mesmo manipulador de eventos para manipular ambos os eventos.
Você também pode usar o mesmo manipulador de eventos para manipular o mesmo evento em controles
diferentes. Por exemplo, se você RadioButton tiver um grupo de controles em um formulário, você pode criar um
único manipulador de eventos para o evento e ter o Click evento de Click cada controle vinculado ao
manipulador de eventos único. Para obter mais informações, consulte Como conectar vários eventos a um único
manipulador de eventos nos Windows Forms.

Confira também
Criando manipuladores de eventos no Windows Forms
Visão geral de eventos
Como criar manipuladores de eventos em tempo de
execução para formulários do Windows Forms
03/02/2020 • 2 minutes to read • Edit Online

Além de criar eventos usando o Designer de Formulários do Windows no Visual Studio, você também pode criar
um manipulador de eventos em tempo de execução. Essa ação permite que você conecte manipuladores de
eventos com base em condições no código no tempo de execução em vez de conectá-los quando o programa
inicia.

Criar um manipulador de eventos em tempo de execução


1. Abra o formulário ao qual você deseja adicionar um manipulador de eventos.
2. Adicione um método ao seu formulário com a assinatura do método para o evento que deseja manipular.
Por exemplo, se você estivesse manipulando o evento de Click de um controle de Button, você criaria um
método como o seguinte:

Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)


' Add event handler code here.
End Sub

private void button1_Click(object sender, System.EventArgs e)


{
// Add event handler code here.
}

private:
void button1_Click(System::Object ^ sender,
System::EventArgs ^ e)
{
// Add event handler code here.
}

3. Adicione código ao manipulador de eventos conforme apropriado para seu aplicativo.


4. Determine para qual formulário ou controle deseja criar um manipulador de eventos.
5. Em um método na classe do formulário, adicione o código que especifica o manipulador de eventos para
manipular o evento. Por exemplo, o código a seguir especifica o manipulador de eventos button1_Click
manipula o evento Click de um controle de Button:

AddHandler Button1.Click, AddressOf Button1_Click

button1.Click += new EventHandler(button1_Click);

button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);


O método AddHandler demonstrado no código de Visual Basic acima estabelece um manipulador de
eventos de clique para o botão.

Consulte também
Criando manipuladores de eventos no Windows Forms
Visão geral de manipuladores de eventos
Solucionando problemas de manipuladores de eventos herdados no Visual Basic
Como conectar vários eventos a um único
manipulador de eventos no Windows Forms
03/02/2020 • 3 minutes to read • Edit Online

No projeto do seu aplicativo, talvez seja necessário usar um único manipulador de eventos para vários eventos ou
fazer com que vários eventos executem o mesmo procedimento. Por exemplo, fazer um comando de menu gerar
o mesmo evento que um botão no seu formulário geralmente representará uma grande economia de tempo se
eles expuserem a mesma funcionalidade. Você pode fazer isso usando a exibição Eventos da janela Propriedades
em C# ou usando a palavra-chave Handles e as caixas suspensas Nome de Classe e Nome do Método no
Editor de Código do Visual Basic.
Conectar vários eventos a um único manipulador de eventos no Visual Basic
1. Clique com o botão direito do mouse do formulário e escolha Exibir código .
2. Na caixa suspensa Nome de Classe , selecione um dos controles que você deseja que o manipulador de
eventos trate.
3. Na caixa suspensa Nome de Método , selecione um dos eventos que você deseja que o manipulador de
eventos trate.
4. O Editor de Código insere o manipulador de eventos apropriado e posiciona o ponto de inserção dentro do
método. No exemplo a seguir, é o evento Click para o controle Button.

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles


Button1.Click
' Add event-handler code here.
End Sub

5. Acrescente os outros eventos que você deseja que sejam tratados à cláusula Handles .

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles


Button1.Click, Button2.Click
' Add event-handler code here.
End Sub

6. Adicione o código apropriado ao manipulador de eventos.


Para conectar vários eventos a um único manipulador de eventos em C#
1. Selecione o controle ao qual você deseja conectar um manipulador de eventos.

2. No janela Propriedades, clique no botão eventos ( ).


3. Clique no nome do evento que você deseja tratar.
4. Na seção de valor ao lado do nome do evento, clique no botão da lista suspensa para exibir uma lista de
manipuladores de eventos existentes que correspondem à assinatura do método do evento que você
deseja tratar.
5. Selecione o manipulador de eventos apropriado na lista.
O código será adicionado ao formulário para associar o evento ao manipulador de eventos existente.
Consulte também
Criando manipuladores de eventos no Windows Forms
Visão geral de manipuladores de eventos
Ordem dos eventos em formulários do Windows
Forms
03/02/2020 • 2 minutes to read • Edit Online

A ordem na qual os eventos são gerados em aplicativos do Windows Forms é de interesse específico para os
desenvolvedores preocupados com tratamento de cada um desses eventos sucessivamente. Quando uma situação
exigir tratamento meticuloso de eventos, como quando você estiver redesenhando partes do formulário, será
necessário um reconhecimento da ordem exata na qual os eventos são gerados em tempo de execução. Este tópico
fornece alguns detalhes sobre a ordem dos eventos durante vários estágios importantes no tempo de vida de
aplicativos e controles. Para obter detalhes específicos sobre a ordem de eventos de entrada do mouse, consulte
Eventos de mouse no Windows Forms. Para obter uma visão geral de eventos no Windows Forms, consulte Visão
geral de eventos. Para obter detalhes sobre a composição de manipuladores de eventos, consulte Visão geral de
manipuladores de eventos.

Eventos de inicialização e desligamento de aplicativos


As classes Form e Control expõem um conjunto de eventos relacionados à inicialização e ao desligamento do
aplicativo. Quando um Aplicativo do Windows Forms é iniciado, os eventos de inicialização do formulário principal
são gerados na seguinte ordem:
Control.HandleCreated
Control.BindingContextChanged
Form.Load
Control.VisibleChanged
Form.Activated
Form.Shown
Quando um aplicativo é fechado, os eventos de desligamento do formulário principal são gerados na seguinte
ordem:
Form.Closing
Form.FormClosing
Form.Closed
Form.FormClosed
Form.Deactivate
O evento ApplicationExit da classe Application é gerado após os eventos de desligamento do formulário principal.

NOTE
Visual Basic 2005 inclui eventos de aplicativo adicionais, como WindowsFormsApplicationBase.Startup e
WindowsFormsApplicationBase.Shutdown.
Eventos de foco e validação
Quando você altera o foco usando o teclado (guia, SHIFT + TAB e assim por diante), chamando os métodos Select
ou SelectNextControl ou definindo a propriedade ActiveControl como o formulário atual, os eventos de foco da
classe Control ocorrem na seguinte ordem:
Enter
GotFocus
Leave
Validating
Validated
LostFocus
Quando você altera o foco usando o mouse ou chamando o método Focus, os eventos de foco da classe Control
ocorrem na seguinte ordem:
Enter
GotFocus
LostFocus
Leave
Validating
Validated

Consulte também
Criando manipuladores de eventos no Windows Forms
Ajustando o tamanho e a escala dos Formulários do
Windows
20/03/2020 • 2 minutes to read • Edit Online

Este tópico fornece links para informações sobre o redimensionamento de Formulários do Windows.

Nesta seção
Como redimensionar o Windows Forms
Fornece instruções para especificar o tamanho dos Formulários do Windows.
Dimensionamento automático em formulários do Windows
Discute como o dimensionamento automático permite que um formulário e seus controles sejam exibidos
adequadamente entre as máquinas.
Suporte a DPI alto em formulários windows Discute o suporte do Windows Forms para Alto DPI e
dimensionamento dinâmico.

Referência
Size
Descreve essa classe e tem links para todos os seus membros.
TableLayoutPanel
Descreve essa classe e tem links para todos os seus membros.
FlowLayoutPanel
Descreve essa classe e tem links para todos os seus membros.

Seções relacionadas
Alterando a aparência dos Formulários do Windows
Fornece links para tópicos descrevendo outras maneiras de alterar a aparência dos Formulários do Windows.
Como redimensionar formulários do Windows Forms
03/02/2020 • 3 minutes to read • Edit Online

Você pode especificar o tamanho do seu Windows Forms de várias maneiras. Você pode alterar a altura e a largura
do formulário programaticamente definindo um novo valor para a propriedade Size ou ajustar as propriedades
Height ou Width individualmente. Se você estiver usando o Visual Studio, poderá alterar o tamanho usando o
Designer de Formulários do Windows. Consulte também Como redimensionar Windows Forms usando o
Designer.

Redimensionar um formulário programaticamente


Defina o tamanho de um formulário em tempo de execução definindo a propriedade Size do formulário.
O exemplo de código a seguir mostra o tamanho do formulário definido como 100 x 100 pixels.

Form1.Size = New System.Drawing.Size(100, 100)

Form1.Size = new System.Drawing.Size(100, 100);

Form1->Size = System::Drawing::Size(100, 100);

Alterar a largura e a altura do formulário programaticamente


Depois que o Size for definido, altere a altura ou a largura do formulário usando as propriedades Width ou Height.
O exemplo de código a seguir mostra a largura do formulário definida para 300 pixels da borda esquerda do
formulário, enquanto a altura permanece constante.

Form1.Width = 300

Form1.Width = 300;

Form1->Width = 300;

-ou-
Altere Width ou Height definindo a propriedade Size.
No entanto, como mostra o exemplo de código a seguir, essa abordagem é mais complicada do que apenas definir
Width ou Height Propriedades.

Form1.Size = New Size(300, Form1.Size.Height)

Form1.Size = new Size(300, Form1.Size.Height);


Form1->Size = System::Drawing::Size(300, Form1->Size.Height);

Alterar o tamanho do formulário por incrementos programaticamente


Para incrementar o tamanho do formulário, defina as propriedades Width e Height.
O exemplo de código a seguir mostra a largura do formulário definida para 200 pixels mais larga do que a
configuração atual.

Form1.Width += 200

Form1.Width += 200;

Form1->Width += 200;

Cau t i on

Sempre use a propriedade Height ou Width para alterar uma dimensão de um formulário, a menos que você esteja
definindo dimensões de altura e largura ao mesmo tempo definindo a propriedade Size como uma nova estrutura
de Size. A propriedade Size retorna uma estrutura de Size, que é um tipo de valor. Não é possível atribuir um novo
valor para a propriedade de um tipo de valor. Portanto, o código a seguir não será compilado.

' NOTE: CODE WILL NOT COMPILE


Dim f As New Form()
f.Size.Width += 100

// NOTE: CODE WILL NOT COMPILE


Form f = new Form();
f.Size.Width += 100;

// NOTE: CODE WILL NOT COMPILE


Form^ f = gcnew Form();
f->Size->X += 100;

Consulte também
Introdução ao Windows Forms
Aprimorando aplicativos do Windows Forms
Dimensionamento automático no Windows Forms
03/02/2020 • 13 minutes to read • Edit Online

O dimensionamento automático permite que um formulário e seus controles, projetados em um computador com
determinada resolução de vídeo ou fonte do sistema, sejam exibidos adequadamente em outra máquina com uma
resolução de vídeo diferente ou fonte do sistema. Garante que o formulário e seus controles sejam
redimensionados de forma inteligente para serem consistentes com o Windows nativo e outros aplicativos nas
máquinas dos usuários e de outros desenvolvedores. O suporte do .NET Framework para dimensionamento
automático e estilos visuais permite que .NET Framework aplicativos mantenham uma aparência consistente em
comparação com os aplicativos nativos do Windows na máquina de cada usuário.
Na maior parte, o dimensionamento automático funciona conforme o esperado no .NET Framework versão 2,0 e
posterior. No entanto, as alterações no esquema de fontes podem ser problemáticas. Para obter um exemplo de
como resolver isso, consulte como responder a alterações de esquema de fonte em um aplicativo Windows Forms.

Necessidade de dimensionamento automático


Sem o dimensionamento automático, um aplicativo criado para uma resolução ou fonte de vídeo parecerá muito
pequeno ou muito grande quando a resolução ou a fonte for alterada. Por exemplo, se o aplicativo for projetado
usando o ponto Tahoma 9 como uma linha de base, sem ajuste, ele aparecerá muito pequeno se for executado em
um computador em que a fonte do sistema for Tahoma 12 Point. Elementos de texto, como títulos, menus,
conteúdo de caixa de texto e assim por diante, serão processados menores do que outros aplicativos. Além disso, o
tamanho dos elementos da interface do usuário que contêm texto, como a barra de título, os menus e muitos
controles, dependem da fonte usada. Neste exemplo, esses elementos também serão relativamente menores.
Uma situação análoga ocorre quando um aplicativo é projetado para uma determinada resolução de vídeo. A
resolução de vídeo mais comum é de 96 pontos por polegada (DPI), que é igual a 100% de escala de exibição, mas
a resolução mais alta é exibida com suporte a 125%, 150%, 200% (que, respectivamente, igual a 120, 144 e 192
DPI) e acima estão se tornando mais comuns. Sem ajuste, um aplicativo, especialmente um baseado em gráficos,
projetado para uma resolução aparecerá muito grande ou muito pequeno quando executado em outra resolução.
O dimensionamento automático busca amenizar esses problemas redimensionando automaticamente o
formulário e seus controles filho de acordo com o tamanho relativo da fonte ou a resolução da tela. O sistema
operacional Windows dá suporte ao dimensionamento automático de caixas de diálogo usando uma unidade
relativa de medida chamada unidades de caixa de diálogo. Uma unidade de caixa de diálogo é baseada na fonte do
sistema e sua relação com os pixels pode ser determinada, embora a função do SDK do Win32 GetDialogBaseUnits
. Quando um usuário altera o tema usado pelo Windows, todas as caixas de diálogo são ajustadas
automaticamente de acordo. Além disso, o .NET Framework dá suporte ao dimensionamento automático de
acordo com a fonte do sistema padrão ou a resolução de vídeo. Opcionalmente, o dimensionamento automático
pode ser desabilitado em um aplicativo.

Suporte original para dimensionamento automático


As versões 1,0 e 1,1 do .NET Framework o dimensionamento automático com suporte de uma maneira simples
que dependia da fonte padrão do Windows usada para a interface do usuário, representada pelo valor do SDK do
Win32 DEFAULT_GUI_FONT . Essa fonte geralmente é alterada apenas quando a resolução de vídeo muda. O
mecanismo a seguir foi usado para implementar o dimensionamento automático:
1. No momento do design, a propriedade AutoScaleBaseSize (que agora está preterida) foi definida com a
altura e a largura da fonte padrão do sistema no computador do desenvolvedor.
2. Em tempo de execução, a fonte padrão do sistema do computador do usuário foi usada para inicializar a
propriedade Font da classe Form.
3. Antes de exibir o formulário, o método ApplyAutoScaling foi chamado para dimensionar o formulário. Esse
método calculou os tamanhos de escala relativos de AutoScaleBaseSize e Font, em seguida, chamou o
método Scale para realmente dimensionar o formulário e seus filhos.
4. O valor de AutoScaleBaseSize foi atualizado para que as chamadas subsequentes para ApplyAutoScaling
não redimensionem progressivamente o formulário.
Embora esse mecanismo fosse suficiente para a maioria das finalidades, ele sofreu as seguintes limitações:
Como a propriedade AutoScaleBaseSize representa o tamanho da fonte da linha de base como valores
inteiros, ocorrem erros de arredondamento que se tornam evidentes quando um formulário é alternado por
várias resoluções.
O dimensionamento automático foi implementado apenas na classe Form, não na classe ContainerControl.
Como resultado, os controles de usuário seriam dimensionados corretamente somente quando o controle
de usuário foi projetado na mesma resolução que o formulário e foi colocado no formulário em tempo de
design.
Os formulários e seus controles filho só poderiam ser projetados simultaneamente por vários
desenvolvedores se suas resoluções de computador fossem as mesmas. Da mesma forma, ele também
tornou a herança de um formulário dependente da resolução associada ao formulário pai.
Ele não é compatível com os gerenciadores de layout mais recentes introduzidos com a versão 2,0 do .NET
Framework, como FlowLayoutPanel e TableLayoutPanel.
Ele não oferece suporte ao dimensionamento baseado diretamente na resolução de vídeo necessária para a
compatibilidade com o .NET Compact Framework.
Embora esse mecanismo seja preservado no .NET Framework versão 2,0 para manter a compatibilidade com
versões anteriores, ele foi substituído pelo mecanismo de dimensionamento mais robusto descrito a seguir. Como
consequência, a AutoScale, ApplyAutoScaling, AutoScaleBaseSizee determinadas sobrecargas de Scale são
marcadas como obsoletas.

NOTE
Você pode excluir com segurança as referências a esses membros ao atualizar seu código herdado para a versão .NET
Framework 2,0.

Suporte atual para dimensionamento automático


O .NET Framework versão 2,0 vence as limitações anteriores, introduzindo as seguintes alterações no
dimensionamento automático de Windows Forms:
O suporte base para dimensionamento foi movido para a classe ContainerControl de forma que todos os
formulários, controles compostos nativos e controles de usuário recebam suporte de dimensionamento
uniforme. Os novos membros AutoScaleFactor, AutoScaleDimensions, AutoScaleMode e PerformAutoScale
foram adicionados.
A classe Control também tem vários novos membros que permitem que ele participe do dimensionamento
e ofereça suporte ao dimensionamento misto no mesmo formato. Especificamente, os membros Scale,
ScaleChildrene GetScaledBounds dão suporte ao dimensionamento.
O suporte para dimensionamento com base na resolução da tela foi adicionado para complementar o
suporte à fonte do sistema, conforme definido pela enumeração de AutoScaleMode. Esse modo é
compatível com o dimensionamento automático com suporte no .NET Compact Framework permitindo
uma migração de aplicativo mais fácil.
A compatibilidade com gerenciadores de layout, como FlowLayoutPanel e TableLayoutPanel, foi adicionada à
implementação do dimensionamento automático.
Os fatores de dimensionamento agora são representados como valores de ponto flutuante, normalmente
usando a estrutura SizeF, de forma que os erros de arredondamento tenham sido praticamente eliminados.
Cau t i on

Não há suporte para mesclagens arbitrárias de DPI e modos de dimensionamento de fonte. Embora você possa
dimensionar um controle de usuário usando um modo (por exemplo, DPI) e colocá-lo em um formulário usando
outro modo (fonte) sem problemas, mas misturar um formulário base em um modo e um formulário derivado em
outro pode levar a resultados inesperados.
Dimensionamento automático em ação
O Windows Forms agora usa a seguinte lógica para dimensionar automaticamente os formulários e seus
conteúdos:
1. Em tempo de design, cada ContainerControl registra o modo de dimensionamento e a resolução atual no
AutoScaleMode e AutoScaleDimensions, respectivamente.
2. Em tempo de execução, a resolução real é armazenada na propriedade CurrentAutoScaleDimensions. A
propriedade AutoScaleFactor calcula dinamicamente a taxa entre a resolução de escala de tempo de
execução e de design.
3. Quando o formulário for carregado, se os valores de CurrentAutoScaleDimensions e AutoScaleDimensions
forem diferentes, o método PerformAutoScale será chamado para dimensionar o controle e seus filhos. Esse
método suspende o layout e chama o método Scale para executar o dimensionamento real. Posteriormente,
o valor de AutoScaleDimensions é atualizado para evitar o dimensionamento progressivo.
4. PerformAutoScale também é invocada automaticamente nas seguintes situações:
Em resposta ao evento OnFontChanged se o modo de dimensionamento for Font.
Quando o layout do controle de contêiner é retomado e uma alteração é detectada nas propriedades
AutoScaleDimensions ou AutoScaleMode.
Como implícito acima, quando um ContainerControl pai está sendo dimensionado. Cada controle de
contêiner é responsável por dimensionar seus filhos usando seus próprios fatores de
dimensionamento e não aquele de seu contêiner pai.
5. Os controles filho podem modificar seu comportamento de dimensionamento por vários meios:
A propriedade ScaleChildren pode ser substituída para determinar se os controles filho devem ser
dimensionados ou não.
O método GetScaledBounds pode ser substituído para ajustar os limites para os quais o controle é
dimensionado, mas não a lógica de dimensionamento.
O método ScaleControl pode ser substituído para alterar a lógica de dimensionamento do controle
atual.

Consulte também
AutoScaleMode
Scale
PerformAutoScale
AutoScaleDimensions
Renderizando controles com estilos visuais
Como Melhorar o Desempenho Evitando a Colocação em Escala Automática
Como responder a alterações no esquema de fontes
em um aplicativo do Windows Forms
03/02/2020 • 5 minutes to read • Edit Online

Nos sistemas operacionais Windows, um usuário pode alterar as configurações de fonte de todo o sistema para
tornar a fonte padrão maior ou menor. A alteração dessas configurações de fonte é essencial para usuários com
deficiência visual, que requerem letras maiores para ler o texto em suas telas. É possível ajustar seu aplicativo do
Windows Forms para reagir a essas alterações aumentando ou diminuindo o tamanho do formulário e todo o
texto contido nele sempre que o esquema de fontes for alterado. Se desejar que seu formulário acomode as
alterações em tamanhos de fonte dinamicamente, será possível adicionar código a ele.
Normalmente, a fonte padrão usada pelo Windows Forms é a fonte retornada pela chamada de namespace de
Microsoft.Win32 para GetStockObject(DEFAULT_GUI_FONT) . A fonte retornada por essa chamada muda apenas
quando a resolução da tela é alterada. Conforme mostrado no procedimento a seguir, seu código deve alterar a
fonte padrão para IconTitleFont para responder às alterações no tamanho da fonte.
Utilizar a fonte da área de trabalho e responder a alterações no esquema de fontes
1. Crie seu formulário e adicione os controles desejados a ele. Para obter mais informações, consulte Como
criar um aplicativo do Windows Forms na linha de comando e Controles para Uso no Windows Forms.
2. Adicione uma referência ao namespace Microsoft.Win32 ao seu código.

using Microsoft.Win32;

Imports Microsoft.Win32

3. Adicione o seguinte código ao construtor do formulário para ligar manipuladores de eventos necessários e
para alterar a fonte padrão em uso do formulário.

this.Font = SystemFonts.IconTitleFont;
SystemEvents.UserPreferenceChanged += new
UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);
this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);

Public Sub New()


' This call is required by the Windows Form Designer.
InitializeComponent()

' Add any initialization after the InitializeComponent() call.


AddHandler SystemEvents.UserPreferenceChanged, New UserPreferenceChangedEventHandler(AddressOf
SystemEvents_UserPreferenceChangesEventHandler)
End Sub

4. Implemente um manipulador para o evento UserPreferenceChanged que faz com que o formulário seja
dimensionado automaticamente quando a categoria de Window é alterada.
void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
{
if (e.Category == UserPreferenceCategory.Window)
{
this.Font = SystemFonts.IconTitleFont;
}
}

Private Sub SystemEvents_UserPreferenceChangesEventHandler(ByVal sender As Object, ByVal e As


UserPreferenceChangedEventArgs)
If (e.Category = UserPreferenceCategory.Window) Then
Me.Font = SystemFonts.IconTitleFont
End If
End Sub

5. Por fim, implemente um manipulador para o evento FormClosing que desanexa o manipulador de eventos
UserPreferenceChanged.

IMPORTANT
Uma falha na inclusão desse código fará com que ocorra vazamento de memória no aplicativo.

void Form1_FormClosing(object sender, FormClosingEventArgs e)


{
SystemEvents.UserPreferenceChanged -= new
UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);
}

Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As


System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
RemoveHandler SystemEvents.UserPreferenceChanged, New UserPreferenceChangedEventHandler(AddressOf
SystemEvents_UserPreferenceChangesEventHandler)
End Sub

6. Compile e execute o código.


Alterar manualmente o esquema de fontes no Windows XP
1. Enquanto o Aplicativo do Windows Forms está em execução, clique com o botão direito do mouse na área
de trabalho do Windows e escolha Propriedades no menu de atalho.
2. Na caixa de diálogo Propriedades de Exibição , clique na guia Aparência .
3. Na caixa de listagem suspensa Tamanho da Fonte , selecione um novo tamanho da fonte.
Você observará que o formulário agora reage às alterações de tempo de execução no esquema de fontes da
área de trabalho. Quando o usuário altera entre Normal , Fontes Grandes e Fontes Extra Grandes , o
formulário muda a fonte e ajusta a escala corretamente.

{1>Exemplo<1}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32;

namespace WinFormsAutoScaling
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();

this.Font = SystemFonts.IconTitleFont;
SystemEvents.UserPreferenceChanged += new
UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);
this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);
}

void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)


{
if (e.Category == UserPreferenceCategory.Window)
{
this.Font = SystemFonts.IconTitleFont;
}
}

void Form1_FormClosing(object sender, FormClosingEventArgs e)


{
SystemEvents.UserPreferenceChanged -= new
UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);
}
}
}

Imports Microsoft.Win32

Public Class Form1


Public Sub New()
' This call is required by the Windows Form Designer.
InitializeComponent()

' Add any initialization after the InitializeComponent() call.


AddHandler SystemEvents.UserPreferenceChanged, New UserPreferenceChangedEventHandler(AddressOf
SystemEvents_UserPreferenceChangesEventHandler)
End Sub

Private Sub SystemEvents_UserPreferenceChangesEventHandler(ByVal sender As Object, ByVal e As


UserPreferenceChangedEventArgs)
If (e.Category = UserPreferenceCategory.Window) Then
Me.Font = SystemFonts.IconTitleFont
End If
End Sub

Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As


System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
RemoveHandler SystemEvents.UserPreferenceChanged, New UserPreferenceChangedEventHandler(AddressOf
SystemEvents_UserPreferenceChangesEventHandler)
End Sub
End Class
O Construtor neste exemplo de código contém uma chamada para InitializeComponent , que é definida quando
você cria um novo projeto de Windows Forms no Visual Studio. Remova essa linha de código se estiver
compilando um aplicativo na linha de comando.

Consulte também
PerformAutoScale
Dimensionamento automático no Windows Forms
Suporte a alto DPI no Windows Forms
03/02/2020 • 7 minutes to read • Edit Online

A partir do .NET Framework 4,7, Windows Forms inclui aprimoramentos para cenários comuns de dpi e DPI
dinâmicos. Elas incluem:
Melhorias no dimensionamento e layout de vários controles de Windows Forms, como o controle de
MonthCalendar e o controle de CheckedListBox.
Escala de passagem única. No .NET Framework 4,6 e versões anteriores, o dimensionamento foi realizado
por meio de várias passagens, o que fazia com que alguns controles fosse escalado mais do que o
necessário.
Suporte para cenários de DPI dinâmico em que o usuário altera o fator de escala ou DPI depois que um
aplicativo de Windows Forms foi iniciado.
Nas versões do .NET Framework a partir do .NET Framework 4,7, o suporte a alto DPI avançado é um recurso
opcional. Você deve configurar seu aplicativo para tirar proveito dele.

Configurando seu aplicativo Windows Forms para suporte a alto DPI


Os novos recursos Windows Forms que dão suporte a reconhecimento de DPI alta estão disponíveis somente em
aplicativos direcionados para o .NET Framework 4,7 e estão em execução em sistemas operacionais Windows,
começando com a atualização do Windows 10 para criadores.
Além disso, para configurar o suporte de DPI alto no seu aplicativo Windows Forms, você deve fazer o seguinte:
Declare a compatibilidade com o Windows 10.
Para fazer isso, adicione o seguinte ao seu arquivo de manifesto:

<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 compatibility -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>

Habilite o reconhecimento de DPI por monitor no arquivo app. config .


Windows Forms introduz um novo elemento <System.Windows.Forms.ApplicationConfigurationSection> para
dar suporte a novos recursos e personalizações adicionadas a partir do .NET Framework 4,7. Para aproveitar
os novos recursos que dão suporte a DPI alto, adicione o seguinte ao arquivo de configuração do aplicativo.

<System.Windows.Forms.ApplicationConfigurationSection>
<add key="DpiAwareness" value="PerMonitorV2" />
</System.Windows.Forms.ApplicationConfigurationSection>

IMPORTANT
Nas versões anteriores do .NET Framework, você usou o manifesto para adicionar suporte a DPI alto. Essa
abordagem não é mais recomendada, já que ela substitui as configurações definidas no arquivo app. config.
Chame o método de EnableVisualStyles estático.
Deve ser a primeira chamada de método no ponto de entrada do aplicativo. Por exemplo:

static void Main()


{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form2());
}

Recusando recursos de DPI alta individuais


Definir o valor de DpiAwareness como PerMonitorV2 habilita todos os recursos de reconhecimento de DPI alto
suportados pelas versões .NET Framework começando com o .NET Framework 4,7. Normalmente, isso é adequado
para a maioria dos aplicativos Windows Forms. No entanto, talvez você queira recusar um ou mais recursos
individuais. O motivo mais importante para fazer isso é que o código do aplicativo existente já lida com esse
recurso. Por exemplo, se seu aplicativo lida com o dimensionamento automático, talvez você queira desabilitar o
recurso de redimensionamento automático da seguinte maneira:

<System.Windows.Forms.ApplicationConfigurationSection>
<add key="DpiAwareness" value="PerMonitorV2" />
<add key="EnableWindowsFormsHighDpiAutoResizing" value="false" />
</System.Windows.Forms.ApplicationConfigurationSection>

Para obter uma lista de chaves individuais e seus valores, consulte Windows Forms adicionar elemento de
configuração.

Novos eventos de alteração de DPI


A partir do .NET Framework 4,7, três novos eventos permitem que você manipule programaticamente alterações
de DPI dinâmicas:
DpiChangedAfterParent, que é disparado quando a configuração de DPI de um controle é alterada
programaticamente após um evento de alteração de DPI para o controle pai ou formulário ter ocorrido.
DpiChangedBeforeParent, que é acionado quando a configuração de DPI de um controle é alterada
programaticamente antes de um evento de alteração de DPI para seu controle pai ou formulário ter ocorrido.
DpiChanged, que é disparado quando a configuração de DPI é alterada no dispositivo de vídeo onde o
formulário está atualmente exibido.

Novos métodos auxiliares e propriedades


O .NET Framework 4,7 também adiciona uma série de novos métodos auxiliares e propriedades que fornecem
informações sobre o dimensionamento de DPI e permitem que você execute o dimensionamento de DPI. Elas
incluem:
LogicalToDeviceUnits, que converte um valor dos pixels lógicos para de dispositivo.
ScaleBitmapLogicalToDevice, que dimensiona uma imagem de bitmap para o DPI lógico de um dispositivo.
DeviceDpi, que retorna o DPI para o dispositivo atual.

Considerações sobre controle de versão


Além de ser executado na atualização do .NET Framework 4,7 e do Windows 10 para criadores, seu aplicativo
também pode ser executado em um ambiente no qual não é compatível com melhorias de DPI alto. Nesse caso,
você precisará desenvolver um fallback para seu aplicativo. Você pode fazer isso para executar o desenho
personalizado para lidar com o dimensionamento.
Para fazer isso, você também precisa determinar o sistema operacional no qual seu aplicativo está sendo
executado. Você pode fazer isso com um código semelhante ao seguinte:

// Create a reference to the OS version of Windows 10 Creators Update.


Version OsMinVersion = new Version(10, 0, 15063, 0);

// Access the platform/version of the current OS.


Console.WriteLine(Environment.OSVersion.Platform.ToString());
Console.WriteLine(Environment.OSVersion.VersionString);

// Compare the current version to the minimum required version.


Console.WriteLine(Environment.OSVersion.Version.CompareTo(OsMinVersion));

Observe que seu aplicativo não detectará com êxito o Windows 10 se ele não estiver listado como um sistema
operacional com suporte no manifesto do aplicativo.
Você também pode verificar a versão do .NET Framework em que o aplicativo foi criado:

Console.WriteLine(AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName);

Consulte também
Windows Forms adicionar elemento de configuração
Ajustando o tamanho e a escala dos Windows Forms
Alterando a aparência do Windows Forms
29/01/2020 • 2 minutes to read • Edit Online

Você pode personalizar a aparência de seus aplicativos de Windows Forms de várias maneiras diferentes, como
alterar a borda, a opacidade, a forma, o estilo ou definir uma imagem de plano de fundo para seu aplicativo
Windows Forms.

Nesta seção
Como alterar as bordas de Windows Forms
Mostra como alterar o estilo de borda de um formulário.

Referência
Form
Descreve essa classe e tem links para todos os seus membros.
FormBorderStyle
Descreve essa enumeração e contém descrições de todos os seus membros.
VisualStyleRenderer
Descreve essa classe e tem links para todos os seus membros.
Image
Descreve essa classe e tem links para todos os seus membros.
Region
Descreve essa classe e tem links para todos os seus membros.
Color
Descreve essa classe e tem links para todos os seus membros.

Seções Relacionadas
Ajustando o tamanho e a escala dos Windows Forms
Contém links para tópicos que mostram como alterar o tamanho e a escala de um formulário.
Elementos Gráficos e Desenho nos Windows Forms
Contém links para tópicos que descrevem como executar um desenho personalizado no Windows Forms.
Controles com suporte para desenho do proprietário interno
Lista o suporte de desenho proprietário em controles de Windows Forms.
Como alterar as bordas de formulários do Windows
Forms
03/02/2020 • 2 minutes to read • Edit Online

Você tem vários estilos de borda para escolher quando estiver determinando a aparência e comportamento dos
Windows Forms. Ao alterar a propriedade FormBorderStyle, você pode controlar o comportamento de
redimensionamento do formulário. Além disso, definir a FormBorderStyle afeta como a barra de legenda é exibida,
bem como quais botões podem aparecer nela. Para obter mais informações, consulte FormBorderStyle.
Há um suporte abrangente para esta tarefa no Visual Studio.
Consulte também Como alterar as bordas dos Windows Forms usando o designer.
Para definir o estilo de borda dos Windows Forms de maneira programática
Defina a propriedade FormBorderStyle como o estilo desejado. O exemplo de código a seguir define o estilo
de borda do formulário DlgBx1 como FixedDialog.

DlgBx1.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog

DlgBx1.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;

DlgBx1->FormBorderStyle =
System::Windows::Forms::FormBorderStyle::FixedDialog;

Consulte também Como criar caixas de diálogo em tempo de design.


Além disso, se você escolheu um estilo de borda para o formulário que fornece botões opcionais
Minimizar e Maximizar , é possível especificar se deseja que um ou os dois botões sejam funcionais. Esses
botões são úteis quando quiser controlar de perto a experiência do usuário. Os botões Minimizar e
Maximizar são habilitados por padrão e sua funcionalidade é manipulada por meio da janela
Propriedades .

Consulte também
FormBorderStyle
FixedDialog
Introdução ao Windows Forms
Controles de formulários do Windows
03/02/2020 • 2 minutes to read • Edit Online

À medida que você cria e modifica a interface do usuário de seus aplicativos dos Windows Forms, será necessário
adicionar, alinhar e posicionar controles. Os controles são objetos que estão contidos em objetos de formulário.
Cada tipo de controle tem seu próprio conjunto de propriedades, métodos e eventos que o tornam adequado para
uma finalidade específica. Você pode manipular os controles no designer e escrever o código para adicionar
controles dinamicamente em tempo de execução.

Nesta seção
Colocando controles em Windows Forms
Fornece links relacionados à colocação de controles em formulários.
Organizando controles no Windows Forms
Artigos relacionados à organização de controles em formulários.
Rotulando controles individuais do Windows Forms e fornecendo atalhos para eles
Descreve os usos dos atalhos de teclado, rótulos de texto em controles e teclas modificadoras.
Controles a serem usados nos Windows Forms
Lista os controles que funcionam com o Windows Forms e tarefas básicas que você pode realizar com cada
controle.
Desenvolvendo controles do Windows Forms personalizados com o .NET Framework
Fornece informações básicas e exemplos para ajudar os usuários a desenvolver controles personalizados dos
Windows Forms.
Desenvolvendo controles dos Windows Forms em tempo de design
Descreve técnicas para criar controles personalizados por meio de herança e design.

Seções relacionadas
\ aplicativos cliente
Entrada do usuário no Windows Forms
03/02/2020 • 2 minutes to read • Edit Online

O Windows Forms inclui um modelo de entrada do usuário com base em eventos que são gerados durante o
processamento de mensagens do Windows relacionadas. Os tópicos nesta seção fornecem informações sobre
entrada do usuário com mouse e teclado, incluindo exemplos de código que demonstram como realizar tarefas
específicas.

Nesta seção
Entrada do usuário em um aplicativo dos Windows Forms
Fornece uma visão geral dos eventos de entrada do usuário e os métodos que processam mensagens do
Windows.
Entrada do teclado em um aplicativo dos Windows Forms
Fornece informações sobre a manipulação de mensagens do teclado, os diferentes tipos de teclas e os eventos de
teclado.
Entrada do mouse em um Aplicativo do Windows Forms
Fornece informações sobre os eventos do mouse e outros recursos relacionados ao mouse, incluindo cursores e
captura do mouse.
Como simular eventos de mouse e teclado no código
Demonstra várias maneiras diferentes de simular programaticamente entrada do mouse e do teclado.
Como manipular eventos de entrada do usuário em controles dos Windows Forms
Apresenta um exemplo de código que manipula a maioria dos eventos de entrada do usuário e relata informações
sobre cada evento.
Validação da entrada do usuário nos Windows Forms
Descreve os métodos para validar a entrada do usuário em aplicativos dos Windows Forms.

Seções Relacionadas
Veja também Criando manipuladores de eventos nos Windows Forms.
Entrada do usuário em um aplicativo do Windows
Forms
03/02/2020 • 4 minutes to read • Edit Online

No Windows Forms, a entrada do usuário é enviada para aplicativos na forma de mensagens do Windows. Uma
série de métodos substituíveis processam essas mensagens no nível do aplicativo, formulário e controle. Quando
esses métodos recebem mensagens de mouse e teclado, eles geram eventos que podem ser manipulados para
obter informações sobre a entrada de mouse ou de teclado. Em muitos casos, os aplicativos do Windows Forms
serão capazes de processar todas as entradas do usuário simplesmente manipulando esses eventos. Em outros
casos, um aplicativo pode precisar substituir um dos métodos que processam mensagens para interceptar uma
mensagem específica antes de ela ser recebida pelo aplicativo, formulário ou controle.

Eventos de Mouse e Teclado


Todos os controles do Windows Forms herdam um conjunto de eventos relacionados às entradas de mouse e
teclado. Por exemplo, um controle pode manipular o evento KeyPress para determinar o código de caractere de
uma chave que foi pressionada, ou um controle pode manipular o evento MouseClick para determinar o local de
um clique do mouse. Para obter mais informações sobre eventos de mouse e teclado, consulte Usando Eventos de
Teclado e Eventos de Mouse no Windows Forms.

Métodos que Processam Mensagens de Entrada do Usuário


Formulários e controles têm acesso à interface IMessageFilter e a um conjunto de métodos substituíveis que
processam mensagens do Windows em pontos diferentes na fila de mensagens. Todos esses métodos têm um
parâmetro Message, que encapsula os detalhes de baixo nível das mensagens do Windows. É possível
implementar ou substituir esses métodos para analisar a mensagem e, então, consumi-la ou passá-la para o
próximo consumidor na fila de mensagens. A tabela a seguir apresenta os métodos que processam todas as
mensagens do Windows no Windows Forms.

M ÉTO DO { 1>O B SERVA Ç Õ ES<1}

PreFilterMessage Este método intercepta mensagens do Windows que estão na


fila (também chamadas de postadas) no nível do aplicativo.

PreProcessMessage Este método intercepta as mensagens do Windows no nível


do formulário e do controle antes que elas sejam processadas.

WndProc Este método processa mensagens do Windows no nível do


formulário e do controle.

DefWndProc Esse método realiza o processamento padrão de mensagens


do Windows no nível do formulário e do controle. Isso fornece
a funcionalidade mínima de uma janela.

OnNotifyMessage Este método intercepta as mensagens do Windows no nível


do formulário e do controle após o seu processamento. O bit
do estilo de EnableNotifyMessage deve ser definido para que
este método seja chamado.

Mensagens de teclado e mouse também são processadas por um conjunto adicional de métodos substituíveis
específicos para esses tipos de mensagens. Para obter mais informações, consulte Como a Entrada do Teclado
Funciona e Como a Entrada do Mouse Funciona no Windows Forms.

Consulte também
Entrada do usuário no Windows Forms
Entrada do teclado em um aplicativo dos Windows Forms
Entrada do mouse em um Aplicativo do Windows Forms
Entrada do teclado em um aplicativo do Windows
Forms
03/02/2020 • 2 minutes to read • Edit Online

O Windows Forms inclui eventos de teclado padrão que permitem que você responda a pressionamentos de tecla
específicos e também fornece maneiras de interceptar, modificar e consumir pressionamentos de tecla no nível de
aplicativo, formulário e controle.

Nesta seção
Como a entrada do teclado funciona
Descreve como as mensagens do teclado são processadas e transformadas em eventos de teclado.
Usando eventos do teclado
Fornece informações sobre os tipos de eventos de teclado e as informações que são recebidas pelos
manipuladores de eventos de teclado.
Como modificar a entrada do teclado para um controle padrão
Apresenta um exemplo de código que mostra como modificar valores de chave antes que eles cheguem a um
controle.
Como determinar qual tecla modificadora foi pressionada
Demonstra como descobrir se SHIFT, ALT ou CTRL foi pressionada além de outra chave.
Como manipular a entrada do teclado no nível do formulário
Apresenta um exemplo de código que mostra como interceptar chaves antes que elas cheguem a um controle.
Como a entrada do teclado funciona
23/10/2019 • 11 minutes to read • Edit Online

O Windows Forms processa a entrada do teclado ao gerar eventos de teclado em resposta às mensagens do
Windows. A maioria dos aplicativos Windows Forms processa a entrada do teclado exclusivamente ao manipular
eventos de teclado. No entanto, você precisa entender como as mensagens do teclado funcionam para que você
possa implementar cenários mais avançados de entrada do teclado, como interceptar teclas antes que elas
atinjam um controle. Este tópico descreve os tipos de dados da chave que o Windows Forms reconhece e fornece
uma visão geral de como as mensagens do teclado são roteadas. Para obter informações sobre eventos de
teclado, consulte Usando eventos do teclado.

Tipos de teclas
Windows Forms identifica a entrada de teclado como códigos de chave virtual que são representados Keys pela
enumeração bit-de bits. Com a Keys enumeração, você pode combinar uma série de teclas pressionadas para
resultar em um único valor. Esses valores correspondem aos valores que acompanham as mensagens
WM_KEYDOWN e WM_SYSKEYDOWN do Windows. Você pode detectar a maioria dos pressionamentos de chave
física KeyDown manipulando os eventos ou KeyUp . As chaves de caractere são um subconjunto da Keys
enumeração e correspondem aos valores que acompanham as mensagens WM_CHAR e WM_SYSCHAR do
Windows. Se a combinação de teclas pressionadas resultar em um caractere, você poderá detectar o caractere
manipulando KeyPress o evento. Como alternativa, você pode usar Keyboard, exposto por Visual Basic interface
de programação, para descobrir quais chaves foram pressionadas e enviar chaves. Para obter mais informações,
consulte Acessando o teclado.

Ordem dos eventos do teclado


Conforme listado anteriormente, existem três eventos relacionados que podem ocorrer em um controle. A
sequência a seguir mostra a ordem geral dos eventos:
1. O usuário envia por push a chave "a", a chave é pré-processado, despachada e ocorre um KeyDown evento.
2. O usuário mantém a chave "a", a chave é pré-processado, despachada e um KeyPress evento ocorre.
Esse evento ocorre várias vezes enquanto o usuário pressiona uma tecla.
3. O usuário libera a chave "a", a chave é pré-processado, despachada e ocorre um KeyUp evento.

Pré-processamento das teclas


Assim como outras mensagens, as mensagens do teclado são WndProc processadas no método de um
formulário ou controle. No entanto, antes que as mensagens do PreProcessMessage teclado sejam processadas, o
método chama um ou mais métodos que podem ser substituídos para manipular chaves de caracteres especiais e
chaves físicas. Você pode substituir esses métodos para detectar e filtrar certas teclas antes que as mensagens
sejam processadas pelo controle. A tabela a seguir mostra a ação que está sendo executada e o método
relacionado que ocorre, na ordem em que o método ocorre.
Pré -processamento de um evento KeyDown
AÇÃO M ÉTO DO REL A C IO N A DO O B SERVA Ç Õ ES

Verifique se há uma chave de comando ProcessCmdKey Este método processa uma chave de
como um acelerador ou um atalho de comando, que tem precedência sobre
menu. teclas regulares. Se esse método
retornar true , a mensagem principal
não será enviada e um evento de tecla
não ocorrerá. Se retornar false ,
IsInputKey será chamado .

Verifique se há uma chave especial que IsInputKey Se o método retornar true , significa
requer pré-processamento ou uma que o controle é um caractere regular e
chave de caractere normal que deva um KeyDown evento é gerado. Se
gerar um KeyDown evento e ser false ,ProcessDialogKey for
expedido para um controle. chamado. Obser vação: Para garantir
que um controle obtenha uma chave
ou uma combinação de chaves, você
pode PreviewKeyDown manipular o
evento IsInputKey e o
PreviewKeyDownEventArgs conjunto
true de para para a chave ou as
chaves desejadas.

Verifique se há uma tecla de navegação ProcessDialogKey Este método processa uma tecla física
(teclas ESC, TAB, Enter ou teclas de que utiliza uma funcionalidade especial
seta). dentro do controle, como alternar o
foco entre o controle e seu pai. Se o
controle imediato não tratar a chave, o
ProcessDialogKey será chamado no
controle pai e assim por diante para o
controle de nível superior na hierarquia.
Se esse método retornar true , o pré-
processamento estará completo e um
evento de tecla não será gerado. Se ele
retornar false , ocorrerá um
KeyDown evento.

Pré -processamento de um evento KeyPress


AÇÃO M ÉTO DO REL A C IO N A DO O B SERVA Ç Õ ES

Verifique se a chave é um caractere IsInputChar Se o caractere for um caractere normal,


normal que deve ser processado pelo esse método retornará true , o
controle KeyPress evento será gerado e nenhum
outro pré-processamento ocorrerá.
Caso ProcessDialogChar contrário, será
chamado.

Verifique se o caractere é um ProcessDialogChar Esse método, semelhante a


mnemônico (como &OK em um botão) ProcessDialogKey, será chamado de
hierarquia de controle. Se o controle for
um controle de contêiner, ele verificará
mnemônicos chamando
ProcessMnemonic a si mesmo e seus
controles filho. Se ProcessDialogChar
retornar true , umKeyPress evento
não ocorrerá.

Processando mensagens do teclado


Depois que as mensagens do WndProc teclado atingem o método de um formulário ou controle, elas são
processadas por um conjunto de métodos que podem ser substituídos. Cada um desses métodos retorna um
Boolean valor que especifica se a mensagem do teclado foi processada e consumida pelo controle. Se um dos
métodos retornar true , então a mensagem será considerada tratada e ela não será passada para a base ou pai
do controle para processamento adicional. Caso contrário, a mensagem permanecerá na fila e poderá ser
processada em outro método da base ou pai do controle. A tabela a seguir apresenta os métodos que processam
mensagens do teclado.

M ÉTO DO O B SERVA Ç Õ ES

ProcessKeyMessage Esse método processa todas as mensagens de teclado que


são recebidas pelo WndProc método do controle.

ProcessKeyPreview Esse método envia a mensagem do teclado para o pai do


controle. Se ProcessKeyPreview ProcessKeyEventArgs retornar
true , nenhum evento de chave será gerado; caso contrário,
será chamado.

ProcessKeyEventArgs Esse método gera os KeyDowneventos KeyPress, e KeyUp ,


conforme apropriado.

Substituindo métodos do teclado


Há vários métodos disponíveis para substituição quando uma mensagem do teclado é pré-processada e
processada. No entanto, alguns métodos são opções muito melhores do que outros. A tabela a seguir mostra
tarefas que você talvez queira realizar e a melhor maneira de substituir os métodos do teclado. Para obter mais
informações sobre como substituir métodos, consulte substituindo Propriedades e métodos em classes derivadas.

TA REFA M ÉTO DO

Interceptar uma chave de navegação e KeyDown gerar um Substitua IsInputKey. Obser vação: Como alternativa, você
evento. Por exemplo, você deseja que as teclas TAB e Enter pode manipular o PreviewKeyDown evento e o IsInputKey
sejam identificadas em uma caixa de texto. conjunto de PreviewKeyDownEventArgs para true para a
chave ou as chaves desejadas.

Execute tratamento de navegação ou entrada especial em um SubstituiçãoProcessDialogKey


controle. Por exemplo, você deseja usar as teclas de seta no
controle de lista para alterar o item selecionado.

Interceptar uma chave de navegação e KeyPress gerar um Substitua IsInputChar.


evento. Por exemplo, em um controle de caixa de rotação
você deseja o pressionamento de várias teclas de seta para
acelerar a progressão pelos itens.

Execute a manipulação especial de entrada ou navegação SubstituiçãoProcessDialogChar


KeyPress durante um evento. Por exemplo, em uma controle
de lista, manter pressionada a tecla "r" ignora os itens que
começam com a letra r.

Execute o tratamento mnemônico personalizado. Por Substitua ProcessMnemonic.


exemplo, você deseja manipular mnemônicos em botões
desenhados pelo proprietário contidos em uma barra de
ferramentas.

Consulte também
Keys
WndProc
PreProcessMessage
Objeto My.Computer.Keyboard
Acessando o Teclado
Usando eventos do teclado
Usando eventos do teclado
23/10/2019 • 4 minutes to read • Edit Online

A maioria dos programas do Windows Forms processa a entrada do teclado tratando eventos de teclado. Este
tópico fornece uma visão geral dos eventos de teclado, incluindo detalhes sobre quando usar cada evento e os
dados que são fornecidos para cada evento. Consulte também visão geral de manipuladores de eventos (Windows
Forms) e visão geral de eventos (Windows Forms).

Eventos de teclado
O Windows Forms fornece dois eventos que ocorrem quando um usuário pressiona uma tecla do teclado e um
evento quando um usuário libera uma tecla do teclado:
O KeyDown evento ocorre uma vez
O KeyPress evento, que pode ocorrer várias vezes quando um usuário segura a mesma tecla.
O KeyUp evento ocorre uma vez quando um usuário libera uma tecla.
Quando um usuário pressiona uma tecla, o Windows Forms determina qual evento deve ser gerado com base em
se a mensagem do teclado especifica uma tecla de caractere ou uma tecla física. Para obter mais informações
sobre teclas de caracteres e físicas, consulte Como funciona a entrada do teclado.
A tabela a seguir descreve os três eventos de teclado.

EVEN TO DE T EC L A DO DESC RIÇ Ã O RESULTA DO S

KeyDown Esse evento é gerado quando um O manipulador para KeyDown recebe:


usuário pressiona uma tecla física.
Um KeyEventArgs parâmetro,
que fornece o KeyCode
propriedade (que especifica um
botão físico do teclado).
O Modifiers propriedade (SHIFT,
CTRL ou ALT).
O KeyData propriedade (que
combina o código e tecla
modificadora). O KeyEventArgs
também fornece um parâmetro:

O Handled propriedade,
que pode ser definida
para impedir que o
controle subjacente
receba a chave.
O SuppressKeyPress
propriedade, que pode
ser usada para suprimir
a KeyPress e KeyUp
eventos para esse
pressionamento de tecla.
EVEN TO DE T EC L A DO DESC RIÇ Ã O RESULTA DO S

KeyPress Esse evento é gerado quando as teclas KeyPress é gerado após KeyDown.
são pressionadas resultam em um
caractere. Por exemplo, um usuário O manipulador para KeyPress
pressiona as teclas SHIFT e a letra “a” recebe:
minúscula, o que resulta em uma letra Um KeyPressEventArgs
“A” maiúscula. parâmetro, que contém o
código de caractere da tecla que
foi pressionada. Esse código de
caractere é exclusivo para cada
combinação de uma tecla de
caractere e tecla modificadora.

Por exemplo, a tecla “A” gerará:

O código de caractere
65, se ela estiver
pressionada com a tecla
SHIFT
Ou a tecla CAPS LOCK,
97 se ela for pressionada
sozinha,
E 1 se ela estiver
pressionada com a tecla
CTRL.

KeyUp Esse evento é gerado quando um O manipulador para KeyUp recebe:


usuário libera uma tecla física.
Um KeyEventArgs parâmetro:

Que fornece o KeyCode


propriedade (que
especifica um botão
físico do teclado).
O Modifiers propriedade
(SHIFT, CTRL ou ALT).
O KeyData propriedade
(que combina o código e
tecla modificadora).

Consulte também
Entrada do teclado em um aplicativo dos Windows Forms
Como a entrada do teclado funciona
Entrada do mouse em um Aplicativo do Windows Forms
Como: modificar a entrada do teclado para um
controle padrão
23/10/2019 • 9 minutes to read • Edit Online

O Windows Forms fornece a capacidade de consumir e modificar as entradas do teclado. Consumir uma tecla
significa tratá-la dentro de um método ou manipulador de eventos para que outros métodos e eventos mais
adiante na fila de mensagens não recebam o valor da tecla. Modificar uma tecla significa modificar o valor de uma
tecla para que os métodos e manipuladores de eventos mais adiante na fila de mensagens recebam um valor de
tecla diferente. Este tópico mostra como realizar essas tarefas.
Consumir uma tecla
Em um KeyPress manipulador de eventos, defina Handled a propriedade da KeyPressEventArgs classe como
true .

-ou-
Em um KeyDown manipulador de eventos, defina Handled a propriedade da KeyEventArgs classe como
true .

NOTE
Definir a Handled KeyDown Propriedade no manipulador de eventos não impede que os KeyPress eventos KeyUp e
sejam gerados para o pressionamento de teclas atual. Use a SuppressKeyPress propriedade para essa finalidade.

O exemplo a seguir é um trecho de switch uma instrução que examina a KeyChar Propriedade do
KeyPressEventArgs recebido por um KeyPress manipulador de eventos. Esse código consome as teclas dos
caracteres “A” e “a”.

// Consume 'A' and 'a'.


case (char)65:
case (char)97:
MessageBox.Show("Control.KeyPress: '" +
e.KeyChar.ToString() + "' consumed.");
e.Handled = true;
break;

' Consume 'A' and 'a'.


Case ChrW(65), ChrW(97)
MessageBox.Show(("Control.KeyPress: '" + _
e.KeyChar.ToString() + "' consumed."))
e.Handled = True

Modificar uma tecla de caractere padrão


Em um KeyPress manipulador de eventos, defina KeyChar a propriedade da KeyPressEventArgs classe como
o valor da nova chave de caractere.
O exemplo a seguir é um trecho de uma instrução switch que modifica “B” para “A” e “b” para “a”. Observe
que a Handled propriedade KeyPressEventArgs do parâmetro é definida como false , de forma que o novo
valor de chave seja propagado para outros métodos e eventos na fila de mensagens.
// Detect 'B', modify it to 'A', and forward the key.
case (char)66:
MessageBox.Show("Control.KeyPress: '" +
e.KeyChar.ToString() + "' replaced by 'A'.");
e.KeyChar = (char)65;
e.Handled = false;
break;

// Detect 'b', modify it to 'a', and forward the key.


case (char)98:
MessageBox.Show("Control.KeyPress: '" +
e.KeyChar.ToString() + "' replaced by 'a'.");
e.KeyChar = (char)97;
e.Handled = false;
break;

' Modify 'B' to 'A' and forward the key.


Case ChrW(66)
MessageBox.Show(("Control.KeyPress: '" + _
e.KeyChar.ToString() + "' replaced by 'A'."))
e.KeyChar = ChrW(65)
e.Handled = False

' Modify 'b' to 'a' and forward the key.


Case ChrW(98)
MessageBox.Show(("Control.KeyPress: '" + _
e.KeyChar.ToString() + "' replaced by 'a'."))
e.KeyChar = ChrW(97)
e.Handled = False

Modificar uma tecla não caractere


Substitua um Control método que processa mensagens do Windows, detecte a mensagem WM_KEYDOWN
ou WM_SYSKEYDOWN e WParam defina a propriedade Message do parâmetro para Keys o valor que
representa a nova chave não caractere.
O exemplo de código a seguir demonstra como substituir PreProcessMessage o método de um controle
para detectar as teclas F1 por F9 e modificar qualquer pressionamento de tecla F3 para F1. Para obter mais
informações Control sobre os métodos que você pode substituir para interceptar mensagens do teclado,
consulte entrada do usuário em um aplicativo Windows Forms e como funciona a entrada do teclado.
// Detect F1 through F9 during preprocessing and modify F3.
public override bool PreProcessMessage(ref Message m)
{
if (m.Msg == WM_KEYDOWN)
{
Keys keyCode = (Keys)m.WParam & Keys.KeyCode;

// Detect F1 through F9.


switch (keyCode)
{
case Keys.F1:
case Keys.F2:
case Keys.F3:
case Keys.F4:
case Keys.F5:
case Keys.F6:
case Keys.F7:
case Keys.F8:
case Keys.F9:

MessageBox.Show("Control.PreProcessMessage: '" +
keyCode.ToString() + "' pressed.");

// Replace F3 with F1, so that ProcessKeyMessage will


// receive F1 instead of F3.
if (keyCode == Keys.F3)
{
m.WParam = (IntPtr)Keys.F1;
MessageBox.Show("Control.PreProcessMessage: '" +
keyCode.ToString() + "' replaced by F1.");
}
break;
}
}

// Send all other messages to the base method.


return base.PreProcessMessage(ref m);
}
' Detect F1 through F9 during preprocessing and modify F3.
Public Overrides Function PreProcessMessage(ByRef m As Message) _
As Boolean

If m.Msg = WM_KEYDOWN Then


Dim keyCode As Keys = CType(m.WParam, Keys) And Keys.KeyCode

' Detect F1 through F9.


Select Case keyCode
Case Keys.F1, Keys.F2, Keys.F3, Keys.F4, Keys.F5, _
Keys.F6, Keys.F7, Keys.F8, Keys.F9

MessageBox.Show(("Control.PreProcessMessage: '" + _
keyCode.ToString() + "' pressed."))

' Replace F3 with F1, so that ProcessKeyMessage will


' receive F1 instead of F3.
If keyCode = Keys.F3 Then
m.WParam = CType(Keys.F1, IntPtr)
MessageBox.Show(("Control.PreProcessMessage: '" + _
keyCode.ToString() + "' replaced by F1."))
End If
End Select
End If

' Send all other messages to the base method.


Return MyBase.PreProcessMessage(m)
End Function

Exemplo
O exemplo de código a seguir é o aplicativo completo para os exemplos de código nas seções anteriores. O
aplicativo usa um controle personalizado derivado da TextBox classe para consumir e modificar a entrada do
teclado.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace KeyboardInput
{
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand,
Name="FullTrust")]
class Form1 : Form
{
// The following Windows message value is defined in Winuser.h.
private int WM_KEYDOWN = 0x100;
CustomTextBox CustomTextBox1 = new CustomTextBox();

[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}

public Form1()
{
this.AutoSize = true;
this.Controls.Add(CustomTextBox1);
CustomTextBox1.KeyPress +=
new KeyPressEventHandler(CustomTextBox1_KeyPress);
}

// Consume and modify several character keys.


// Consume and modify several character keys.
void CustomTextBox1_KeyPress(object sender, KeyPressEventArgs e)
{
switch (e.KeyChar)
{
// Consume 'A' and 'a'.
case (char)65:
case (char)97:
MessageBox.Show("Control.KeyPress: '" +
e.KeyChar.ToString() + "' consumed.");
e.Handled = true;
break;

// Detect 'B', modify it to 'A', and forward the key.


case (char)66:
MessageBox.Show("Control.KeyPress: '" +
e.KeyChar.ToString() + "' replaced by 'A'.");
e.KeyChar = (char)65;
e.Handled = false;
break;

// Detect 'b', modify it to 'a', and forward the key.


case (char)98:
MessageBox.Show("Control.KeyPress: '" +
e.KeyChar.ToString() + "' replaced by 'a'.");
e.KeyChar = (char)97;
e.Handled = false;
break;
}
}
}
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand,
Name="FullTrust")]
public class CustomTextBox : TextBox
{
// The following Windows message value is defined in Winuser.h.
private int WM_KEYDOWN = 0x100;

public CustomTextBox()
{
this.Size = new Size(100, 100);
this.AutoSize = false;
}

// Detect F1 through F9 during preprocessing and modify F3.


public override bool PreProcessMessage(ref Message m)
{
if (m.Msg == WM_KEYDOWN)
{
Keys keyCode = (Keys)m.WParam & Keys.KeyCode;

// Detect F1 through F9.


switch (keyCode)
{
case Keys.F1:
case Keys.F2:
case Keys.F3:
case Keys.F4:
case Keys.F5:
case Keys.F6:
case Keys.F7:
case Keys.F8:
case Keys.F9:

MessageBox.Show("Control.PreProcessMessage: '" +
keyCode.ToString() + "' pressed.");

// Replace F3 with F1, so that ProcessKeyMessage will


// receive F1 instead of F3.
if (keyCode == Keys.F3)
if (keyCode == Keys.F3)
{
m.WParam = (IntPtr)Keys.F1;
MessageBox.Show("Control.PreProcessMessage: '" +
keyCode.ToString() + "' replaced by F1.");
}
break;
}
}

// Send all other messages to the base method.


return base.PreProcessMessage(ref m);
}

// Detect F1 through F9 during processing.


protected override bool ProcessKeyMessage(ref Message m)
{
if (m.Msg == WM_KEYDOWN)
{
Keys keyCode = (Keys)m.WParam & Keys.KeyCode;

// Detect F1 through F9.


switch (keyCode)
{
case Keys.F1:
case Keys.F2:
case Keys.F3:
case Keys.F4:
case Keys.F5:
case Keys.F6:
case Keys.F7:
case Keys.F8:
case Keys.F9:

MessageBox.Show("Control.ProcessKeyMessage: '" +
keyCode.ToString() + "' pressed.");
break;
}
}

// Send all messages to the base method.


return base.ProcessKeyMessage(ref m);
}
}
}

Imports System.Drawing
Imports System.Security
Imports System.Security.Permissions
Imports System.Windows.Forms

Namespace KeyboardInput
<System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand,
Name:="FullTrust")> _
Class Form1
Inherits Form

' The following Windows message value is defined in Winuser.h.


Private WM_KEYDOWN As Integer = &H100
Private WithEvents CustomTextBox1 As New CustomTextBox()

<STAThread()> _
Public Shared Sub Main()
Application.EnableVisualStyles()
Application.Run(New Form1())
End Sub
Public Sub New()
Me.AutoSize = True
Me.Controls.Add(CustomTextBox1)
End Sub

' Consume and modify several character keys.


Sub CustomTextBox1_KeyPress(ByVal sender As Object, _
ByVal e As KeyPressEventArgs) Handles CustomTextBox1.KeyPress

Select Case e.KeyChar

' Consume 'A' and 'a'.


Case ChrW(65), ChrW(97)
MessageBox.Show(("Control.KeyPress: '" + _
e.KeyChar.ToString() + "' consumed."))
e.Handled = True

' Modify 'B' to 'A' and forward the key.


Case ChrW(66)
MessageBox.Show(("Control.KeyPress: '" + _
e.KeyChar.ToString() + "' replaced by 'A'."))
e.KeyChar = ChrW(65)
e.Handled = False

' Modify 'b' to 'a' and forward the key.


Case ChrW(98)
MessageBox.Show(("Control.KeyPress: '" + _
e.KeyChar.ToString() + "' replaced by 'a'."))
e.KeyChar = ChrW(97)
e.Handled = False
End Select
End Sub
End Class

<System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand,
Name:="FullTrust")> _
Public Class CustomTextBox
Inherits TextBox

' The following Windows message value is defined in Winuser.h.


Private WM_KEYDOWN As Integer = &H100

Public Sub New()


Me.Size = New Size(100, 100)
Me.AutoSize = False
End Sub

' Detect F1 through F9 during preprocessing and modify F3.


Public Overrides Function PreProcessMessage(ByRef m As Message) _
As Boolean

If m.Msg = WM_KEYDOWN Then


Dim keyCode As Keys = CType(m.WParam, Keys) And Keys.KeyCode

' Detect F1 through F9.


Select Case keyCode
Case Keys.F1, Keys.F2, Keys.F3, Keys.F4, Keys.F5, _
Keys.F6, Keys.F7, Keys.F8, Keys.F9

MessageBox.Show(("Control.PreProcessMessage: '" + _
keyCode.ToString() + "' pressed."))

' Replace F3 with F1, so that ProcessKeyMessage will


' receive F1 instead of F3.
If keyCode = Keys.F3 Then
m.WParam = CType(Keys.F1, IntPtr)
MessageBox.Show(("Control.PreProcessMessage: '" + _
keyCode.ToString() + "' replaced by F1."))
End If
End Select
End If

' Send all other messages to the base method.


Return MyBase.PreProcessMessage(m)
End Function

' Detect F1 through F9 during processing.


Protected Overrides Function ProcessKeyMessage(ByRef m As Message) _
As Boolean

If m.Msg = WM_KEYDOWN Then


Dim keyCode As Keys = CType(m.WParam, Keys) And Keys.KeyCode

' Detect F1 through F9.


Select Case keyCode
Case Keys.F1, Keys.F2, Keys.F3, Keys.F4, Keys.F5, _
Keys.F6, Keys.F7, Keys.F8, Keys.F9

MessageBox.Show(("Control.ProcessKeyMessage: '" + _
keyCode.ToString() + "' pressed."))
End Select
End If

' Send all messages to the base method.


Return MyBase.ProcessKeyMessage(m)
End Function

End Class
End Namespace

Compilando o código
Este exemplo requer:
Referências aos assemblies System, System.Drawing e System.Windows.Forms.

Consulte também
Entrada do teclado em um aplicativo dos Windows Forms
Entrada do usuário em um aplicativo dos Windows Forms
Como a entrada do teclado funciona
Como: determinar qual tecla modificadora foi
pressionada
23/10/2019 • 3 minutes to read • Edit Online

Quando você cria um aplicativo que aceita a digitação do usuário, também é recomendável monitorar as teclas
modificadoras como SHIFT, ALT e CTRL. Quando uma tecla modificadora for pressionada junto com outras teclas,
ou com cliques do mouse, seu aplicativo pode responder adequadamente. Por exemplo, se a letra S for
pressionada, isso poderá simplesmente fazer um “s” aparecer na tela, mas se as teclas CTRL + S forem
pressionadas, o documento atual poderá ser salvo. Se você manipular o KeyDown evento, a Modifiers propriedade
de KeyEventArgs recebido pelo manipulador de eventos especifica quais teclas modificadoras são pressionadas.
Como alternativa, a KeyData propriedade de KeyEventArgs especifica o caractere que foi pressionado, bem como
quaisquer chaves de modificador combinadas com um OR-bit. No entanto, se você estiver KeyPress manipulando
o evento ou um evento do mouse, o manipulador de eventos não receberá essas informações. Nesse caso, você
deve usar a ModifierKeys propriedade Control da classe. Em ambos os casos, você deve executar uma e/ou um
Keys valor apropriado e o valor que você está testando. A Keys Enumeração oferece variações de cada chave de
modificador, portanto, é importante que você execute o bit e o com o valor correto. Por exemplo, a tecla Shift é
representada por Shift RShiftKey , ShiftKeye LShiftKey o valor correto para testar o deslocamento como uma chave
de modificador é Shift. Da mesma forma, para testar CTRL e Alt como modificadores, você deve Control usar Alt os
valores e, respectivamente.

NOTE
Visual Basic programadores também podem acessar informações de chave por Keyboard meio da propriedade

Determinar qual tecla modificadora foi pressionada


Use o operador AND nonbit com ModifierKeys a propriedade Keys e um valor da enumeração para
determinar se uma tecla modificadora específica é pressionada. O exemplo de código a seguir mostra como
determinar se a tecla Shift é pressionada KeyPress dentro de um manipulador de eventos.

private:
void textBox1_KeyPress(Object^ sender, KeyPressEventArgs^ e)
{
if ((Control::ModifierKeys & Keys::Shift) == Keys::Shift)
{
MessageBox::Show("Pressed " + Keys::Shift.ToString());
}
}

public void TextBox1_KeyPress(object sender, KeyPressEventArgs e)


{
if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
{
MessageBox.Show("Pressed " + Keys.Shift);
}
}
Public Sub TextBox1_KeyPress(ByVal sender As Object, _
ByVal e As KeyPressEventArgs) Handles TextBox1.KeyPress

If ((Control.ModifierKeys And Keys.Shift) = Keys.Shift) Then


MsgBox("Pressed " + Keys.Shift.ToString())
End If
End Sub

Consulte também
Keys
ModifierKeys
Entrada do teclado em um aplicativo dos Windows Forms
Como: Determinar se CapsLock está no Visual Basic
Como: manipular a entrada do teclado no nível do
formulário
23/10/2019 • 7 minutes to read • Edit Online

Os Windows Forms proporcionam a capacidade de manipular mensagens de teclado no nível do formulário, antes
que as mensagens cheguem a um controle. Este tópico mostra como realizar essa tarefa.
Como manipular uma mensagem do teclado no nível do formulário
Lidar com o KeyPress ou KeyDown evento do formulário de inicialização e defina as KeyPreview
propriedade do formulário para true para que as mensagens do teclado são recebidas pelo formulário
antes que elas atinjam os controles no formulário. O seguinte código de exemplo manipula o KeyPress
eventos, detectando todas as teclas numéricas e consumindo '1', '4' e '7'.

// Detect all numeric characters at the form level and consume 1,


// 4, and 7. Note that Form.KeyPreview must be set to true for this
// event handler to be called.
private:
void Form1_KeyPress(Object^ sender, KeyPressEventArgs^ e)
{
if ((e->KeyChar >= '0') && (e->KeyChar <= '9'))
{
MessageBox::Show("Form.KeyPress: '" +
e->KeyChar.ToString() + "' pressed.");

switch (e->KeyChar)
{
case '1':
case '4':
case '7':
MessageBox::Show("Form.KeyPress: '" +
e->KeyChar.ToString() + "' consumed.");
e->Handled = true;
break;
}
}
}
// Detect all numeric characters at the form level and consume 1,
// 4, and 7. Note that Form.KeyPreview must be set to true for this
// event handler to be called.
void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar >= 48 && e.KeyChar <= 57)
{
MessageBox.Show("Form.KeyPress: '" +
e.KeyChar.ToString() + "' pressed.");

switch (e.KeyChar)
{
case (char)49:
case (char)52:
case (char)55:
MessageBox.Show("Form.KeyPress: '" +
e.KeyChar.ToString() + "' consumed.");
e.Handled = true;
break;
}
}
}

' Detect all numeric characters at the form level and consume 1,
' 4, and 7. Note that Form.KeyPreview must be set to true for this
' event handler to be called.
Sub Form1_KeyPress(ByVal sender As Object, _
ByVal e As KeyPressEventArgs) Handles Me.KeyPress

If e.KeyChar >= ChrW(48) And e.KeyChar <= ChrW(57) Then


MessageBox.Show(("Form.KeyPress: '" + _
e.KeyChar.ToString() + "' pressed."))

Select Case e.KeyChar


Case ChrW(49), ChrW(52), ChrW(55)
MessageBox.Show(("Form.KeyPress: '" + _
e.KeyChar.ToString() + "' consumed."))
e.Handled = True
End Select
End If
End Sub

Exemplo
O exemplo de código a seguir é o aplicativo completo para o exemplo acima. O aplicativo inclui um TextBox
juntamente com vários outros controles que permitem que você mova o foco do TextBox. O KeyPress eventos da
janela principal Form consome '1', '4' e '7' e o KeyPress evento do TextBox consome '2', '5' e '8' e exibe as teclas
restantes. Comparar as MessageBox de saída quando você pressiona uma tecla numérica enquanto o TextBox tem
o foco com o MessageBox quando você pressiona uma tecla numérica enquanto o foco está em um dos outros
controles de saída.

#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>
#using <System.dll>

using namespace System;


using namespace System::Drawing;
using namespace System::Windows::Forms;
using namespace System::Security::Permissions;

namespace KeyboardInputForm
{
{
public ref class Form1 sealed: public Form, public IMessageFilter
{
// The following Windows message value is defined in Winuser.h.
private:
static const int WM_KEYDOWN = 0x100;
private:
TextBox^ inputTextBox;
public:
Form1()
{
inputTextBox = gcnew TextBox();
this->AutoSize = true;
Application::AddMessageFilter(this);
FlowLayoutPanel^ panel = gcnew FlowLayoutPanel();
panel->AutoSize = true;
panel->FlowDirection = FlowDirection::TopDown;
panel->Controls->Add(gcnew Button());
panel->Controls->Add(gcnew RadioButton());
panel->Controls->Add(inputTextBox);
this->Controls->Add(panel);
this->KeyPreview = true;
this->KeyPress +=
gcnew KeyPressEventHandler(this, &Form1::Form1_KeyPress);
inputTextBox->KeyPress +=
gcnew KeyPressEventHandler(this,
&Form1::inputTextBox_KeyPress);
}

// Detect all numeric characters at the


// application level and consume 0.
[SecurityPermission(SecurityAction::LinkDemand,
Flags=SecurityPermissionFlag::UnmanagedCode)]
virtual bool PreFilterMessage(Message% m)
{
// Detect key down messages.
if (m.Msg == WM_KEYDOWN)
{
Keys keyCode = (Keys)((int)m.WParam) & Keys::KeyCode;
// Determine whether the keystroke is a number from the top of
// the keyboard, or a number from the keypad.
if (((keyCode >= Keys::D0) && (keyCode <= Keys::D9))
||((keyCode >= Keys::NumPad0)
&& (keyCode <= Keys::NumPad9)))
{
MessageBox::Show(
"IMessageFilter.PreFilterMessage: '" +
keyCode.ToString() + "' pressed.");

if ((keyCode == Keys::D0) || (keyCode == Keys::NumPad0))


{
MessageBox::Show(
"IMessageFilter.PreFilterMessage: '" +
keyCode.ToString() + "' consumed.");
return true;
}
}
}

// Forward all other messages.


return false;
}

// Detect all numeric characters at the form level and consume 1,


// 4, and 7. Note that Form.KeyPreview must be set to true for this
// event handler to be called.
private:
void Form1_KeyPress(Object^ sender, KeyPressEventArgs^ e)
{
if ((e->KeyChar >= '0') && (e->KeyChar <= '9'))
if ((e->KeyChar >= '0') && (e->KeyChar <= '9'))
{
MessageBox::Show("Form.KeyPress: '" +
e->KeyChar.ToString() + "' pressed.");

switch (e->KeyChar)
{
case '1':
case '4':
case '7':
MessageBox::Show("Form.KeyPress: '" +
e->KeyChar.ToString() + "' consumed.");
e->Handled = true;
break;
}
}
}

// Detect all numeric characters at the TextBox level and consume


// 2, 5, and 8.
private:
void inputTextBox_KeyPress(Object^ sender, KeyPressEventArgs^ e)
{
if ((e->KeyChar >= '0') && (e->KeyChar <= '9'))
{
MessageBox::Show("Control.KeyPress: '" +
e->KeyChar.ToString() + "' pressed.");

switch (e->KeyChar)
{
case '2':
case '5':
case '8':
MessageBox::Show("Control.KeyPress: '" +
e->KeyChar.ToString() + "' consumed.");
e->Handled = true;
break;
}
}
}
};
}

[STAThread]
int main()
{
Application::EnableVisualStyles();
Application::Run(gcnew KeyboardInputForm::Form1());
}

using System;
using System.Drawing;
using System.Windows.Forms;

namespace KeyboardInputForm
{
class Form1 : Form
{
TextBox TextBox1 = new TextBox();

[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}

public Form1()
public Form1()
{
this.AutoSize = true;

FlowLayoutPanel panel = new FlowLayoutPanel();


panel.AutoSize = true;
panel.FlowDirection = FlowDirection.TopDown;
panel.Controls.Add(TextBox1);
this.Controls.Add(panel);

this.KeyPreview = true;
this.KeyPress +=
new KeyPressEventHandler(Form1_KeyPress);
TextBox1.KeyPress +=
new KeyPressEventHandler(TextBox1_KeyPress);
}

// Detect all numeric characters at the form level and consume 1,


// 4, and 7. Note that Form.KeyPreview must be set to true for this
// event handler to be called.
void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar >= 48 && e.KeyChar <= 57)
{
MessageBox.Show("Form.KeyPress: '" +
e.KeyChar.ToString() + "' pressed.");

switch (e.KeyChar)
{
case (char)49:
case (char)52:
case (char)55:
MessageBox.Show("Form.KeyPress: '" +
e.KeyChar.ToString() + "' consumed.");
e.Handled = true;
break;
}
}
}

// Detect all numeric characters at the TextBox level and consume


// 2, 5, and 8.
void TextBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar >= 48 && e.KeyChar <= 57)
{
MessageBox.Show("Control.KeyPress: '" +
e.KeyChar.ToString() + "' pressed.");

switch (e.KeyChar)
{
case (char)50:
case (char)53:
case (char)56:
MessageBox.Show("Control.KeyPress: '" +
e.KeyChar.ToString() + "' consumed.");
e.Handled = true;
break;
}
}
}
}
}

Imports System.Drawing
Imports System.Windows.Forms

Namespace KeyboardInputForm
Namespace KeyboardInputForm

Class Form1
Inherits Form

Private WithEvents TextBox1 As New TextBox()

<STAThread()> _
Public Shared Sub Main()
Application.EnableVisualStyles()
Application.Run(New Form1())
End Sub

Public Sub New()


Me.AutoSize = True

Dim panel As New FlowLayoutPanel()


panel.AutoSize = True
panel.FlowDirection = FlowDirection.TopDown
panel.Controls.Add(TextBox1)
Me.Controls.Add(panel)

Me.KeyPreview = True
End Sub

' Detect all numeric characters at the form level and consume 1,
' 4, and 7. Note that Form.KeyPreview must be set to true for this
' event handler to be called.
Sub Form1_KeyPress(ByVal sender As Object, _
ByVal e As KeyPressEventArgs) Handles Me.KeyPress

If e.KeyChar >= ChrW(48) And e.KeyChar <= ChrW(57) Then


MessageBox.Show(("Form.KeyPress: '" + _
e.KeyChar.ToString() + "' pressed."))

Select Case e.KeyChar


Case ChrW(49), ChrW(52), ChrW(55)
MessageBox.Show(("Form.KeyPress: '" + _
e.KeyChar.ToString() + "' consumed."))
e.Handled = True
End Select
End If
End Sub

' Detect all numeric characters at the TextBox level and consume
' 2, 5, and 8.
Sub TextBox1_KeyPress(ByVal sender As Object, _
ByVal e As KeyPressEventArgs) Handles TextBox1.KeyPress

If e.KeyChar >= ChrW(48) And e.KeyChar <= ChrW(57) Then


MessageBox.Show(("Control.KeyPress: '" + _
e.KeyChar.ToString() + "' pressed."))

Select Case e.KeyChar


Case ChrW(50), ChrW(53), ChrW(56)
MessageBox.Show(("Control.KeyPress: '" + _
e.KeyChar.ToString() + "' consumed."))
e.Handled = True
End Select
End If
End Sub

End Class
End Namespace

Compilando o código
Este exemplo requer:
Referências aos assemblies System, System.Drawing e System.Windows.Forms.

Consulte também
Entrada do teclado em um aplicativo dos Windows Forms
Entrada do mouse em um aplicativo do Windows
Forms
03/02/2020 • 2 minutes to read • Edit Online

O Windows Forms inclui uma variedade de eventos de mouse e suporte adicional para cursores personalizados
de mouse, captura de mouse e comportamento de arrastar e soltar.

Nesta seção
Como a entrada do mouse funciona nos Windows Forms
Fornece informações sobre os eventos do mouse e como obter informações atuais e configurações do sistema
para o mouse.
Eventos do mouse nos Windows Forms
Fornece informações sobre a ordem na qual os eventos do mouse ocorrem e como os eventos do mouse são
gerados dentro de controles específicos.
Como distinguir entre cliques e cliques duplos
Demonstra como usar cliques únicos e duplos para iniciar ações incompatíveis.
Ponteiros do mouse nos Windows Forms
Descreve como alterar o cursor do mouse.
Captura do mouse nos Windows Forms
Descreve como um controle pode capturar o mouse.
Funcionalidade do tipo "arrastar e soltar" no Windows Forms
Descreve como implementar o comportamento de arrastar e soltar.

Seções Relacionadas
Acessando o Mouse
Lista os tópicos para acessar o mouse usando Visual Basic.
Como a entrada do mouse funciona no Windows
Forms
03/02/2020 • 9 minutes to read • Edit Online

Receber e manipular entradas de mouse é uma parte importante qualquer aplicativo do Windows. Você pode
manipular eventos de mouse para executar uma ação em seu aplicativo ou usar informações sobre a localização
do mouse para executar testes de clique ou outras ações. Além disso, é possível alterar a maneira como os
controles em seu aplicativo manipulam as entradas de mouse. Este tópico descreve esses eventos de mouse de
forma detalhada, bem como obter e alterar configurações do sistema para o mouse. Para obter mais informações
sobre os dados fornecidos com os eventos de mouse e a ordem em que os eventos de clique do mouse são
gerados, consulte Eventos de mouse nos Windows Forms.

Localização do mouse e teste de clique


Quando o usuário move o mouse, o sistema operacional move o ponteiro do mouse. O ponteiro do mouse
contém um único pixel, chamado de ponto de acesso, que o sistema operacional rastreia e reconhece como a
posição do ponteiro. Quando o usuário move o mouse ou pressiona um botão do mouse, o Control que contém a
HotSpot gera o evento de mouse apropriado. Você pode obter a posição atual do mouse com a propriedade
Location da MouseEventArgs ao manipular um evento do mouse ou usando a propriedade Position da classe
Cursor. Posteriormente, você pode usar informações sobre a localização do mouse para executar o teste de clique
e, em seguida, executar uma ação com base na localização do mouse. O recurso de teste de colisão é integrado a
vários controles em Windows Forms como os controles ListView, TreeView, MonthCalendar e DataGridView.
Usado com o evento de mouse apropriado, MouseHover por exemplo, o teste de clique é muito útil para
determinar quando o aplicativo deve executar uma ação específica.

Eventos de mouse
A principal maneira de responder a entradas de mouse é manipular eventos de mouse. A tabela a seguir mostra
os eventos de mouse e descreve quando eles são gerados.

EVEN TO DE M O USE DESC RIÇ Ã O

Click Esse evento ocorre quando o botão do mouse é liberado,


normalmente antes do evento MouseUp. O manipulador para
esse evento recebe um argumento do tipo EventArgs.
Manipule este evento quando você só precisar determinar
quando um clique ocorrer.

MouseClick Este evento ocorre quando o usuário clica no controle com o


mouse. O manipulador para esse evento recebe um
argumento do tipo MouseEventArgs. Manipule este evento
quando você precisar obter informações sobre o mouse
quando um clique ocorrer.

DoubleClick Este evento ocorre quando um usuário clica duas vezes no


controle. O manipulador para esse evento recebe um
argumento do tipo EventArgs. Manipule este evento quando
você só precisar determinar quando um clique duplo ocorrer.
EVEN TO DE M O USE DESC RIÇ Ã O

MouseDoubleClick Este evento ocorre quando o usuário clica duas vezes no


controle com o mouse. O manipulador para esse evento
recebe um argumento do tipo MouseEventArgs. Manipule
este evento quando você precisar obter informações sobre o
mouse quando um clique duplo ocorrer.

MouseDown Este evento ocorre quando o ponteiro do mouse está sobre o


controle e um botão do mouse é pressionado. O manipulador
para esse evento recebe um argumento do tipo
MouseEventArgs.

MouseEnter Este evento ocorre quando o ponteiro do mouse entra na


borda ou na área de cliente do controle, dependendo do tipo
de controle. O manipulador para esse evento recebe um
argumento do tipo EventArgs.

MouseHover Este evento ocorre quando o ponteiro do mouse para e


permanece sobre o controle. O manipulador para esse evento
recebe um argumento do tipo EventArgs.

MouseLeave Este evento ocorre quando o ponteiro do mouse deixa a


borda ou a área de cliente do controle, dependendo do tipo
de controle. O manipulador para esse evento recebe um
argumento do tipo EventArgs.

MouseMove Este evento ocorre quando o ponteiro do mouse se move


enquanto está sobre um controle. O manipulador para esse
evento recebe um argumento do tipo MouseEventArgs.

MouseUp Este evento ocorre quando o ponteiro do mouse está sobre o


controle e o usuário libera um botão do mouse. O
manipulador para esse evento recebe um argumento do tipo
MouseEventArgs.

MouseWheel Este evento ocorre quando o usuário gira o botão de rolagem


do mouse enquanto o controle está em foco. O manipulador
para esse evento recebe um argumento do tipo
MouseEventArgs. Você pode usar a propriedade Delta de
MouseEventArgs para determinar a distância com que o
mouse foi rolado.

Alterando a entrada do mouse e detectando as configurações do


sistema
Você pode detectar e alterar a maneira como um controle manipula a entrada do mouse derivando do controle e
usando os métodos GetStyle e SetStyle. O método SetStyle usa uma combinação bit a bit de valores de
ControlStyles para determinar se o controle terá comportamento padrão ou de clique duplo ou se o controle
manipulará seu próprio processamento de mouse. Além disso, a classe SystemInformation inclui propriedades
que descrevem os recursos do mouse e especificam como o mouse interage com o sistema operacional. A tabela a
seguir resume essas propriedades.

P RO P RIEDA DE DESC RIÇ Ã O


P RO P RIEDA DE DESC RIÇ Ã O

DoubleClickSize Obtém as dimensões, em pixels, da área em que o usuário


deve clicar duas vezes para que o sistema operacional
considere os dois cliques um clique duplo.

DoubleClickTime Obtém o número máximo de milissegundos que pode


decorrer entre um primeiro clique e um segundo clique para
que o sistema operacional considere a ação do mouse um
clique duplo.

MouseButtons Obtém o número de botões do mouse.

MouseButtonsSwapped Obtém um valor que indica se as funções dos botões


esquerdo e direito do mouse foram trocadas.

MouseHoverSize Obtém as dimensões, em pixels, do retângulo no qual o


ponteiro do mouse deve permanecer pelo tempo de foco do
mouse antes que uma mensagem de foco do mouse seja
gerada.

MouseHoverTime Obtém o tempo, em milissegundos, que o ponteiro do mouse


deve permanecer no retângulo de foco antes que uma
mensagem de foco do mouse seja gerada.

MousePresent Obtém um valor que indica se um mouse está instalado.

MouseSpeed Obtém um valor que indica a velocidade atual do mouse, de 1


a 20.

MouseWheelPresent Obtém um valor que indica se um mouse com botão de


rolagem está instalado.

MouseWheelScrollDelta Obtém o valor delta do incremento de uma única rotação da


roda do mouse.

MouseWheelScrollLines Obtém o número de linhas a rolar quando o botão de


rolagem do mouse é girado.

Consulte também
Entrada do mouse em um Aplicativo do Windows Forms
Captura do mouse nos Windows Forms
Ponteiros do mouse nos Windows Forms
Eventos do mouse no Windows Forms
03/02/2020 • 8 minutes to read • Edit Online

Quando manipula entradas de mouse, você geralmente deseja conhecer a localização do ponteiro do mouse e o
estado dos botões do mouse. Este tópico fornece detalhes sobre como obter essas informações de eventos do
mouse e explica a ordem em que eventos de clique do mouse são gerados em controles dos Windows Forms.
Para obter uma lista e uma descrição de todos os eventos de mouse, consulte Como a entrada do mouse
funciona nos Windows Forms. Consulte também visão geral de manipuladores de eventos (Windows Forms) e
visão geral de eventos (Windows Forms).

Informações sobre o mouse


Um MouseEventArgs é enviado aos manipuladores de eventos do mouse relacionados ao clique de um botão do
mouse e do controle dos movimentos do mouse. MouseEventArgs fornece informações sobre o estado atual do
mouse, incluindo o local do ponteiro do mouse nas coordenadas do cliente, quais botões do mouse são
pressionados e se a roda do mouse foi rolada. Vários eventos de mouse, como aqueles que simplesmente
notificam quando o ponteiro do mouse inseriu ou deixaram os limites de um controle, enviam um EventArgs ao
manipulador de eventos sem nenhuma informação adicional.
Se você quiser saber o estado atual dos botões do mouse ou o local do ponteiro do mouse e desejar evitar
manipular um evento do mouse, também poderá usar as propriedades MouseButtons e MousePosition da classe
Control. MouseButtons retorna informações sobre quais botões do mouse estão pressionados no momento. O
MousePosition retorna as coordenadas de tela do ponteiro do mouse e é equivalente ao valor retornado por
Position.

Convertendo entre coordenadas de cliente e da tela


Como algumas informações de localização do mouse estão em coordenadas de cliente e algumas estão em
coordenadas de tela, talvez seja necessário converter um ponto de um sistema de coordenadas para outro. Você
pode fazer isso facilmente usando os métodos PointToClient e PointToScreen disponíveis na classe Control.

Comportamento do evento de clique


Se quiser manipular eventos de clique do mouse na ordem correta, você precisará conhecer a ordem em que os
eventos de clique são gerados em controles dos Windows Forms. Todos os controles dos Windows Forms geram
eventos de clique na mesma ordem quando um botão do mouse é pressionado e liberado (independentemente
de qual botão do mouse), exceto onde é indicado na lista a seguir de controles individuais. A lista a seguir mostra
a ordem dos eventos gerados por um único clique do botão do mouse:
1. MouseDown .
2. Click .
3. MouseClick .
4. MouseUp .
A seguir está a ordem dos eventos gerados para um clique duplo com botão do mouse:
1. MouseDown .
2. Click .
3. MouseClick .
4. MouseUp .
5. MouseDown .
6. DoubleClick . (Isso pode variar, dependendo se o controle em questão tem o conjunto de bits
StandardDoubleClick de estilo definido como true . Para obter mais informações sobre como definir um
bit de ControlStyles, consulte o método SetStyle.)
7. MouseDoubleClick .
8. MouseUp .
Para ver um exemplo de código que mostra a ordem dos eventos de clique do mouse, consulte Como manipular
eventos de entrada do usuário em controles dos Windows Forms.
Controles individuais
Os controles a seguir não estão em conformidade com o comportamento padrão dos eventos de clique do
mouse:
Button
CheckBox
ComboBox
RadioButton

NOTE
Para o controle de ComboBox, o comportamento de evento detalhado posteriormente ocorrerá se o usuário clicar
no campo de edição, no botão ou em um item dentro da lista.

Clique com o botão esquerdo: Click, MouseClick


Clique com botão direito do mouse: não são gerados eventos de clique
Clique duas vezes com o botão esquerdo: Click, MouseClick; Click, MouseClick
Clique duas vezes com botão direito: não são gerados eventos de clique
controles TextBox, RichTextBox, ListBox, MaskedTextBoxe CheckedListBox

NOTE
O comportamento do evento detalhado a seguir ocorre quando o usuário clica em qualquer lugar desses controles.

Clique com o botão esquerdo: Click, MouseClick


Clique com botão direito do mouse: não são gerados eventos de clique
Clique duas vezes com o botão esquerdo: Click, MouseClick, DoubleClickMouseDoubleClick
Clique duas vezes com botão direito: não são gerados eventos de clique
Controle ListView
NOTE
O comportamento de evento detalhado posteriormente ocorre somente quando o usuário clica nos itens no
controle de ListView. Nenhum evento é gerado para cliques em qualquer outro lugar no controle. Além dos eventos
descritos posteriormente, há os eventos de BeforeLabelEdit e AfterLabelEdit, que podem ser de seu interesse se
você quiser usar a validação com o controle de ListView.

Clique com o botão esquerdo: Click, MouseClick


Clique com o botão direito do mouse em: Click, MouseClick
Clique duas vezes com o botão esquerdo: Click, MouseClick; DoubleClick, MouseDoubleClick
Clique duas vezes com o botão direito do mouse: Click, MouseClick; DoubleClick, MouseDoubleClick
Controle TreeView

NOTE
O comportamento de evento detalhado posteriormente ocorre apenas quando o usuário clica nos itens em si ou à
direita dos itens no controle de TreeView. Nenhum evento é gerado para cliques em qualquer outro lugar no
controle. Além daqueles descritos posteriormente, há os eventos BeforeCheck, BeforeSelect, BeforeLabelEdit,
AfterSelect, AfterChecke AfterLabelEdit, que podem ser de seu interesse se você quiser usar a validação com o
controle TreeView.

Clique com o botão esquerdo: Click, MouseClick


Clique com o botão direito do mouse em: Click, MouseClick
Clique duas vezes com o botão esquerdo: Click, MouseClick; DoubleClick, MouseDoubleClick
Clique duas vezes com o botão direito do mouse: Click, MouseClick; DoubleClick, MouseDoubleClick
Comportamento de pintura de controles de alternância
Os controles de alternância, como os controles derivados da classe ButtonBase, têm o seguinte comportamento
de pintura distinto em combinação com eventos de clique do mouse:
1. O usuário pressiona o botão do mouse.
2. O controle pinta no estado pressionado.
3. O evento MouseDown é gerado.
4. O usuário libera o botão do mouse.
5. O controle pinta no estado elevado.
6. O evento Click é gerado.
7. O evento MouseClick é gerado.
8. O evento MouseUp é gerado.
NOTE
Se o usuário mover o ponteiro para fora do controle de alternância enquanto o botão do mouse estiver inoperante
(como mover o mouse para fora do controle de Button enquanto ele é pressionado), o controle de alternância será
pintado no estado gerado e somente o evento de MouseUp ocorrerá. Os eventos de Click ou MouseClick não
ocorrerão nessa situação.

Consulte também
Entrada do mouse em um Aplicativo do Windows Forms
Como: distinguir entre cliques e cliques duplos
23/10/2019 • 11 minutes to read • Edit Online

Normalmente, um único clique inicia uma interface do usuário e um clique duplo estende a ação. Por exemplo, um
clique normalmente seleciona um item e um clique duplo edita o item selecionado. No entanto, eventos de clique a
formulários do Windows não acomodam facilmente um cenário onde um clique e um clique duplo executam ações
incompatíveis, como uma ação associada à Click ou MouseClick eventos é executado antes da ação ligada para o
DoubleClickou MouseDoubleClick eventos. Este tópico demonstra duas soluções para esse problema. Uma solução
é manipular o evento de clique duplo e reverter as ações no tratamento de evento de clique. Em raras situações,
você talvez seja necessário simular um clique e comportamento de clique duplo manipulando o MouseDown
evento e, usando o DoubleClickTime e DoubleClickSize propriedades do SystemInformation classe. Você medir o
tempo entre cliques e se um segundo clique ocorre antes do valor de DoubleClickTime for atingido e o clique foi
dentro de um retângulo definido por DoubleClickSize, executar a ação de clique duplo; caso contrário, execute a
ação de clique.
Reverter uma ação de clique
Verifique se o controle em que você está trabalhando tem um comportamento de clique duplo padrão. Se
não estiver, habilite o controle com o SetStyle método. Trate o evento de clique duplo e reverta a ação de
clique, bem como a ação de clique duplo. O exemplo de código a seguir demonstra um como criar um botão
personalizado com clique duplo habilitado, bem como reverter a ação de clique no código de tratamento de
eventos de clique duplo.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace MouseRollBackSingleClick
{
public class Form1 : Form
{
private DoubleClickButton button1;
private FormBorderStyle initialStyle;

public Form1()
{
initialStyle = this.FormBorderStyle;
this.ClientSize = new System.Drawing.Size(292, 266);
button1 = new DoubleClickButton();
button1.Location = new Point (40,40);
button1.Click += new EventHandler(button1_Click);
button1.AutoSize = true;
this.AllowDrop = true;
button1.Text = "Click or Double Click";
button1.DoubleClick += new EventHandler(button1_DoubleClick);
this.Controls.Add(button1);
}

// Handle the double click event.


void button1_DoubleClick(object sender, EventArgs e)
{
// Change the border style back to the initial style.
this.FormBorderStyle = initialStyle;
MessageBox.Show("Rolled back single click change.");
}

// Handle the click event.


void button1_Click(object sender, EventArgs e)
{
this.FormBorderStyle = FormBorderStyle.FixedToolWindow;
}

[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
}
public class DoubleClickButton : Button
{
public DoubleClickButton() : base()
{
// Set the style so a double click event occurs.
SetStyle(ControlStyles.StandardClick |
ControlStyles.StandardDoubleClick, true);
}
}
}
Imports System.ComponentModel
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms

Public Class Form1


Inherits Form
Private WithEvents button1 As DoubleClickButton
Private initialStyle As FormBorderStyle

Public Sub New()


Me.SuspendLayout()
initialStyle = Me.FormBorderStyle
Me.ClientSize = New System.Drawing.Size(292, 266)
button1 = New DoubleClickButton()
button1.Location = New Point(40, 40)
button1.AutoSize = True
button1.Text = "Click or Double Click"
Me.Controls.Add(button1)
Me.Name = "Form1"
Me.ResumeLayout(False)
Me.PerformLayout()

End Sub

' Handle the double click event.


Private Sub button1_DoubleClick(ByVal sender As Object, ByVal e As EventArgs) _
Handles button1.DoubleClick

' Change the border style back to the initial style.


Me.FormBorderStyle = initialStyle
MessageBox.Show("Rolled back single click change.")

End Sub

' Handle the click event.


Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs) _
Handles button1.Click

Me.FormBorderStyle = FormBorderStyle.FixedToolWindow

End Sub

<STAThread()> _
Shared Sub Main()
Application.EnableVisualStyles()
Application.Run(New Form1())

End Sub
End Class

Public Class DoubleClickButton


Inherits Button

Public Sub New()


' Set the style so a double click event occurs.
SetStyle(ControlStyles.StandardClick Or ControlStyles.StandardDoubleClick, True)

End Sub
End Class
Distinguir entre cliques no evento MouseDown
Lidar com o MouseDown eventos e determinar o local e o tempo de espaço entre os cliques usando
apropriado SystemInformation propriedades e um Timer componente. Execute a ação apropriada
dependendo se ocorreu um clique ou um clique duplo. O exemplo de código a seguir demonstra como fazer
isso.

#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>
#using <System.dll>

using namespace System;


using namespace System::Drawing;
using namespace System::Windows::Forms;

namespace SingleVersusDoubleClick
{
public ref class Form1 : public Form
{
private:
Rectangle hitTestRectangle;
private:
Rectangle doubleClickRectangle;
private:
TextBox^ outputBox;
private:
Timer^ doubleClickTimer;
private:
ProgressBar^ doubleClickBar;
private:
Label^ hitTestLabel;
private:
Label^ timerLabel;
private:
bool isFirstClick;
private:
bool isDoubleClick;
private:
int milliseconds;

public:
Form1()
{
hitTestRectangle = Rectangle();
hitTestRectangle.Location = Point(30, 20);
hitTestRectangle.Size = System::Drawing::Size(100, 40);

doubleClickRectangle = Rectangle();

outputBox = gcnew TextBox();


outputBox->Location = Point(30, 120);
outputBox->Size = System::Drawing::Size(200, 100);
outputBox->AutoSize = false;
outputBox->Multiline = true;

doubleClickTimer = gcnew Timer();


doubleClickTimer->Interval = 100;
doubleClickTimer->Tick +=
gcnew EventHandler(this, &Form1::doubleClickTimer_Tick);

doubleClickBar = gcnew ProgressBar();


doubleClickBar->Location = Point(30, 85);
doubleClickBar->Minimum = 0;
doubleClickBar->Maximum = SystemInformation::DoubleClickTime;

hitTestLabel = gcnew Label();


hitTestLabel->Location = Point(30, 5);
hitTestLabel->Size = System::Drawing::Size(100, 15);
hitTestLabel->Size = System::Drawing::Size(100, 15);
hitTestLabel->Text = "Hit test rectangle:";

timerLabel = gcnew Label();


timerLabel->Location = Point(30, 70);
timerLabel->Size = System::Drawing::Size(100, 15);
timerLabel->Text = "Double click timer:";

isFirstClick = true;

this->Paint += gcnew PaintEventHandler(this, &Form1::Form1_Paint);


this->MouseDown +=
gcnew MouseEventHandler(this, &Form1::Form1_MouseDown);
this->Controls->
AddRange(gcnew array<Control^> { doubleClickBar, outputBox,
hitTestLabel, timerLabel });
}

// Detect a valid single click or double click.


private:
void Form1_MouseDown(Object^ sender, MouseEventArgs^ e)
{
// Verify that the mouse click is in the main hit
// test rectangle.
if (!hitTestRectangle.Contains(e->Location))
{
return;
}

// This is the first mouse click.


if (isFirstClick)
{
isFirstClick = false;

// Determine the location and size of the double click


// rectangle area to draw around the cursor point.
doubleClickRectangle = Rectangle(
e->X - (SystemInformation::DoubleClickSize.Width / 2),
e->Y - (SystemInformation::DoubleClickSize.Height / 2),
SystemInformation::DoubleClickSize.Width,
SystemInformation::DoubleClickSize.Height);
Invalidate();

// Start the double click timer.


doubleClickTimer->Start();
}

// This is the second mouse click.


else
{
// Verify that the mouse click is within the double click
// rectangle and is within the system-defined double
// click period.
if (doubleClickRectangle.Contains(e->Location) &&
milliseconds < SystemInformation::DoubleClickTime)
{
isDoubleClick = true;
}
}
}

private:
void doubleClickTimer_Tick(Object^ sender, EventArgs^ e)
{
milliseconds += 100;
doubleClickBar->Increment(100);

// The timer has reached the double click time limit.


if (milliseconds >= SystemInformation::DoubleClickTime)
{
{
doubleClickTimer->Stop();

if (isDoubleClick)
{
outputBox->AppendText("Perform double click action");
outputBox->AppendText(Environment::NewLine);
}
else
{
outputBox->AppendText("Perform single click action");
outputBox->AppendText(Environment::NewLine);
}

// Allow the MouseDown event handler to process clicks again.


isFirstClick = true;
isDoubleClick = false;
milliseconds = 0;
doubleClickBar->Value = 0;
}
}

// Paint the hit test and double click rectangles.


private:
void Form1_Paint(Object^ sender, PaintEventArgs^ e)
{
// Draw the border of the main hit test rectangle.
e->Graphics->DrawRectangle(Pens::Black, hitTestRectangle);

// Fill in the double click rectangle.


e->Graphics->FillRectangle(Brushes::Blue, doubleClickRectangle);
}
};
}

[STAThread]
int main()
{
Application::EnableVisualStyles();
Application::Run(gcnew SingleVersusDoubleClick::Form1);
}

using System;
using System.Drawing;
using System.Windows.Forms;

namespace SingleVersusDoubleClick
{
class Form1 : Form
{
private Rectangle hitTestRectangle = new Rectangle();
private Rectangle doubleClickRectangle = new Rectangle();
private TextBox textBox1 = new TextBox();
private Timer doubleClickTimer = new Timer();
private ProgressBar doubleClickBar = new ProgressBar();
private Label label1 = new Label();
private Label label2 = new Label();
private bool isFirstClick = true;
private bool isDoubleClick = false;
private int milliseconds = 0;

[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
}

public Form1()
{
label1.Location = new Point(30, 5);
label1.Size = new Size(100, 15);
label1.Text = "Hit test rectangle:";

label2.Location = new Point(30, 70);


label2.Size = new Size(100, 15);
label2.Text = "Double click timer:";

hitTestRectangle.Location = new Point(30, 20);


hitTestRectangle.Size = new Size(100, 40);

doubleClickTimer.Interval = 100;
doubleClickTimer.Tick +=
new EventHandler(doubleClickTimer_Tick);

doubleClickBar.Location = new Point(30, 85);


doubleClickBar.Minimum = 0;
doubleClickBar.Maximum = SystemInformation.DoubleClickTime;

textBox1.Location = new Point(30, 120);


textBox1.Size = new Size(200, 100);
textBox1.AutoSize = false;
textBox1.Multiline = true;

this.Paint += new PaintEventHandler(Form1_Paint);


this.MouseDown += new MouseEventHandler(Form1_MouseDown);
this.Controls.AddRange(new Control[] { doubleClickBar, textBox1,
label1, label2 });
}

// Detect a valid single click or double click.


void Form1_MouseDown(object sender, MouseEventArgs e)
{
// Verify that the mouse click is in the main hit
// test rectangle.
if (!hitTestRectangle.Contains(e.Location))
{
return;
}

// This is the first mouse click.


if (isFirstClick)
{
isFirstClick = false;

// Determine the location and size of the double click


// rectangle area to draw around the cursor point.
doubleClickRectangle = new Rectangle(
e.X - (SystemInformation.DoubleClickSize.Width / 2),
e.Y - (SystemInformation.DoubleClickSize.Height / 2),
SystemInformation.DoubleClickSize.Width,
SystemInformation.DoubleClickSize.Height);
Invalidate();

// Start the double click timer.


doubleClickTimer.Start();
}

// This is the second mouse click.


else
{
// Verify that the mouse click is within the double click
// rectangle and is within the system-defined double
// click period.
if (doubleClickRectangle.Contains(e.Location) &&
milliseconds < SystemInformation.DoubleClickTime)
{
isDoubleClick = true;
}
}
}

void doubleClickTimer_Tick(object sender, EventArgs e)


{
milliseconds += 100;
doubleClickBar.Increment(100);

// The timer has reached the double click time limit.


if (milliseconds >= SystemInformation.DoubleClickTime)
{
doubleClickTimer.Stop();

if (isDoubleClick)
{
textBox1.AppendText("Perform double click action");
textBox1.AppendText(Environment.NewLine);
}
else
{
textBox1.AppendText("Perform single click action");
textBox1.AppendText(Environment.NewLine);
}

// Allow the MouseDown event handler to process clicks again.


isFirstClick = true;
isDoubleClick = false;
milliseconds = 0;
doubleClickBar.Value = 0;
}
}

// Paint the hit test and double click rectangles.


void Form1_Paint(object sender, PaintEventArgs e)
{
// Draw the border of the main hit test rectangle.
e.Graphics.DrawRectangle(Pens.Black, hitTestRectangle);

// Fill in the double click rectangle.


e.Graphics.FillRectangle(Brushes.Blue, doubleClickRectangle);
}
}
}

Imports System.Drawing
Imports System.Windows.Forms

Namespace SingleVersusDoubleClick

Class Form1
Inherits Form
Private hitTestRectangle As New Rectangle()
Private doubleClickRectangle As New Rectangle()
Private textBox1 As New TextBox()
Private WithEvents doubleClickTimer As New Timer()
Private doubleClickBar As New ProgressBar()
Private label1 As New Label()
Private label2 As New Label()
Private isFirstClick As Boolean = True
Private isDoubleClick As Boolean = False
Private milliseconds As Integer = 0

<STAThread()> _
Public Shared Sub Main()
Public Shared Sub Main()
Application.EnableVisualStyles()
Application.Run(New Form1())
End Sub

Public Sub New()


label1.Location = New Point(30, 5)
label1.Size = New Size(100, 15)
label1.Text = "Hit test rectangle:"

label2.Location = New Point(30, 70)


label2.Size = New Size(100, 15)
label2.Text = "Double click timer:"

hitTestRectangle.Location = New Point(30, 20)


hitTestRectangle.Size = New Size(100, 40)
doubleClickTimer.Interval = 100

doubleClickBar.Location = New Point(30, 85)


doubleClickBar.Minimum = 0
doubleClickBar.Maximum = SystemInformation.DoubleClickTime

textBox1.Location = New Point(30, 120)


textBox1.Size = New Size(200, 100)
textBox1.AutoSize = False
textBox1.Multiline = True

Me.Controls.Add(doubleClickBar)
Me.Controls.Add(textBox1)
Me.Controls.Add(label1)
Me.Controls.Add(label2)
End Sub

' Detect a valid single click or double click.


Sub Form1_MouseDown(ByVal sender As Object, _
ByVal e As MouseEventArgs) Handles Me.MouseDown

' Verify that the mouse click is in the main hit


' test rectangle.
If Not hitTestRectangle.Contains(e.Location) Then
Return
End If

' This is the first mouse click.


If isFirstClick = True Then
isFirstClick = False

' Determine the location and size of the double click


' rectangle to draw around the cursor point.
doubleClickRectangle = New Rectangle( _
e.X - (SystemInformation.DoubleClickSize.Width / 2), _
e.Y - (SystemInformation.DoubleClickSize.Height / 2), _
SystemInformation.DoubleClickSize.Width, _
SystemInformation.DoubleClickSize.Height)
Invalidate()

' Start the double click timer.


doubleClickTimer.Start()

' This is the second mouse click.


Else
' Verify that the mouse click is within the double click
' rectangle and is within the system-defined double
' click period.
If doubleClickRectangle.Contains(e.Location) And _
milliseconds < SystemInformation.DoubleClickTime Then
isDoubleClick = True
End If
End If
End Sub

Sub doubleClickTimer_Tick(ByVal sender As Object, _


ByVal e As EventArgs) Handles doubleClickTimer.Tick

milliseconds += 100
doubleClickBar.Increment(100)

' The timer has reached the double click time limit.
If milliseconds >= SystemInformation.DoubleClickTime Then
doubleClickTimer.Stop()

If isDoubleClick Then
textBox1.AppendText("Perform double click action")
textBox1.AppendText(Environment.NewLine)
Else
textBox1.AppendText("Perform single click action")
textBox1.AppendText(Environment.NewLine)
End If

' Allow the MouseDown event handler to process clicks again.


isFirstClick = True
isDoubleClick = False
milliseconds = 0
doubleClickBar.Value = 0
End If
End Sub

' Paint the hit test and double click rectangles.


Sub Form1_Paint(ByVal sender As Object, _
ByVal e As PaintEventArgs) Handles Me.Paint

' Draw the border of the main hit test rectangle.


e.Graphics.DrawRectangle(Pens.Black, hitTestRectangle)

' Fill in the double click rectangle.


e.Graphics.FillRectangle(Brushes.Blue, doubleClickRectangle)
End Sub
End Class
End Namespace

Compilando o código
Esses exemplos precisam de:
Referências aos assemblies System, System.Drawing e System.Windows.Forms.

Consulte também
Entrada do mouse em um Aplicativo do Windows Forms
Ponteiros do mouse no Windows Forms
03/02/2020 • 3 minutes to read • Edit Online

O ponteiro do mouse, que às vezes é conhecido como o cursor, é um bitmap que especifica um ponto de foco na
tela para entrada do usuário com o mouse. Este tópico fornece uma visão geral do ponteiro do mouse no
Windows Forms e descreve algumas maneiras de modificar e controlar o ponteiro do mouse.

Acessando o ponteiro do mouse


O ponteiro do mouse é representado pela classe Cursor, e cada Control tem uma propriedade Control.Cursor que
especifica o ponteiro para esse controle. A classe Cursor contém propriedades que descrevem o ponteiro, como as
propriedades Position e HotSpot, e os métodos que podem modificar a aparência do ponteiro, como os métodos
Show, Hidee DrawStretched.

Controlando o ponteiro do mouse


Às vezes, pode ser recomendável limitar a área na qual o ponteiro do mouse pode ser usado ou alterar a posição
do mouse. Você pode obter ou definir o local atual do mouse usando a propriedade Position da Cursor. Além disso,
você pode limitar a área em que o ponteiro do mouse pode ser usado para definir a propriedade Clip. A área de
recorte, por padrão, é a tela inteira.

Alterando o ponteiro do mouse


Alterar o ponteiro do mouse é uma maneira importante de fornecer comentários para o usuário. Por exemplo, o
ponteiro do mouse pode ser modificado nos manipuladores do MouseEnter e MouseLeave eventos para informar
ao usuário que as computações estão ocorrendo e limitar a interação do usuário no controle. Às vezes, o ponteiro
do mouse será alterado devido a eventos de sistema, como quando seu aplicativo está envolvido em uma
operação do tipo "arrastar e soltar".
A principal maneira de alterar o ponteiro do mouse é definindo a propriedade Control.Cursor ou DefaultCursor de
um controle para uma nova Cursor. Para obter exemplos de alteração do ponteiro do mouse, consulte o exemplo
de código na classe Cursor. Além disso, a classe Cursors expõe um conjunto de objetos Cursor para muitos tipos
diferentes de ponteiros, como um ponteiro que se assemelha a uma mão. Para exibir o ponteiro de espera, que se
assemelha a uma ampulheta, sempre que o ponteiro do mouse estiver no controle, use a propriedade
UseWaitCursor da classe Control.

Consulte também
Cursor
Entrada do mouse em um Aplicativo do Windows Forms
Funcionalidade do tipo "arrastar e soltar" no Windows Forms
Captura do mouse no Windows Forms
03/02/2020 • 2 minutes to read • Edit Online

Captura do mouse significa quando um controle toma o comando todas as entradas do mouse. Quando um
controle tiver capturado o mouse, ele recebe a entrada do mouse com o ponteiro estando ou não dentro de suas
bordas.

Configuração da captura do mouse


nos Windows Forms, o mouse é capturado pelo controle quando o usuário pressiona um botão do mouse em um
controle e o mouse é liberado pelo controle quando o usuário solta o botão do mouse.
A propriedade Capture da classe Control especifica se um controle capturou o mouse. Para determinar quando um
controle perde a captura do mouse, manipule o evento MouseCaptureChanged.
Somente a janela em primeiro plano pode capturar o mouse. Quando uma janela de tela de fundo tenta capturar o
mouse, a janela recebe mensagens apenas de eventos de mouse que ocorrerem quando o ponteiro do mouse
estiver dentro a parte visível da janela. Além disso, mesmo que a janela em primeiro plano tenha capturado o
mouse, o usuário ainda poderá clicar em outra janela, colocando-a em primeiro plano. Quando o mouse é
capturado, as teclas de atalho não funcionam.

Consulte também
Entrada do mouse em um Aplicativo do Windows Forms
Funcionalidade de arrastar e soltar no Windows
Forms
03/02/2020 • 4 minutes to read • Edit Online

O Windows Forms incluem um conjunto de métodos, eventos e classes que implementam o comportamento do
tipo "arrastar e soltar". Este tópico fornece uma visão geral do suporte a arrastar e soltar no Windows Forms.
Consulte também Operações do tipo "arrastar e soltar" e suporte à área de transferência.

Realizando operações do tipo "arrastar e soltar"


Para executar uma operação de arrastar e soltar, use o método DoDragDrop da classe Control. Para obter mais
informações sobre como uma operação de arrastar e soltar é executada, consulte DoDragDrop. Para obter o
retângulo no qual o ponteiro do mouse deve ser arrastado antes que uma operação de arrastar e soltar seja
iniciada, use a propriedade DragSize da classe SystemInformation.

Eventos relacionados a operações do tipo "arrastar e soltar"


Há duas categorias de eventos em uma operação de arrastar e soltar: os eventos que ocorrem no destino atual da
operação do tipo "arrastar e soltar" e eventos que ocorrem na fonte da operação de arrastar e soltar.
Eventos de destino atual
A tabela a seguir mostra os eventos que ocorrem no destino atual de uma operação do tipo "arrastar e soltar".

EVEN TO DE M O USE DESC RIÇ Ã O

DragEnter Esse evento ocorre quando um objeto é arrastado para os


limites do controle. O manipulador para esse evento recebe
um argumento do tipo DragEventArgs.

DragOver Esse evento ocorre quando um objeto é arrastado enquanto o


ponteiro do mouse está dentro dos limites do controle. O
manipulador para esse evento recebe um argumento do tipo
DragEventArgs.

DragDrop Esse evento ocorre quando uma operação do tipo "arrastar e


soltar" é concluída. O manipulador para esse evento recebe
um argumento do tipo DragEventArgs.

DragLeave Esse evento ocorre quando um objeto é arrastado para fora


dos limites do controle. O manipulador para esse evento
recebe um argumento do tipo EventArgs.

A classe DragEventArgs fornece o local do ponteiro do mouse, o estado atual dos botões do mouse e as teclas
modificadoras do teclado, os dados que estão sendo arrastados e DragDropEffects valores que especificam as
operações permitidas pela origem do evento de arrastar e o efeito de soltar destino para a operação.
Eventos na fonte
A tabela a seguir mostra os eventos que ocorrem na fonte atual de uma operação do tipo "arrastar e soltar".
EVEN TO DE M O USE DESC RIÇ Ã O

GiveFeedback Esse evento ocorre durante uma operação de arrastar. Ele


fornece uma indicação visual para o usuário que a operação
do tipo "arrastar e soltar" está ocorrendo, como uma alteração
no ponteiro do mouse. O manipulador para esse evento
recebe um argumento do tipo GiveFeedbackEventArgs.

QueryContinueDrag Esse evento é gerado durante uma operação do tipo "arrastar


e soltar" e permite que a fonte de arrastar determine se a
operação do tipo "arrastar e soltar" deve ser cancelada. O
manipulador para esse evento recebe um argumento do tipo
QueryContinueDragEventArgs.

A classe QueryContinueDragEventArgs fornece o estado atual dos botões do mouse e as teclas modificadoras do
teclado, um valor que especifica se a tecla ESC foi pressionada e um valor DragAction que pode ser definido para
especificar se a operação de arrastar e soltar deve continuar.

Consulte também
Entrada do mouse em um Aplicativo do Windows Forms
Como simular eventos de mouse e teclado no código
11/12/2019 • 13 minutes to read • Edit Online

O Windows Forms fornece várias opções para simular programaticamente entradas do mouse e do teclado. Este
tópico fornece uma visão geral dessas opções.

Simulando entrada do mouse


A melhor maneira de simular eventos do mouse é chamar o método On EventName que gera o evento de mouse
que você deseja simular. Essa opção é possível apenas dentro de controles e formulários personalizados, pois os
métodos que geram eventos são protegidos e não podem ser acessados fora do controle ou do formulário. Por
exemplo, as etapas a seguir ilustram como simular um clique no botão direito do mouse no código.
Para clicar programaticamente no botão direito do mouse
1. Crie um MouseEventArgs cuja propriedade Button esteja definida como o valor MouseButtons.Right.
2. Chame o método OnMouseClick com este MouseEventArgs como o argumento.
Para obter mais informações sobre controles personalizados, consulte Desenvolvendo Controles dos Windows
Forms no Tempo de Design.
Existem outras maneiras de simular a entrada do mouse. Por exemplo, você pode definir programaticamente uma
propriedade de controle que representa um estado que normalmente é definido por meio de entrada do mouse
(como a propriedade Checked do controle CheckBox), ou você pode chamar diretamente o delegado que está
anexado ao evento que você deseja simular.

Simulando Entrada do Teclado


Embora você possa simular a entrada do teclado usando as estratégias discutidas acima para entrada do mouse,
Windows Forms também fornece a classe SendKeys para enviar pressionamentos de teclas para o aplicativo ativo.
Cau t i on

Se seu aplicativo for destinado ao uso internacional com uma variedade de teclados, o uso de SendKeys.Send
poderá gerar resultados imprevisíveis e deve ser evitado.
NOTE
A classe SendKeys foi atualizada para o .NET Framework 3,0 para habilitar seu uso em aplicativos executados no Windows
Vista. A segurança avançada do Windows Vista (conhecida como Controle de Conta de Usuário ou UAC) impede que a
implementação anterior funcione conforme o esperado.
A classe SendKeys é suscetível a problemas de tempo, que alguns desenvolvedores precisavam solucionar. A implementação
atualizada ainda está suscetível a problemas de atraso, mas é ligeiramente mais rápida e pode exigir alterações para as
soluções alternativas. A classe SendKeys tenta usar a implementação anterior primeiro e, se isso falhar, usará a nova
implementação. Como resultado, a classe SendKeys pode se comportar de forma diferente em sistemas operacionais
diferentes. Além disso, quando a classe SendKeys usa a nova implementação, o método SendWait não aguardará que as
mensagens sejam processadas quando forem enviadas a outro processo.
Se seu aplicativo depender de um comportamento consistente independentemente do sistema operacional, você poderá
forçar a classe de SendKeys a usar a nova implementação adicionando a seguinte configuração de aplicativo ao seu arquivo
app. config.

<appSettings>
<add key="SendKeys" value="SendInput"/>
</appSettings>

Para forçar a classe de SendKeys a usar a implementação anterior, use o valor "JournalHook" em vez disso.

Para enviar um pressionamento de tecla para o mesmo aplicativo


1. Chame o método Send ou SendWait da classe SendKeys. Os pressionamentos de teclas especificados serão
recebidos pelo controle ativo do aplicativo. O exemplo de código a seguir usa Send para simular o
pressionamento da tecla ENTER quando o usuário clica duas vezes na superfície do formulário. Este exemplo
pressupõe um Form com um único controle de Button que tem um índice de tabulação de 0.

// Send a key to the button when the user double-clicks anywhere


// on the form.
private:
void Form1_DoubleClick(Object^ sender, EventArgs^ e)
{
// Send the enter key to the button, which triggers the click
// event for the button. This works because the tab stop of
// the button is 0.
SendKeys::Send("{ENTER}");
}

// Send a key to the button when the user double-clicks anywhere


// on the form.
private void Form1_DoubleClick(object sender, EventArgs e)
{
// Send the enter key to the button, which raises the click
// event for the button. This works because the tab stop of
// the button is 0.
SendKeys.Send("{ENTER}");
}
' Send a key to the button when the user double-clicks anywhere
' on the form.
Private Sub Form1_DoubleClick(ByVal sender As Object, _
ByVal e As EventArgs) Handles Me.DoubleClick

' Send the enter key to the button, which raises the click
' event for the button. This works because the tab stop of
' the button is 0.
SendKeys.Send("{ENTER}")
End Sub

Para enviar um pressionamento de tecla para um aplicativo diferente


1. Ative a janela do aplicativo que receberá os pressionamentos de tecla e, em seguida, chame o método Send
ou SendWait. Como não há nenhum método gerenciado para ativar outro aplicativo, você deve usar
métodos nativos do Windows para forçar foco em outros aplicativos. O exemplo de código a seguir usa a
invocação de plataforma para chamar os métodos FindWindow e SetForegroundWindow para ativar a janela
do aplicativo de calculadora e, em seguida, chama SendWait para emitir uma série de cálculos para o
aplicativo de calculadora.

NOTE
Os parâmetros corretos da chamada FindWindow que localiza o aplicativo Calculadora variam de acordo com sua
versão do Windows. O código a seguir encontra o aplicativo de calculadora no Windows 7. No Windows Vista, altere o
primeiro parâmetro para "SciCalc". Você pode usar a ferramenta Spy++, incluída no Visual Studio, para determinar os
parâmetros corretos.

// Get a handle to an application window.


public:
[DllImport("USER32.DLL", CharSet = CharSet::Unicode)]
static IntPtr FindWindow(String^ lpClassName, String^ lpWindowName);
public:
// Activate an application window.
[DllImport("USER32.DLL")]
static bool SetForegroundWindow(IntPtr hWnd);

// Send a series of key presses to the Calculator application.


private:
void button1_Click(Object^ sender, EventArgs^ e)
{
// Get a handle to the Calculator application. The window class
// and window name were obtained using the Spy++ tool.
IntPtr calculatorHandle = FindWindow("CalcFrame", "Calculator");

// Verify that Calculator is a running process.


if (calculatorHandle == IntPtr::Zero)
{
MessageBox::Show("Calculator is not running.");
return;
}

// Make Calculator the foreground application and send it


// a set of calculations.
SetForegroundWindow(calculatorHandle);
SendKeys::SendWait("111");
SendKeys::SendWait("*");
SendKeys::SendWait("11");
SendKeys::SendWait("=");
}
// Get a handle to an application window.
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName,
string lpWindowName);

// Activate an application window.


[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);

// Send a series of key presses to the Calculator application.


private void button1_Click(object sender, EventArgs e)
{
// Get a handle to the Calculator application. The window class
// and window name were obtained using the Spy++ tool.
IntPtr calculatorHandle = FindWindow("CalcFrame","Calculator");

// Verify that Calculator is a running process.


if (calculatorHandle == IntPtr.Zero)
{
MessageBox.Show("Calculator is not running.");
return;
}

// Make Calculator the foreground application and send it


// a set of calculations.
SetForegroundWindow(calculatorHandle);
SendKeys.SendWait("111");
SendKeys.SendWait("*");
SendKeys.SendWait("11");
SendKeys.SendWait("=");
}

' Get a handle to an application window.


Declare Auto Function FindWindow Lib "USER32.DLL" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr

' Activate an application window.


Declare Auto Function SetForegroundWindow Lib "USER32.DLL" _
(ByVal hWnd As IntPtr) As Boolean

' Send a series of key presses to the Calculator application.


Private Sub button1_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles button1.Click

' Get a handle to the Calculator application. The window class


' and window name were obtained using the Spy++ tool.
Dim calculatorHandle As IntPtr = FindWindow("CalcFrame", "Calculator")

' Verify that Calculator is a running process.


If calculatorHandle = IntPtr.Zero Then
MsgBox("Calculator is not running.")
Return
End If

' Make Calculator the foreground application and send it


' a set of calculations.
SetForegroundWindow(calculatorHandle)
SendKeys.SendWait("111")
SendKeys.SendWait("*")
SendKeys.SendWait("11")
SendKeys.SendWait("=")
End Sub
Exemplo
O exemplo de código a seguir é o aplicativo completo para os exemplos de código anteriores.

#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>
#using <System.dll>

using namespace System;


using namespace System::Runtime::InteropServices;
using namespace System::Drawing;
using namespace System::Windows::Forms;

namespace SimulateKeyPress
{

public ref class Form1 : public Form


{
public:
Form1()
{
Button^ button1 = gcnew Button();
button1->Location = Point(10, 10);
button1->TabIndex = 0;
button1->Text = "Click to automate Calculator";
button1->AutoSize = true;
button1->Click += gcnew EventHandler(this, &Form1::button1_Click);

this->DoubleClick += gcnew EventHandler(this,


&Form1::Form1_DoubleClick);
this->Controls->Add(button1);
}

// Get a handle to an application window.


public:
[DllImport("USER32.DLL", CharSet = CharSet::Unicode)]
static IntPtr FindWindow(String^ lpClassName, String^ lpWindowName);
public:
// Activate an application window.
[DllImport("USER32.DLL")]
static bool SetForegroundWindow(IntPtr hWnd);

// Send a series of key presses to the Calculator application.


private:
void button1_Click(Object^ sender, EventArgs^ e)
{
// Get a handle to the Calculator application. The window class
// and window name were obtained using the Spy++ tool.
IntPtr calculatorHandle = FindWindow("CalcFrame", "Calculator");

// Verify that Calculator is a running process.


if (calculatorHandle == IntPtr::Zero)
{
MessageBox::Show("Calculator is not running.");
return;
}

// Make Calculator the foreground application and send it


// a set of calculations.
SetForegroundWindow(calculatorHandle);
SendKeys::SendWait("111");
SendKeys::SendWait("*");
SendKeys::SendWait("11");
SendKeys::SendWait("=");
}

// Send a key to the button when the user double-clicks anywhere


// on the form.
// on the form.
private:
void Form1_DoubleClick(Object^ sender, EventArgs^ e)
{
// Send the enter key to the button, which triggers the click
// event for the button. This works because the tab stop of
// the button is 0.
SendKeys::Send("{ENTER}");
}
};
}

[STAThread]
int main()
{
Application::EnableVisualStyles();
Application::Run(gcnew SimulateKeyPress::Form1());
}

using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;

namespace SimulateKeyPress
{
class Form1 : Form
{
private Button button1 = new Button();

[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}

public Form1()
{
button1.Location = new Point(10, 10);
button1.TabIndex = 0;
button1.Text = "Click to automate Calculator";
button1.AutoSize = true;
button1.Click += new EventHandler(button1_Click);

this.DoubleClick += new EventHandler(Form1_DoubleClick);


this.Controls.Add(button1);
}

// Get a handle to an application window.


[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName,
string lpWindowName);

// Activate an application window.


[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);

// Send a series of key presses to the Calculator application.


private void button1_Click(object sender, EventArgs e)
{
// Get a handle to the Calculator application. The window class
// and window name were obtained using the Spy++ tool.
IntPtr calculatorHandle = FindWindow("CalcFrame","Calculator");

// Verify that Calculator is a running process.


if (calculatorHandle == IntPtr.Zero)
{
{
MessageBox.Show("Calculator is not running.");
return;
}

// Make Calculator the foreground application and send it


// a set of calculations.
SetForegroundWindow(calculatorHandle);
SendKeys.SendWait("111");
SendKeys.SendWait("*");
SendKeys.SendWait("11");
SendKeys.SendWait("=");
}

// Send a key to the button when the user double-clicks anywhere


// on the form.
private void Form1_DoubleClick(object sender, EventArgs e)
{
// Send the enter key to the button, which raises the click
// event for the button. This works because the tab stop of
// the button is 0.
SendKeys.Send("{ENTER}");
}
}
}

Imports System.Runtime.InteropServices
Imports System.Drawing
Imports System.Windows.Forms

Namespace SimulateKeyPress

Class Form1
Inherits Form
Private WithEvents button1 As New Button()

<STAThread()> _
Public Shared Sub Main()
Application.EnableVisualStyles()
Application.Run(New Form1())
End Sub

Public Sub New()


button1.Location = New Point(10, 10)
button1.TabIndex = 0
button1.Text = "Click to automate Calculator"
button1.AutoSize = True
Me.Controls.Add(button1)
End Sub

' Get a handle to an application window.


Declare Auto Function FindWindow Lib "USER32.DLL" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr

' Activate an application window.


Declare Auto Function SetForegroundWindow Lib "USER32.DLL" _
(ByVal hWnd As IntPtr) As Boolean

' Send a series of key presses to the Calculator application.


Private Sub button1_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles button1.Click

' Get a handle to the Calculator application. The window class


' and window name were obtained using the Spy++ tool.
Dim calculatorHandle As IntPtr = FindWindow("CalcFrame", "Calculator")

' Verify that Calculator is a running process.


' Verify that Calculator is a running process.
If calculatorHandle = IntPtr.Zero Then
MsgBox("Calculator is not running.")
Return
End If

' Make Calculator the foreground application and send it


' a set of calculations.
SetForegroundWindow(calculatorHandle)
SendKeys.SendWait("111")
SendKeys.SendWait("*")
SendKeys.SendWait("11")
SendKeys.SendWait("=")
End Sub

' Send a key to the button when the user double-clicks anywhere
' on the form.
Private Sub Form1_DoubleClick(ByVal sender As Object, _
ByVal e As EventArgs) Handles Me.DoubleClick

' Send the enter key to the button, which raises the click
' event for the button. This works because the tab stop of
' the button is 0.
SendKeys.Send("{ENTER}")
End Sub

End Class
End Namespace

Compilando o Código
Este exemplo requer:
Referências aos assemblies System, System.Drawing e System.Windows.Forms.

Consulte também
Entrada do usuário nos Windows Forms
Como manipular eventos de entrada do usuário em
controles do Windows Forms
03/02/2020 • 27 minutes to read • Edit Online

Este exemplo demonstra como lidar com a maioria dos eventos de teclado, mouse, foco e validação que podem
ocorrer em um controle de Windows Forms. A caixa de texto chamada TextBoxInput recebe os eventos quando
ele tem o foco e as informações sobre cada evento são gravadas na caixa de texto chamada TextBoxOutput na
ordem em que os eventos são gerados. O aplicativo também inclui um conjunto de caixas de seleção que podem
ser usadas para filtrar os eventos a serem relatados.

{1>Exemplo<1}
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>
#using <System.dll>

using namespace System;


using namespace System::Drawing;
using namespace System::ComponentModel;
using namespace System::Windows::Forms;

namespace UserInputWalkthrough
{
public ref class Form1 : public Form
{
Label^ lblEvent;
Label^ lblInput;

TextBox^ TextBoxOutput;
TextBox^ TextBoxInput;
GroupBox^ GroupBoxEvents;
Button^ ButtonClear;
LinkLabel^ LinkLabelDrag;

CheckBox^ CheckBoxToggleAll;
CheckBox^ CheckBoxMouse;
CheckBox^ CheckBoxMouseEnter;
CheckBox^ CheckBoxMouseMove;
CheckBox^ CheckBoxMousePoints;
CheckBox^ CheckBoxMouseDrag;
CheckBox^ CheckBoxMouseDragOver;
CheckBox^ CheckBoxKeyboard;
CheckBox^ CheckBoxKeyUpDown;
CheckBox^ CheckBoxFocus;
CheckBox^ CheckBoxValidation;

public:
Form1() : Form()
{
this->Load += gcnew EventHandler(this, &Form1::Form1_Load);

lblEvent = gcnew Label();


lblInput = gcnew Label();

TextBoxOutput = gcnew TextBox();


TextBoxInput = gcnew TextBox();
GroupBoxEvents = gcnew GroupBox();
ButtonClear = gcnew Button();
LinkLabelDrag = gcnew LinkLabel();
LinkLabelDrag = gcnew LinkLabel();

CheckBoxToggleAll = gcnew CheckBox();


CheckBoxMouse = gcnew CheckBox();
CheckBoxMouseEnter = gcnew CheckBox();
CheckBoxMouseMove = gcnew CheckBox();
CheckBoxMousePoints = gcnew CheckBox();
CheckBoxMouseDrag = gcnew CheckBox();
CheckBoxMouseDragOver = gcnew CheckBox();
CheckBoxKeyboard = gcnew CheckBox();
CheckBoxKeyUpDown = gcnew CheckBox();
CheckBoxFocus = gcnew CheckBox();
CheckBoxValidation = gcnew CheckBox();
}

private:
void Form1_Load(Object^ sender, EventArgs^ e)
{
this->GroupBoxEvents->SuspendLayout();
this->SuspendLayout();

lblEvent->Location = Point(232, 12);


lblEvent->Size = System::Drawing::Size(98, 14);
lblEvent->AutoSize = true;
lblEvent->Text = "Generated Events:";

lblInput->Location = Point(13, 12);


lblInput->Size = System::Drawing::Size(95, 14);
lblInput->AutoSize = true;
lblInput->Text = "User Input Target:";

TextBoxInput->Location = Point(13, 34);


TextBoxInput->Size = System::Drawing::Size(200, 200);
TextBoxInput->AllowDrop = true;
TextBoxInput->AutoSize = false;
TextBoxInput->Cursor = Cursors::Cross;
TextBoxInput->Multiline = true;
TextBoxInput->TabIndex = 1;

LinkLabelDrag->AllowDrop = true;
LinkLabelDrag->AutoSize = true;
LinkLabelDrag->Location = Point(13, 240);
LinkLabelDrag->Size = System::Drawing::Size(175, 14);
LinkLabelDrag->TabIndex = 2;
LinkLabelDrag->TabStop = true;
LinkLabelDrag->Text = "Click here to use as a drag source";
LinkLabelDrag->Links->Add(gcnew LinkLabel::Link(0,
LinkLabelDrag->Text->Length));

GroupBoxEvents->Location = Point(13, 281);


GroupBoxEvents->Size = System::Drawing::Size(200, 302);
GroupBoxEvents->Text = "Event Filter:";
GroupBoxEvents->TabStop = true;
GroupBoxEvents->TabIndex = 3;
GroupBoxEvents->Controls->Add(CheckBoxMouseEnter);
GroupBoxEvents->Controls->Add(CheckBoxToggleAll);
GroupBoxEvents->Controls->Add(CheckBoxMousePoints);
GroupBoxEvents->Controls->Add(CheckBoxKeyUpDown);
GroupBoxEvents->Controls->Add(CheckBoxMouseDragOver);
GroupBoxEvents->Controls->Add(CheckBoxMouseDrag);
GroupBoxEvents->Controls->Add(CheckBoxValidation);
GroupBoxEvents->Controls->Add(CheckBoxMouseMove);
GroupBoxEvents->Controls->Add(CheckBoxFocus);
GroupBoxEvents->Controls->Add(CheckBoxKeyboard);
GroupBoxEvents->Controls->Add(CheckBoxMouse);

CheckBoxToggleAll->AutoSize = true;
CheckBoxToggleAll->Location = Point(7, 20);
CheckBoxToggleAll->Size = System::Drawing::Size(122, 17);
CheckBoxToggleAll->TabIndex = 4;
CheckBoxToggleAll->TabIndex = 4;
CheckBoxToggleAll->Text = "Toggle All Events";

CheckBoxMouse->AutoSize = true;
CheckBoxMouse->Location = Point(7, 45);
CheckBoxMouse->Size = System::Drawing::Size(137, 17);
CheckBoxMouse->TabIndex = 5;
CheckBoxMouse->Text = "Mouse and Click Events";

CheckBoxMouseEnter->AutoSize = true;
CheckBoxMouseEnter->Location = Point(26, 69);
CheckBoxMouseEnter->Margin =
System::Windows::Forms::Padding(3, 3, 3, 1);
CheckBoxMouseEnter->Size = System::Drawing::Size(151, 17);
CheckBoxMouseEnter->TabIndex = 6;
CheckBoxMouseEnter->Text = "Mouse Enter/Hover/Leave";

CheckBoxMouseMove->AutoSize = true;
CheckBoxMouseMove->Location = Point(26, 89);
CheckBoxMouseMove->Margin =
System::Windows::Forms::Padding(3, 2, 3, 3);
CheckBoxMouseMove->Size = System::Drawing::Size(120, 17);
CheckBoxMouseMove->TabIndex = 7;
CheckBoxMouseMove->Text = "Mouse Move Events";

CheckBoxMousePoints->AutoSize = true;
CheckBoxMousePoints->Location = Point(26, 112);
CheckBoxMousePoints->Margin =
System::Windows::Forms::Padding(3, 3, 3, 1);
CheckBoxMousePoints->Size = System::Drawing::Size(141, 17);
CheckBoxMousePoints->TabIndex = 8;
CheckBoxMousePoints->Text = "Draw Mouse Points";

CheckBoxMouseDrag->AutoSize = true;
CheckBoxMouseDrag->Location = Point(26, 135);
CheckBoxMouseDrag->Margin =
System::Windows::Forms::Padding(3, 1, 3, 3);
CheckBoxMouseDrag->Size = System::Drawing::Size(151, 17);
CheckBoxMouseDrag->TabIndex = 9;
CheckBoxMouseDrag->Text = "Mouse Drag && Drop Events";

CheckBoxMouseDragOver->AutoSize = true;
CheckBoxMouseDragOver->Location = Point(44, 159);
CheckBoxMouseDragOver->Size = System::Drawing::Size(142, 17);
CheckBoxMouseDragOver->TabIndex = 10;
CheckBoxMouseDragOver->Text = "Mouse Drag Over Events";

CheckBoxKeyboard->AutoSize = true;
CheckBoxKeyboard->Location = Point(8, 184);
CheckBoxKeyboard->Size = System::Drawing::Size(103, 17);
CheckBoxKeyboard->TabIndex = 11;
CheckBoxKeyboard->Text = "Keyboard Events";

CheckBoxKeyUpDown->AutoSize = true;
CheckBoxKeyUpDown->Location = Point(26, 207);
CheckBoxKeyUpDown->Margin =
System::Windows::Forms::Padding(3, 3, 3, 1);
CheckBoxKeyUpDown->Size = System::Drawing::Size(133, 17);
CheckBoxKeyUpDown->TabIndex = 12;
CheckBoxKeyUpDown->Text = "Key Up && Down Events";

CheckBoxFocus->AutoSize = true;
CheckBoxFocus->Location = Point(8, 233);
CheckBoxFocus->Margin =
System::Windows::Forms::Padding(3, 2, 3, 3);
CheckBoxFocus->Size = System::Drawing::Size(146, 17);
CheckBoxFocus->TabIndex = 13;
CheckBoxFocus->Text = "Focus && Activation Events";

CheckBoxValidation->AutoSize = true;
CheckBoxValidation->AutoSize = true;
CheckBoxValidation->Location = Point(8, 257);
CheckBoxValidation->Size = System::Drawing::Size(104, 17);
CheckBoxValidation->TabIndex = 14;
CheckBoxValidation->Text = "Validation Events";

TextBoxOutput->Location = Point(232, 34);


TextBoxOutput->Size = System::Drawing::Size(308, 510);
TextBoxOutput->Multiline = true;
TextBoxOutput->CausesValidation = false;
TextBoxOutput->ReadOnly = true;
TextBoxOutput->ScrollBars = ScrollBars::Vertical;
TextBoxOutput->TabIndex = 15;
TextBoxOutput->WordWrap = false;

ButtonClear->Location = Point(232, 560);


ButtonClear->Size = System::Drawing::Size(308, 23);
ButtonClear->TabIndex = 16;
ButtonClear->Text = "Clear Event List";

this->ClientSize = System::Drawing::Size(552, 595);


this->Controls->Add(LinkLabelDrag);
this->Controls->Add(ButtonClear);
this->Controls->Add(GroupBoxEvents);
this->Controls->Add(lblEvent);
this->Controls->Add(lblInput);
this->Controls->Add(TextBoxInput);
this->Controls->Add(TextBoxOutput);
this->Text = "User Input Events";

ButtonClear->Click +=
gcnew EventHandler(this, &Form1::ButtonClear_Click);
TextBoxInput->KeyDown +=
gcnew KeyEventHandler(this, &Form1::TextBoxInput_KeyDown);
TextBoxInput->KeyPress +=
gcnew KeyPressEventHandler(this,
&Form1::TextBoxInput_KeyPress);
TextBoxInput->KeyUp +=
gcnew KeyEventHandler(this, &Form1::TextBoxInput_KeyUp);
TextBoxInput->Click +=
gcnew EventHandler(this, &Form1::TextBoxInput_Click);
TextBoxInput->DoubleClick +=
gcnew EventHandler(this, &Form1::TextBoxInput_DoubleClick);
TextBoxInput->MouseClick +=
gcnew MouseEventHandler(this, &Form1::TextBoxInput_MouseClick);
TextBoxInput->MouseDoubleClick +=
gcnew MouseEventHandler(this,
&Form1::TextBoxInput_MouseDoubleClick);
TextBoxInput->MouseDown +=
gcnew MouseEventHandler(this, &Form1::TextBoxInput_MouseDown);
TextBoxInput->MouseUp +=
gcnew MouseEventHandler(this, &Form1::TextBoxInput_MouseUp);
TextBoxInput->MouseEnter +=
gcnew EventHandler(this, &Form1::TextBoxInput_MouseEnter);
TextBoxInput->MouseHover +=
gcnew EventHandler(this, &Form1::TextBoxInput_MouseHover);
TextBoxInput->MouseLeave +=
gcnew EventHandler(this, &Form1::TextBoxInput_MouseLeave);
TextBoxInput->MouseWheel +=
gcnew MouseEventHandler(this, &Form1::TextBoxInput_MouseWheel);
TextBoxInput->MouseMove +=
gcnew MouseEventHandler(this, &Form1::TextBoxInput_MouseMove);
TextBoxInput->MouseCaptureChanged +=
gcnew EventHandler(this,
&Form1::TextBoxInput_MouseCaptureChanged);
TextBoxInput->DragEnter +=
gcnew DragEventHandler(this, &Form1::TextBoxInput_DragEnter);
TextBoxInput->DragDrop +=
gcnew DragEventHandler(this, &Form1::TextBoxInput_DragDrop);
TextBoxInput->DragOver +=
gcnew DragEventHandler(this, &Form1::TextBoxInput_DragOver);
TextBoxInput->DragLeave +=
gcnew EventHandler(this, &Form1::TextBoxInput_DragLeave);
TextBoxInput->Enter +=
gcnew EventHandler(this, &Form1::TextBoxInput_Enter);
TextBoxInput->Leave +=
gcnew EventHandler(this, &Form1::TextBoxInput_Leave);
TextBoxInput->GotFocus +=
gcnew EventHandler(this, &Form1::TextBoxInput_GotFocus);
TextBoxInput->LostFocus +=
gcnew EventHandler(this, &Form1::TextBoxInput_LostFocus);
TextBoxInput->Validated +=
gcnew EventHandler(this, &Form1::TextBoxInput_Validated);
TextBoxInput->Validating +=
gcnew CancelEventHandler(this,
&Form1::TextBoxInput_Validating);

LinkLabelDrag->MouseDown +=
gcnew MouseEventHandler(this, &Form1::LinkLabelDrag_MouseDown);
LinkLabelDrag->GiveFeedback +=
gcnew GiveFeedbackEventHandler(this,
&Form1::LinkLabelDrag_GiveFeedback);

CheckBoxToggleAll->CheckedChanged +=
gcnew EventHandler(this,
&Form1::CheckBoxToggleAll_CheckedChanged);
CheckBoxMouse->CheckedChanged +=
gcnew EventHandler(this, &Form1::CheckBoxMouse_CheckedChanged);
CheckBoxMouseDrag->CheckedChanged +=
gcnew EventHandler(this,
&Form1::CheckBoxMouseDrag_CheckedChanged);
CheckBoxMouseEnter->CheckedChanged +=
gcnew EventHandler(this,
&Form1::CheckBoxMouseMove_CheckedChanged);
CheckBoxMouseMove->CheckedChanged +=
gcnew EventHandler(this,
&Form1::CheckBoxMouseMove_CheckedChanged);
CheckBoxKeyboard->CheckedChanged +=
gcnew EventHandler(this,
&Form1::CheckBoxKeyboard_CheckedChanged);

this->GroupBoxEvents->ResumeLayout(false);
this->GroupBoxEvents->PerformLayout();
this->ResumeLayout(false);
this->PerformLayout();
CheckAllChildCheckBoxes(this, true);
}

// Recursively search the form for all contained checkboxes and


// initially check them
private:
void CheckAllChildCheckBoxes(Control^ parent, bool value)
{
CheckBox^ box;
for each (Control^ currentControl in parent->Controls)
{
if (dynamic_cast<CheckBox^>(currentControl))
{
box = (CheckBox^)currentControl;
box->Checked = value;
}

// Recurse if control contains other controls


if (currentControl->Controls->Count > 0)
{
CheckAllChildCheckBoxes(currentControl, value);
}
}
}
}

// All-purpose method for displaying a line of text in one of the


// text boxes.
private:
void DisplayLine(String^ line)
{
TextBoxOutput->AppendText(line);
TextBoxOutput->AppendText(Environment::NewLine);
}

// Click event handler for the button that clears the text box.
private:
void ButtonClear_Click(Object^ sender, EventArgs^ e)
{
TextBoxOutput->Invalidate();
TextBoxOutput->Clear();
}

private:
void TextBoxInput_KeyDown(Object^ sender, KeyEventArgs^ e)
{
if (CheckBoxKeyUpDown->Checked)
{
DisplayLine("KeyDown: " + e->KeyData.ToString());
}
}

private:
void TextBoxInput_KeyUp(Object^ sender, KeyEventArgs^ e)
{
if (CheckBoxKeyUpDown->Checked)
{
DisplayLine("KeyUp: " + e->KeyData.ToString());
}
}

private:
void TextBoxInput_KeyPress(Object^ sender,
KeyPressEventArgs^ e)
{
if (CheckBoxKeyboard->Checked)
{
if (Char::IsWhiteSpace(e->KeyChar))
{
DisplayLine("KeyPress: WS");
}
else
{
DisplayLine("KeyPress: " + e->KeyChar.ToString());
}
}
}

private:
void TextBoxInput_Click(Object^ sender, EventArgs^ e)
{
if (CheckBoxMouse->Checked)
{
DisplayLine("Click event");
}
}

private:
void TextBoxInput_DoubleClick(Object^ sender, EventArgs^ e)
{
if (CheckBoxMouse->Checked)
{
DisplayLine("DoubleClick event");
DisplayLine("DoubleClick event");
}
}

private:
void TextBoxInput_MouseClick(Object^ sender, MouseEventArgs^ e)
{
if (CheckBoxMouse->Checked)
{
DisplayLine("MouseClick: " + e->Button.ToString() +
" " + e->Location.ToString());
}
}

private:
void TextBoxInput_MouseDoubleClick(Object^ sender,
MouseEventArgs^ e)
{
if (CheckBoxMouse->Checked)
{
DisplayLine("MouseDoubleClick: " + e->Button.ToString() +
" " + e->Location.ToString());
}
}

private:
void TextBoxInput_MouseDown(Object^ sender,
MouseEventArgs^ e)
{
if (CheckBoxMouse->Checked)
{
DisplayLine("MouseDown: " + e->Button.ToString() +
" " + e->Location.ToString());
}
}

private:
void TextBoxInput_MouseUp(Object^ sender,
MouseEventArgs^ e)
{
if (CheckBoxMouse->Checked)
{
DisplayLine("MouseUp: " + e->Button.ToString() +
" " + e->Location.ToString());
}

// The TextBox control was designed to change focus only on


// the primary click, so force focus to avoid user confusion.
if (!TextBoxInput->Focused)
{
TextBoxInput->Focus();
}
}

private:
void TextBoxInput_MouseEnter(Object^ sender, EventArgs^ e)
{
if (CheckBoxMouseEnter->Checked)
{
DisplayLine("MouseEnter event");
}
}

private:
void TextBoxInput_MouseHover(Object^ sender, EventArgs^ e)
{
if (CheckBoxMouseEnter->Checked)
{
DisplayLine("MouseHover event");
}
}
}

private:
void TextBoxInput_MouseLeave(Object^ sender, EventArgs^ e)
{
if (CheckBoxMouseEnter->Checked)
{
DisplayLine("MouseLeave event");
}
}

private:
void TextBoxInput_MouseWheel(Object^ sender,
MouseEventArgs^ e)
{
if (CheckBoxMouse->Checked)
{
DisplayLine("MouseWheel: " + e->Delta.ToString() +
" detents at " + e->Location.ToString());
}
}

private:
void TextBoxInput_MouseMove(Object^ sender,
MouseEventArgs^ e)
{
if (CheckBoxMouseMove->Checked)
{
DisplayLine("MouseMove: " + e->Button.ToString() + " " +
e->Location.ToString());
}

if (CheckBoxMousePoints->Checked)
{
Graphics^ g = TextBoxInput->CreateGraphics();
g->FillRectangle(Brushes::Black, e->Location.X,
e->Location.Y, 1, 1);
delete g;
}
}

private:
void TextBoxInput_MouseCaptureChanged(Object^ sender,
EventArgs^ e)
{
if (CheckBoxMouseDrag->Checked)
{
DisplayLine("MouseCaptureChanged event");
}
}

private:
void TextBoxInput_DragEnter(Object^ sender, DragEventArgs^ e)
{
if (CheckBoxMouseDrag->Checked)
{
Point^ pt = gcnew Point(e->X, e->Y);
DisplayLine("DragEnter: " +
CovertKeyStateToString(e->KeyState)
+ " at " + pt->ToString());
}
}

private:
void TextBoxInput_DragDrop(Object^ sender, DragEventArgs^ e)
{
if (CheckBoxMouseDrag->Checked)
{
Point^ pt = gcnew Point(e->X, e->Y);
Point^ pt = gcnew Point(e->X, e->Y);
DisplayLine("DragDrop: " +
CovertKeyStateToString(e->KeyState)
+ " at " + pt->ToString());
}
}

private:
void TextBoxInput_DragOver(Object^ sender, DragEventArgs^ e)
{
if (CheckBoxMouseDragOver->Checked)
{
Point^ pt = gcnew Point(e->X, e->Y);
DisplayLine("DragOver: " +
CovertKeyStateToString(e->KeyState)
+ " at " + pt->ToString());
}

// Allow if drop data is of type string.


if (!e->Data->GetDataPresent(String::typeid))
{
e->Effect = DragDropEffects::None;
}
else
{
e->Effect = DragDropEffects::Copy;
}
}

private:
void TextBoxInput_DragLeave(Object^ sender,
EventArgs^ e)
{
if (CheckBoxMouseDrag->Checked)
{
DisplayLine("DragLeave event");
}
}

private:
static String^ CovertKeyStateToString(int keyState)
{
String^ keyString = "None";

// Which button was pressed?


if ((keyState & 1) == 1)
{
keyString = "Left";
}
else if ((keyState & 2) == 2)
{
keyString = "Right";
}
else if ((keyState & 16) == 16)
{
keyString = "Middle";
}

// Are one or more modifier keys also pressed?


if ((keyState & 4) == 4)
{
keyString += "+SHIFT";
}

if ((keyState & 8) == 8)
{
keyString += "+CTRL";
}

if ((keyState & 32) == 32)


if ((keyState & 32) == 32)
{
keyString += "+ALT";
}

return keyString;
}

private:
void TextBoxInput_Enter(Object^ sender, EventArgs^ e)
{
if (CheckBoxFocus->Checked)
{
DisplayLine("Enter event");
}
}

private:
void TextBoxInput_Leave(Object^ sender, EventArgs^ e)
{
if (CheckBoxFocus->Checked)
{
DisplayLine("Leave event");
}
}

private:
void TextBoxInput_GotFocus(Object^ sender, EventArgs^ e)
{
if (CheckBoxFocus->Checked)
{
DisplayLine("GotFocus event");
}
}

private:
void TextBoxInput_LostFocus(Object^ sender, EventArgs^ e)
{
if (CheckBoxFocus->Checked)
{
DisplayLine("LostFocus event");
}
}

private:
void TextBoxInput_Validated(Object^ sender, EventArgs^ e)
{
if (CheckBoxValidation->Checked)
{
DisplayLine("Validated event");
}
}

private:
void TextBoxInput_Validating(
Object^ sender, CancelEventArgs^ e)
{
if (CheckBoxValidation->Checked)
{
DisplayLine("Validating event");
}
}

private:
void CheckBoxToggleAll_CheckedChanged(
Object^ sender, EventArgs^ e)
{
if (dynamic_cast<CheckBox^>(sender))
{
CheckAllChildCheckBoxes(this, ((CheckBox^)sender)->Checked);
}
}

private:
void CheckBoxMouse_CheckedChanged(
Object^ sender, EventArgs^ e)
{
ConfigureCheckBoxSettings();
}

private:
void CheckBoxMouseDrag_CheckedChanged(
Object^ sender, EventArgs^ e)
{
ConfigureCheckBoxSettings();
}

private:
void CheckBoxKeyboard_CheckedChanged(
Object^ sender, EventArgs^ e)
{
ConfigureCheckBoxSettings();
}

private:
void CheckBoxMouseMove_CheckedChanged(
Object^ sender, EventArgs^ e)
{
ConfigureCheckBoxSettings();
}

// Reconcile dependencies between the check box


// selection choices.
private:
void ConfigureCheckBoxSettings()
{
// CheckBoxMouse is a top-level check box.
if (!CheckBoxMouse->Checked)
{
CheckBoxMouseEnter->Enabled = false;
CheckBoxMouseMove->Enabled = false;
CheckBoxMouseDrag->Enabled = false;
CheckBoxMouseDragOver->Enabled = false;
CheckBoxMousePoints->Enabled = false;
}
else
{
CheckBoxMouseEnter->Enabled = true;
CheckBoxMouseMove->Enabled = true;
CheckBoxMouseDrag->Enabled = true;
CheckBoxMousePoints->Enabled = true;

// Enable children depending on the state of the parent.


if (!CheckBoxMouseDrag->Checked)
{
CheckBoxMouseDragOver->Enabled = false;
}
else
{
CheckBoxMouseDragOver->Enabled = true;
}
}

if (!CheckBoxKeyboard->Checked)
{
CheckBoxKeyUpDown->Enabled = false;
}
else
{
CheckBoxKeyUpDown->Enabled = true;
}
}

private:
void LinkLabelDrag_MouseDown(Object^ sender, MouseEventArgs^ e)
{
String^ data = "Sample Data";
LinkLabelDrag->DoDragDrop(data, DragDropEffects::All);
}

private:
void LinkLabelDrag_GiveFeedback(Object^ sender,
GiveFeedbackEventArgs^ e)
{
if ((e->Effect & DragDropEffects::Copy) ==
DragDropEffects::Copy)
{
LinkLabelDrag->Cursor = Cursors::HSplit;
}
else
{
LinkLabelDrag->Cursor = Cursors::Default;
}
}
};
}

[STAThread]
int main()
{
Application::EnableVisualStyles();
Application::Run(gcnew UserInputWalkthrough::Form1());
}

using System;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;

namespace UserInputWalkthrough
{
public class Form1 : Form
{
Label Label1 = new Label();
Label Label2 = new Label();
TextBox TextBoxOutput = new TextBox();
TextBox TextBoxInput = new TextBox();
GroupBox GroupBoxEvents = new GroupBox();
Button ButtonClear = new Button();
LinkLabel LinkLabelDrag = new LinkLabel();

CheckBox CheckBoxToggleAll = new CheckBox();


CheckBox CheckBoxMouse = new CheckBox();
CheckBox CheckBoxMouseEnter = new CheckBox();
CheckBox CheckBoxMouseMove = new CheckBox();
CheckBox CheckBoxMousePoints = new CheckBox();
CheckBox CheckBoxMouseDrag = new CheckBox();
CheckBox CheckBoxMouseDragOver = new CheckBox();
CheckBox CheckBoxKeyboard = new CheckBox();
CheckBox CheckBoxKeyUpDown = new CheckBox();
CheckBox CheckBoxFocus = new CheckBox();
CheckBox CheckBoxValidation = new CheckBox();

[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}

public Form1()
: base()
{
this.Load += new EventHandler(Form1_Load);
}

private void Form1_Load(object sender, EventArgs e)


{
this.GroupBoxEvents.SuspendLayout();
this.SuspendLayout();

Label1.Location = new Point(232, 12);


Label1.Size = new Size(98, 14);
Label1.AutoSize = true;
Label1.Text = "Generated Events:";

Label2.Location = new Point(13, 12);


Label2.Size = new Size(95, 14);
Label2.AutoSize = true;
Label2.Text = "User Input Target:";

TextBoxInput.Location = new Point(13, 34);


TextBoxInput.Size = new Size(200, 200);
TextBoxInput.AllowDrop = true;
TextBoxInput.AutoSize = false;
TextBoxInput.Cursor = Cursors.Cross;
TextBoxInput.Multiline = true;
TextBoxInput.TabIndex = 1;

LinkLabelDrag.AllowDrop = true;
LinkLabelDrag.AutoSize = true;
LinkLabelDrag.Location = new Point(13, 240);
LinkLabelDrag.Size = new Size(175, 14);
LinkLabelDrag.TabIndex = 2;
LinkLabelDrag.TabStop = true;
LinkLabelDrag.Text = "Click here to use as a drag source";
LinkLabelDrag.Links.Add(new LinkLabel.Link(0,
LinkLabelDrag.Text.Length));

GroupBoxEvents.Location = new Point(13, 281);


GroupBoxEvents.Size = new Size(200, 302);
GroupBoxEvents.Text = "Event Filter:";
GroupBoxEvents.TabStop = true;
GroupBoxEvents.TabIndex = 3;
GroupBoxEvents.Controls.Add(CheckBoxMouseEnter);
GroupBoxEvents.Controls.Add(CheckBoxToggleAll);
GroupBoxEvents.Controls.Add(CheckBoxMousePoints);
GroupBoxEvents.Controls.Add(CheckBoxKeyUpDown);
GroupBoxEvents.Controls.Add(CheckBoxMouseDragOver);
GroupBoxEvents.Controls.Add(CheckBoxMouseDrag);
GroupBoxEvents.Controls.Add(CheckBoxValidation);
GroupBoxEvents.Controls.Add(CheckBoxMouseMove);
GroupBoxEvents.Controls.Add(CheckBoxFocus);
GroupBoxEvents.Controls.Add(CheckBoxKeyboard);
GroupBoxEvents.Controls.Add(CheckBoxMouse);

CheckBoxToggleAll.AutoSize = true;
CheckBoxToggleAll.Location = new Point(7, 20);
CheckBoxToggleAll.Size = new Size(122, 17);
CheckBoxToggleAll.TabIndex = 4;
CheckBoxToggleAll.Text = "Toggle All Events";

CheckBoxMouse.AutoSize = true;
CheckBoxMouse.Location = new Point(7, 45);
CheckBoxMouse.Location = new Point(7, 45);
CheckBoxMouse.Size = new Size(137, 17);
CheckBoxMouse.TabIndex = 5;
CheckBoxMouse.Text = "Mouse and Click Events";

CheckBoxMouseEnter.AutoSize = true;
CheckBoxMouseEnter.Location = new Point(26, 69);
CheckBoxMouseEnter.Margin = new Padding(3, 3, 3, 1);
CheckBoxMouseEnter.Size = new System.Drawing.Size(151, 17);
CheckBoxMouseEnter.TabIndex = 6;
CheckBoxMouseEnter.Text = "Mouse Enter/Hover/Leave";

CheckBoxMouseMove.AutoSize = true;
CheckBoxMouseMove.Location = new Point(26, 89);
CheckBoxMouseMove.Margin = new Padding(3, 2, 3, 3);
CheckBoxMouseMove.Size = new Size(120, 17);
CheckBoxMouseMove.TabIndex = 7;
CheckBoxMouseMove.Text = "Mouse Move Events";

CheckBoxMousePoints.AutoSize = true;
CheckBoxMousePoints.Location = new Point(26, 112);
CheckBoxMousePoints.Margin = new Padding(3, 3, 3, 1);
CheckBoxMousePoints.Size = new Size(141, 17);
CheckBoxMousePoints.TabIndex = 8;
CheckBoxMousePoints.Text = "Draw Mouse Points";

CheckBoxMouseDrag.AutoSize = true;
CheckBoxMouseDrag.Location = new Point(26, 135);
CheckBoxMouseDrag.Margin = new Padding(3, 1, 3, 3);
CheckBoxMouseDrag.Size = new Size(151, 17);
CheckBoxMouseDrag.TabIndex = 9;
CheckBoxMouseDrag.Text = "Mouse Drag && Drop Events";

CheckBoxMouseDragOver.AutoSize = true;
CheckBoxMouseDragOver.Location = new Point(44, 159);
CheckBoxMouseDragOver.Size = new Size(142, 17);
CheckBoxMouseDragOver.TabIndex = 10;
CheckBoxMouseDragOver.Text = "Mouse Drag Over Events";

CheckBoxKeyboard.AutoSize = true;
CheckBoxKeyboard.Location = new Point(8, 184);
CheckBoxKeyboard.Size = new Size(103, 17);
CheckBoxKeyboard.TabIndex = 11;
CheckBoxKeyboard.Text = "Keyboard Events";

CheckBoxKeyUpDown.AutoSize = true;
CheckBoxKeyUpDown.Location = new Point(26, 207);
CheckBoxKeyUpDown.Margin = new Padding(3, 3, 3, 1);
CheckBoxKeyUpDown.Size = new Size(133, 17);
CheckBoxKeyUpDown.TabIndex = 12;
CheckBoxKeyUpDown.Text = "Key Up && Down Events";

CheckBoxFocus.AutoSize = true;
CheckBoxFocus.Location = new Point(8, 233);
CheckBoxFocus.Margin = new Padding(3, 2, 3, 3);
CheckBoxFocus.Size = new Size(146, 17);
CheckBoxFocus.TabIndex = 13;
CheckBoxFocus.Text = "Focus && Activation Events";

CheckBoxValidation.AutoSize = true;
CheckBoxValidation.Location = new Point(8, 257);
CheckBoxValidation.Size = new Size(104, 17);
CheckBoxValidation.TabIndex = 14;
CheckBoxValidation.Text = "Validation Events";

TextBoxOutput.Location = new Point(232, 34);


TextBoxOutput.Size = new Size(308, 510);
TextBoxOutput.Multiline = true;
TextBoxOutput.CausesValidation = false;
TextBoxOutput.ReadOnly = true;
TextBoxOutput.ReadOnly = true;
TextBoxOutput.ScrollBars = ScrollBars.Vertical;
TextBoxOutput.TabIndex = 15;
TextBoxOutput.WordWrap = false;

ButtonClear.Location = new Point(232, 560);


ButtonClear.Size = new Size(308, 23);
ButtonClear.TabIndex = 16;
ButtonClear.Text = "Clear Event List";

this.ClientSize = new Size(552, 595);


this.Controls.Add(LinkLabelDrag);
this.Controls.Add(ButtonClear);
this.Controls.Add(GroupBoxEvents);
this.Controls.Add(Label1);
this.Controls.Add(Label2);
this.Controls.Add(TextBoxInput);
this.Controls.Add(TextBoxOutput);
this.Text = "User Input Events";

ButtonClear.Click +=
new EventHandler(ButtonClear_Click);
TextBoxInput.KeyDown +=
new KeyEventHandler(TextBoxInput_KeyDown);
TextBoxInput.KeyPress +=
new KeyPressEventHandler(TextBoxInput_KeyPress);
TextBoxInput.KeyUp +=
new KeyEventHandler(TextBoxInput_KeyUp);
TextBoxInput.Click +=
new EventHandler(TextBoxInput_Click);
TextBoxInput.DoubleClick +=
new EventHandler(TextBoxInput_DoubleClick);
TextBoxInput.MouseClick +=
new MouseEventHandler(TextBoxInput_MouseClick);
TextBoxInput.MouseDoubleClick +=
new MouseEventHandler(TextBoxInput_MouseDoubleClick);
TextBoxInput.MouseDown +=
new MouseEventHandler(TextBoxInput_MouseDown);
TextBoxInput.MouseUp +=
new MouseEventHandler(TextBoxInput_MouseUp);
TextBoxInput.MouseEnter +=
new EventHandler(TextBoxInput_MouseEnter);
TextBoxInput.MouseHover +=
new EventHandler(TextBoxInput_MouseHover);
TextBoxInput.MouseLeave +=
new EventHandler(TextBoxInput_MouseLeave);
TextBoxInput.MouseWheel +=
new MouseEventHandler(TextBoxInput_MouseWheel);
TextBoxInput.MouseMove +=
new MouseEventHandler(TextBoxInput_MouseMove);
TextBoxInput.MouseCaptureChanged +=
new EventHandler(TextBoxInput_MouseCaptureChanged);
TextBoxInput.DragEnter +=
new DragEventHandler(TextBoxInput_DragEnter);
TextBoxInput.DragDrop +=
new DragEventHandler(TextBoxInput_DragDrop);
TextBoxInput.DragOver +=
new DragEventHandler(TextBoxInput_DragOver);
TextBoxInput.DragLeave +=
new EventHandler(TextBoxInput_DragLeave);
TextBoxInput.Enter +=
new EventHandler(TextBoxInput_Enter);
TextBoxInput.Leave +=
new EventHandler(TextBoxInput_Leave);
TextBoxInput.GotFocus +=
new EventHandler(TextBoxInput_GotFocus);
TextBoxInput.LostFocus +=
new EventHandler(TextBoxInput_LostFocus);
TextBoxInput.Validated +=
new EventHandler(TextBoxInput_Validated);
new EventHandler(TextBoxInput_Validated);
TextBoxInput.Validating +=
new CancelEventHandler(TextBoxInput_Validating);

LinkLabelDrag.MouseDown +=
new MouseEventHandler(LinkLabelDrag_MouseDown);
LinkLabelDrag.GiveFeedback +=
new GiveFeedbackEventHandler(LinkLabelDrag_GiveFeedback);

CheckBoxToggleAll.CheckedChanged +=
new EventHandler(CheckBoxToggleAll_CheckedChanged);
CheckBoxMouse.CheckedChanged +=
new EventHandler(CheckBoxMouse_CheckedChanged);
CheckBoxMouseDrag.CheckedChanged +=
new EventHandler(CheckBoxMouseDrag_CheckedChanged);
CheckBoxMouseEnter.CheckedChanged +=
new EventHandler(CheckBoxMouseMove_CheckedChanged);
CheckBoxMouseMove.CheckedChanged +=
new EventHandler(CheckBoxMouseMove_CheckedChanged);
CheckBoxKeyboard.CheckedChanged +=
new EventHandler(CheckBoxKeyboard_CheckedChanged);

this.GroupBoxEvents.ResumeLayout(false);
this.GroupBoxEvents.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
CheckAllChildCheckBoxes(this, true);
}

// Recursively search the form for all contained checkboxes and


// initially check them
private void CheckAllChildCheckBoxes(Control parent, bool value)
{
CheckBox box;
foreach (Control currentControl in parent.Controls)
{
if (currentControl is CheckBox)
{
box = (CheckBox)currentControl;
box.Checked = value;
}

// Recurse if control contains other controls


if (currentControl.Controls.Count > 0)
{
CheckAllChildCheckBoxes(currentControl, value);
}
}
}

// All-purpose method for displaying a line of text in one of the


// text boxes.
private void DisplayLine(string line)
{
TextBoxOutput.AppendText(line);
TextBoxOutput.AppendText(Environment.NewLine);
}

// Click event handler for the button that clears the text box.
private void ButtonClear_Click(object sender, EventArgs e)
{
TextBoxOutput.Invalidate();
TextBoxOutput.Clear();
}

private void TextBoxInput_KeyDown(object sender, KeyEventArgs e)


{
if (CheckBoxKeyUpDown.Checked)
{
DisplayLine("KeyDown: " + e.KeyData.ToString());
DisplayLine("KeyDown: " + e.KeyData.ToString());
}
}

private void TextBoxInput_KeyUp(object sender, KeyEventArgs e)


{
if (CheckBoxKeyUpDown.Checked)
{
DisplayLine("KeyUp: " + e.KeyData.ToString());
}
}

private void TextBoxInput_KeyPress(object sender,


KeyPressEventArgs e)
{
if (CheckBoxKeyboard.Checked)
{
if (Char.IsWhiteSpace(e.KeyChar))
{
DisplayLine("KeyPress: WS");
}
else
{
DisplayLine("KeyPress: " + e.KeyChar.ToString());
}
}
}

private void TextBoxInput_Click(object sender, EventArgs e)


{
if (CheckBoxMouse.Checked)
{
DisplayLine("Click event");
}
}

private void TextBoxInput_DoubleClick(object sender, EventArgs e)


{
if (CheckBoxMouse.Checked)
{
DisplayLine("DoubleClick event");
}
}

private void TextBoxInput_MouseClick(object sender, MouseEventArgs e)


{
if (CheckBoxMouse.Checked)
{
DisplayLine("MouseClick: " + e.Button.ToString() +
" " + e.Location.ToString());
}
}

private void TextBoxInput_MouseDoubleClick(object sender,


MouseEventArgs e)
{
if (CheckBoxMouse.Checked)
{
DisplayLine("MouseDoubleClick: " + e.Button.ToString() +
" " + e.Location.ToString());
}
}

private void TextBoxInput_MouseDown(object sender,


MouseEventArgs e)
{
if (CheckBoxMouse.Checked)
{
DisplayLine("MouseDown: " + e.Button.ToString() +
" " + e.Location.ToString());
" " + e.Location.ToString());
}
}

private void TextBoxInput_MouseUp(object sender,


MouseEventArgs e)
{
if (CheckBoxMouse.Checked)
{
DisplayLine("MouseUp: " + e.Button.ToString() +
" " + e.Location.ToString());
}

// The TextBox control was designed to change focus only on


// the primary click, so force focus to avoid user confusion.
if (!TextBoxInput.Focused)
{
TextBoxInput.Focus();
}
}

private void TextBoxInput_MouseEnter(object sender, EventArgs e)


{
if (CheckBoxMouseEnter.Checked)
{
DisplayLine("MouseEnter event");
}
}

private void TextBoxInput_MouseHover(object sender, EventArgs e)


{
if (CheckBoxMouseEnter.Checked)
{
DisplayLine("MouseHover event");
}
}

private void TextBoxInput_MouseLeave(object sender, EventArgs e)


{
if (CheckBoxMouseEnter.Checked)
{
DisplayLine("MouseLeave event");
}
}

private void TextBoxInput_MouseWheel(object sender,


MouseEventArgs e)
{
if (CheckBoxMouse.Checked)
{
DisplayLine("MouseWheel: " + e.Delta.ToString() +
" detents at " + e.Location.ToString());
}
}

private void TextBoxInput_MouseMove(object sender,


MouseEventArgs e)
{
if (CheckBoxMouseMove.Checked)
{
DisplayLine("MouseMove: " + e.Button.ToString() + " " +
e.Location.ToString());
}

if (CheckBoxMousePoints.Checked)
{
Graphics g = TextBoxInput.CreateGraphics();
g.FillRectangle(Brushes.Black, e.Location.X,
e.Location.Y, 1, 1);
g.Dispose();
}
}

private void TextBoxInput_MouseCaptureChanged(object sender,


EventArgs e)
{
if (CheckBoxMouseDrag.Checked)
{
DisplayLine("MouseCaptureChanged event");
}
}

private void TextBoxInput_DragEnter(object sender,


DragEventArgs e)
{
if (CheckBoxMouseDrag.Checked)
{
Point pt = new Point(e.X, e.Y);
DisplayLine("DragEnter: " +
CovertKeyStateToString(e.KeyState)
+ " at " + pt.ToString());
}
}

private void TextBoxInput_DragDrop(object sender,


DragEventArgs e)
{
if (CheckBoxMouseDrag.Checked)
{
Point pt = new Point(e.X, e.Y);
DisplayLine("DragDrop: " +
CovertKeyStateToString(e.KeyState)
+ " at " + pt.ToString());
}
}

private void TextBoxInput_DragOver(object sender,


DragEventArgs e)
{
if (CheckBoxMouseDragOver.Checked)
{
Point pt = new Point(e.X, e.Y);
DisplayLine("DragOver: " +
CovertKeyStateToString(e.KeyState)
+ " at " + pt.ToString());
}

// Allow if drop data is of type string.


if (!e.Data.GetDataPresent(typeof(String)))
{
e.Effect = DragDropEffects.None;
}
else
{
e.Effect = DragDropEffects.Copy;
}
}

private void TextBoxInput_DragLeave(object sender,


EventArgs e)
{
if (CheckBoxMouseDrag.Checked)
{
DisplayLine("DragLeave event");
}
}

private string CovertKeyStateToString(int keyState)


{
string keyString = "None";

// Which button was pressed?


if ((keyState & 1) == 1)
{
keyString = "Left";
}
else if ((keyState & 2) == 2)
{
keyString = "Right";
}
else if ((keyState & 16) == 16)
{
keyString = "Middle";
}

// Are one or more modifier keys also pressed?


if ((keyState & 4) == 4)
{
keyString += "+SHIFT";
}

if ((keyState & 8) == 8)
{
keyString += "+CTRL";
}

if ((keyState & 32) == 32)


{
keyString += "+ALT";
}

return keyString;
}

private void TextBoxInput_Enter(object sender, EventArgs e)


{
if (CheckBoxFocus.Checked)
{
DisplayLine("Enter event");
}
}

private void TextBoxInput_Leave(object sender, EventArgs e)


{
if (CheckBoxFocus.Checked)
{
DisplayLine("Leave event");
}
}

private void TextBoxInput_GotFocus(object sender, EventArgs e)


{
if (CheckBoxFocus.Checked)
{
DisplayLine("GotFocus event");
}
}

private void TextBoxInput_LostFocus(object sender, EventArgs e)


{
if (CheckBoxFocus.Checked)
{
DisplayLine("LostFocus event");
}
}

private void TextBoxInput_Validated(object sender, EventArgs e)


private void TextBoxInput_Validated(object sender, EventArgs e)
{
if (CheckBoxValidation.Checked)
{
DisplayLine("Validated event");
}
}

private void TextBoxInput_Validating(


object sender, CancelEventArgs e)
{
if (CheckBoxValidation.Checked)
{
DisplayLine("Validating event");
}
}

private void CheckBoxToggleAll_CheckedChanged(


object sender, EventArgs e)
{
if (sender is CheckBox)
{
CheckAllChildCheckBoxes(this, ((CheckBox)sender).Checked);
}
}

private void CheckBoxMouse_CheckedChanged(


object sender, EventArgs e)
{
ConfigureCheckBoxSettings();
}

private void CheckBoxMouseDrag_CheckedChanged(


object sender, EventArgs e)
{
ConfigureCheckBoxSettings();
}

private void CheckBoxKeyboard_CheckedChanged(


object sender, EventArgs e)
{
ConfigureCheckBoxSettings();
}

private void CheckBoxMouseMove_CheckedChanged(


object sender, EventArgs e)
{
ConfigureCheckBoxSettings();
}

// Reconcile dependencies between the check box


// selection choices.
private void ConfigureCheckBoxSettings()
{
// CheckBoxMouse is a top-level check box.
if (!CheckBoxMouse.Checked)
{
CheckBoxMouseEnter.Enabled = false;
CheckBoxMouseMove.Enabled = false;
CheckBoxMouseDrag.Enabled = false;
CheckBoxMouseDragOver.Enabled = false;
CheckBoxMousePoints.Enabled = false;
}
else
{
CheckBoxMouseEnter.Enabled = true;
CheckBoxMouseMove.Enabled = true;
CheckBoxMouseDrag.Enabled = true;
CheckBoxMousePoints.Enabled = true;
// Enable children depending on the state of the parent.
if (!CheckBoxMouseDrag.Checked)
{
CheckBoxMouseDragOver.Enabled = false;
}
else
{
CheckBoxMouseDragOver.Enabled = true;
}
}

if (!CheckBoxKeyboard.Checked)
{
CheckBoxKeyUpDown.Enabled = false;
}
else
{
CheckBoxKeyUpDown.Enabled = true;
}
}

private void LinkLabelDrag_MouseDown(object sender,


MouseEventArgs e)
{
string data = "Sample Data";
LinkLabelDrag.DoDragDrop(data, DragDropEffects.All);
}

private void LinkLabelDrag_GiveFeedback(object sender,


GiveFeedbackEventArgs e)
{
if ((e.Effect & DragDropEffects.Copy) ==
DragDropEffects.Copy)
{
LinkLabelDrag.Cursor = Cursors.HSplit;
}
else
{
LinkLabelDrag.Cursor = Cursors.Default;
}
}
}
}

Imports System.Drawing
Imports System.ComponentModel
Imports System.Windows.Forms

Namespace UserInputWalkthrough

Public Class Form1


Inherits Form

Dim Label1 As New Label


Dim Label2 As New Label
Dim TextBoxOutput As New TextBox
Dim WithEvents TextBoxInput As New TextBox
Dim WithEvents GroupBoxEvents As New GroupBox
Dim WithEvents ButtonClear As New Button
Dim WithEvents LinkLabelDrag As New LinkLabel

Dim WithEvents CheckBoxToggleAll As New CheckBox


Dim WithEvents CheckBoxMouse As New CheckBox
Dim WithEvents CheckBoxMouseEnter As New CheckBox
Dim WithEvents CheckBoxMouseMove As New CheckBox
Dim WithEvents CheckBoxMousePoints As New CheckBox
Dim WithEvents CheckBoxMouseDrag As New CheckBox
Dim WithEvents CheckBoxMouseDrag As New CheckBox
Dim WithEvents CheckBoxMouseDragOver As New CheckBox
Dim WithEvents CheckBoxKeyboard As New CheckBox
Dim WithEvents CheckBoxKeyUpDown As New CheckBox
Dim WithEvents CheckBoxFocus As New CheckBox
Dim WithEvents CheckBoxValidation As New CheckBox

<STAThread()> _
Shared Sub Main()
Application.EnableVisualStyles()
Application.Run(New Form1())
End Sub

Public Sub New()


MyBase.New()
End Sub

Private Sub Form1_Load(ByVal sender As Object, _


ByVal e As System.EventArgs) Handles MyBase.Load

Me.GroupBoxEvents.SuspendLayout()
Me.SuspendLayout()

Label1.Location = New Point(232, 12)


Label1.Size = New Size(98, 14)
Label1.AutoSize = True
Label1.Text = "Generated Events:"

Label2.Location = New Point(13, 12)


Label2.Size = New Size(95, 14)
Label2.AutoSize = True
Label2.Text = "User Input Target:"

TextBoxInput.Location = New Point(13, 34)


TextBoxInput.Size = New Size(200, 200)
TextBoxInput.AllowDrop = True
TextBoxInput.AutoSize = False
TextBoxInput.Cursor = Cursors.Cross
TextBoxInput.Multiline = True
TextBoxInput.TabIndex = 1

LinkLabelDrag.AllowDrop = True
LinkLabelDrag.AutoSize = True
LinkLabelDrag.Location = New Point(13, 240)
LinkLabelDrag.Size = New Size(175, 14)
LinkLabelDrag.TabIndex = 2
LinkLabelDrag.TabStop = True
LinkLabelDrag.Text = "Click here to use as a drag source"
LinkLabelDrag.Links.Add(New LinkLabel.Link(0, _
LinkLabelDrag.Text.Length))

GroupBoxEvents.Location = New Point(13, 281)


GroupBoxEvents.Size = New Size(200, 302)
GroupBoxEvents.TabIndex = 3
GroupBoxEvents.TabStop = False
GroupBoxEvents.Text = "Event Filter:"
GroupBoxEvents.Controls.Add(CheckBoxMouseEnter)
GroupBoxEvents.Controls.Add(CheckBoxToggleAll)
GroupBoxEvents.Controls.Add(CheckBoxMousePoints)
GroupBoxEvents.Controls.Add(CheckBoxKeyUpDown)
GroupBoxEvents.Controls.Add(CheckBoxMouseDragOver)
GroupBoxEvents.Controls.Add(CheckBoxMouseDrag)
GroupBoxEvents.Controls.Add(CheckBoxValidation)
GroupBoxEvents.Controls.Add(CheckBoxMouseMove)
GroupBoxEvents.Controls.Add(CheckBoxFocus)
GroupBoxEvents.Controls.Add(CheckBoxKeyboard)
GroupBoxEvents.Controls.Add(CheckBoxMouse)

CheckBoxToggleAll.AutoSize = True
CheckBoxToggleAll.Location = New Point(7, 20)
CheckBoxToggleAll.Location = New Point(7, 20)
CheckBoxToggleAll.Size = New Size(122, 17)
CheckBoxToggleAll.TabIndex = 4
CheckBoxToggleAll.Text = "Toggle All Events"

CheckBoxMouse.AutoSize = True
CheckBoxMouse.Location = New Point(7, 45)
CheckBoxMouse.Size = New Size(137, 17)
CheckBoxMouse.TabIndex = 5
CheckBoxMouse.Text = "Mouse and Click Events"

CheckBoxMouseEnter.AutoSize = True
CheckBoxMouseEnter.Location = New Point(26, 69)
CheckBoxMouseEnter.Margin = New Padding(3, 3, 3, 1)
CheckBoxMouseEnter.Size = New System.Drawing.Size(151, 17)
CheckBoxMouseEnter.TabIndex = 6
CheckBoxMouseEnter.Text = "Mouse Enter/Hover/Leave"

CheckBoxMouseMove.AutoSize = True
CheckBoxMouseMove.Location = New Point(26, 89)
CheckBoxMouseMove.Margin = New Padding(3, 2, 3, 3)
CheckBoxMouseMove.Size = New Size(120, 17)
CheckBoxMouseMove.TabIndex = 7
CheckBoxMouseMove.Text = "Mouse Move Events"

CheckBoxMousePoints.AutoSize = True
CheckBoxMousePoints.Location = New Point(26, 112)
CheckBoxMousePoints.Margin = New Padding(3, 3, 3, 1)
CheckBoxMousePoints.Size = New Size(141, 17)
CheckBoxMousePoints.TabIndex = 8
CheckBoxMousePoints.Text = "Draw Mouse Points"

CheckBoxMouseDrag.AutoSize = True
CheckBoxMouseDrag.Location = New Point(26, 135)
CheckBoxMouseDrag.Margin = New Padding(3, 1, 3, 3)
CheckBoxMouseDrag.Size = New Size(151, 17)
CheckBoxMouseDrag.TabIndex = 9
CheckBoxMouseDrag.Text = "Mouse Drag && Drop Events"

CheckBoxMouseDragOver.AutoSize = True
CheckBoxMouseDragOver.Location = New Point(44, 159)
CheckBoxMouseDragOver.Size = New Size(142, 17)
CheckBoxMouseDragOver.TabIndex = 10
CheckBoxMouseDragOver.Text = "Mouse Drag Over Events"

CheckBoxKeyboard.AutoSize = True
CheckBoxKeyboard.Location = New Point(8, 184)
CheckBoxKeyboard.Size = New Size(103, 17)
CheckBoxKeyboard.TabIndex = 11
CheckBoxKeyboard.Text = "Keyboard Events"

CheckBoxKeyUpDown.AutoSize = True
CheckBoxKeyUpDown.Location = New Point(26, 207)
CheckBoxKeyUpDown.Margin = New Padding(3, 3, 3, 1)
CheckBoxKeyUpDown.Size = New Size(133, 17)
CheckBoxKeyUpDown.TabIndex = 12
CheckBoxKeyUpDown.Text = "Key Up && Down Events"

CheckBoxFocus.AutoSize = True
CheckBoxFocus.Location = New Point(8, 233)
CheckBoxFocus.Margin = New Padding(3, 2, 3, 3)
CheckBoxFocus.Size = New Size(146, 17)
CheckBoxFocus.TabIndex = 13
CheckBoxFocus.Text = "Focus && Activation Events"

CheckBoxValidation.AutoSize = True
CheckBoxValidation.Location = New Point(8, 257)
CheckBoxValidation.Size = New Size(104, 17)
CheckBoxValidation.TabIndex = 14
CheckBoxValidation.Text = "Validation Events"
CheckBoxValidation.Text = "Validation Events"

TextBoxOutput.Location = New Point(232, 34)


TextBoxOutput.Size = New Size(308, 510)
TextBoxOutput.Multiline = True
TextBoxOutput.CausesValidation = False
TextBoxOutput.ReadOnly = True
TextBoxOutput.ScrollBars = ScrollBars.Vertical
TextBoxOutput.TabIndex = 15
TextBoxOutput.WordWrap = False

ButtonClear.Location = New Point(232, 560)


ButtonClear.Size = New Size(308, 23)
ButtonClear.TabIndex = 16
ButtonClear.Text = "Clear Event List"

Me.ClientSize = New Size(552, 595)


Me.Controls.Add(LinkLabelDrag)
Me.Controls.Add(ButtonClear)
Me.Controls.Add(GroupBoxEvents)
Me.Controls.Add(Label1)
Me.Controls.Add(Label2)
Me.Controls.Add(TextBoxInput)
Me.Controls.Add(TextBoxOutput)
Me.Text = "User Input Events"

Me.GroupBoxEvents.ResumeLayout(False)
Me.GroupBoxEvents.PerformLayout()
Me.ResumeLayout(False)
Me.PerformLayout()
CheckAllChildCheckBoxes(Me, True)
End Sub

' Recursively search the form for all contained checkboxes and
' initially check them
Private Sub CheckAllChildCheckBoxes(ByRef parent As Control, _
ByVal value As Boolean)

Dim currentControl As Control


Dim box As CheckBox
For Each currentControl In parent.Controls
box = TryCast(currentControl, CheckBox)
If box IsNot Nothing Then
box.Checked = value
End If

'Recurse if control contains other controls


If currentControl.Controls.Count > 0 Then
CheckAllChildCheckBoxes(currentControl, value)
End If
Next
End Sub

' All-purpose method for displaying a line of text in one of the


' text boxes.
Private Sub DisplayLine(ByRef line As String)

TextBoxOutput.AppendText(line)
TextBoxOutput.AppendText(ControlChars.NewLine)
End Sub

' Click event handler for the button that clears the text box.
Private Sub ButtonClear_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles ButtonClear.Click

TextBoxOutput.Invalidate()
TextBoxOutput.Clear()
End Sub

Private Sub TextBoxInput_KeyDown(ByVal sender As Object, _


Private Sub TextBoxInput_KeyDown(ByVal sender As Object, _
ByVal e As KeyEventArgs) Handles TextBoxInput.KeyDown

If CheckBoxKeyUpDown.Checked = True Then


DisplayLine("KeyDown: " + e.KeyData.ToString())
End If
End Sub

Private Sub TextBoxInput_KeyUp(ByVal sender As Object, _


ByVal e As KeyEventArgs) Handles TextBoxInput.KeyUp

If CheckBoxKeyUpDown.Checked = True Then


DisplayLine("KeyUp: " + e.KeyData.ToString())
End If
End Sub

Private Sub TextBoxInput_KeyPress(ByVal sender As Object, _


ByVal e As KeyPressEventArgs) Handles TextBoxInput.KeyPress

If CheckBoxKeyboard.Checked = True Then

If Char.IsWhiteSpace(e.KeyChar) Then
Dim keyVal As Integer
keyVal = AscW(e.KeyChar)
DisplayLine("KeyPress: WS-" + keyVal.ToString())
Else
DisplayLine("KeyPress: " + e.KeyChar.ToString())
End If
End If
End Sub

Private Sub TextBoxInput_Click(ByVal sender As Object, _


ByVal e As EventArgs) Handles TextBoxInput.Click

If CheckBoxMouse.Checked = True Then


DisplayLine("Click event")
End If
End Sub

Private Sub TextBoxInput_DoubleClick(ByVal sender As Object, _


ByVal e As EventArgs) Handles TextBoxInput.DoubleClick

If CheckBoxMouse.Checked = True Then


DisplayLine("DoubleClick event")
End If
End Sub

Private Sub TextBoxInput_MouseClick(ByVal sender As Object, _


ByVal e As MouseEventArgs) Handles TextBoxInput.MouseClick

If CheckBoxMouse.Checked = True Then


DisplayLine("MouseClick: " + e.Button.ToString() + _
" " + e.Location.ToString())
End If
End Sub

Private Sub TextBoxInput_MouseDoubleClick(ByVal sender As Object, _


ByVal e As MouseEventArgs) Handles TextBoxInput.MouseDoubleClick

If CheckBoxMouse.Checked = True Then


DisplayLine("MouseDoubleClick: " + e.Button.ToString() + _
" " + e.Location.ToString())
End If
End Sub

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


ByVal e As MouseEventArgs) Handles TextBoxInput.MouseDown

If CheckBoxMouse.Checked = True Then


DisplayLine("MouseDown: " + e.Button.ToString() + _
" " + e.Location.ToString())
End If
End Sub

Private Sub TextBoxInput_MouseUp(ByVal sender As Object, _


ByVal e As MouseEventArgs) Handles TextBoxInput.MouseUp

If CheckBoxMouse.Checked = True Then


DisplayLine("MouseUp: " + e.Button.ToString() + _
" " + e.Location.ToString())
End If

' The TextBox control was designed to change focus only on


' the primary click, so force focus to avoid user confusion.
If TextBoxInput.Focused = False Then
TextBoxInput.Focus()
End If
End Sub

Private Sub TextBoxInput_MouseEnter(ByVal sender As Object, _


ByVal e As EventArgs) Handles TextBoxInput.MouseEnter

If CheckBoxMouseEnter.Checked = True Then


DisplayLine("MouseEnter event")
End If
End Sub

Private Sub TextBoxInput_MouseHover(ByVal sender As Object, _


ByVal e As EventArgs) Handles TextBoxInput.MouseHover

If CheckBoxMouseEnter.Checked = True Then


DisplayLine("MouseHover event")
End If
End Sub

Private Sub TextBoxInput_MouseLeave(ByVal sender As Object, _


ByVal e As EventArgs) Handles TextBoxInput.MouseLeave

If CheckBoxMouseEnter.Checked = True Then


DisplayLine("MouseLeave event")
End If
End Sub

Private Sub TextBoxInput_MouseWheel(ByVal sender As Object, _


ByVal e As MouseEventArgs) Handles TextBoxInput.MouseWheel

If CheckBoxMouse.Checked = True Then


DisplayLine("MouseWheel: " + e.Delta.ToString() + _
" detents at " + e.Location.ToString())
End If
End Sub

Private Sub TextBoxInput_MouseMove(ByVal sender As Object, _


ByVal e As MouseEventArgs) Handles TextBoxInput.MouseMove

If CheckBoxMouseMove.Checked = True Then


DisplayLine("MouseMove: " + e.Button.ToString() + " " + _
e.Location.ToString())
End If

If CheckBoxMousePoints.Checked = True Then


Dim g As Graphics = TextBoxInput.CreateGraphics()
g.FillRectangle(Brushes.Black, e.Location.X, _
e.Location.Y, 1, 1)
g.Dispose()
End If
End Sub
Private Sub TextBoxInput_MouseCaptureChanged( _
ByVal sender As Object, ByVal e As EventArgs) _
Handles TextBoxInput.MouseCaptureChanged

If CheckBoxMouseDrag.Checked = True Then


DisplayLine("MouseCaptureChanged event")
End If
End Sub

Private Sub TextBoxInput_DragEnter(ByVal sender As Object, _


ByVal e As DragEventArgs) Handles TextBoxInput.DragEnter

Dim pt As Point
If CheckBoxMouseDrag.Checked = True Then
pt = New Point(e.X, e.Y)
DisplayLine("DragEnter: " + _
CovertKeyStateToString(e.KeyState) _
+ " at " + pt.ToString())
End If
End Sub

Private Sub TextBoxInput_DragDrop(ByVal sender As Object, _


ByVal e As DragEventArgs) Handles TextBoxInput.DragDrop

If CheckBoxMouseDrag.Checked = True Then


Dim pt As Point
pt = New Point(e.X, e.Y)

DisplayLine("DragDrop: " + _
CovertKeyStateToString(e.KeyState) _
+ " at " + pt.ToString())
End If
End Sub

Private Sub TextBoxInput_DragOver(ByVal sender As Object, _


ByVal e As DragEventArgs) Handles TextBoxInput.DragOver

If CheckBoxMouseDragOver.Checked = True Then


Dim pt As Point
pt = New Point(e.X, e.Y)
DisplayLine("DragOver: " + _
CovertKeyStateToString(e.KeyState) _
+ " at " + pt.ToString())
End If

' Allow if drop data is of type string.


If Not (e.Data.GetDataPresent(GetType(String))) Then
e.Effect = DragDropEffects.None
Else
e.Effect = DragDropEffects.Copy
End If
End Sub

Private Sub TextBoxInput_DragLeave(ByVal sender As Object, _


ByVal e As EventArgs) Handles TextBoxInput.DragLeave

If CheckBoxMouseDrag.Checked = True Then


DisplayLine("DragLeave event")
End If
End Sub

Private Function CovertKeyStateToString(ByVal keyState As Integer) _


As String

Dim keyString As String = "None"

' Which button was pressed?


If ((keyState And 1) = 1) Then
keyString = "Left"
keyString = "Left"
ElseIf ((keyState And 2) = 2) Then
keyString = "Right"
ElseIf ((keyState And 16) = 16) Then
keyString = "Middle"
End If

' Are one or more modifier keys also pressed?


If ((keyState And 4) = 4) Then
keyString += "+SHIFT"
End If
If ((keyState And 8) = 8) Then
keyString += "+CTRL"
End If
If ((keyState And 32) = 32) Then
keyString += "+ALT"
End If

Return keyString
End Function

Private Sub TextBoxInput_Enter(ByVal sender As Object, _


ByVal e As EventArgs) Handles TextBoxInput.Enter

If CheckBoxFocus.Checked = True Then


DisplayLine("Enter event")
End If
End Sub

Private Sub TextBoxInput_Leave(ByVal sender As Object, _


ByVal e As EventArgs) Handles TextBoxInput.Leave

If CheckBoxFocus.Checked = True Then


DisplayLine("Leave event")
End If
End Sub

Private Sub TextBoxInput_GotFocus(ByVal sender As Object, _


ByVal e As EventArgs) Handles TextBoxInput.GotFocus

If CheckBoxFocus.Checked = True Then


DisplayLine("GotFocus event")
End If
End Sub

Private Sub TextBoxInput_LostFocus(ByVal sender As Object, _


ByVal e As EventArgs) Handles TextBoxInput.LostFocus

If CheckBoxFocus.Checked = True Then


DisplayLine("LostFocus event")
End If
End Sub

Private Sub TextBoxInput_Validated(ByVal sender As Object, _


ByVal e As EventArgs) Handles TextBoxInput.Validated

If CheckBoxValidation.Checked = True Then


DisplayLine("Validated event")
End If
End Sub

Private Sub TextBoxInput_Validating(ByVal sender As Object, _


ByVal e As CancelEventArgs) _
Handles TextBoxInput.Validating

If CheckBoxValidation.Checked = True Then


DisplayLine("Validating event")
End If
End Sub
Private Sub CheckBoxToggleAll_CheckedChanged( _
ByVal sender As Object, ByVal e As EventArgs) _
Handles CheckBoxToggleAll.CheckedChanged

Dim cb As CheckBox
cb = TryCast(sender, CheckBox)
If cb IsNot Nothing Then
CheckAllChildCheckBoxes(Me, cb.Checked)
End If
End Sub

Private Sub CheckBoxMouse_CheckedChanged( _


ByVal sender As Object, ByVal e As EventArgs) _
Handles CheckBoxMouse.CheckedChanged

ConfigureCheckBoxSettings()
End Sub

Private Sub CheckBoxMouseDrag_CheckedChanged( _


ByVal sender As Object, ByVal e As EventArgs) _
Handles CheckBoxMouseDrag.CheckedChanged

ConfigureCheckBoxSettings()
End Sub

Private Sub CheckBoxKeyboard_CheckedChanged( _


ByVal sender As Object, ByVal e As EventArgs) _
Handles CheckBoxKeyboard.CheckedChanged

ConfigureCheckBoxSettings()
End Sub

Private Sub CheckBoxMouseMove_CheckedChanged( _


ByVal sender As Object, ByVal e As EventArgs) _
Handles CheckBoxMouseEnter.CheckedChanged, _
CheckBoxMouseMove.CheckedChanged

ConfigureCheckBoxSettings()
End Sub

' Reconcile dependencies between the check box


' selection choices.
Private Sub ConfigureCheckBoxSettings()

' CheckBoxMouse is a top-level check box.


If CheckBoxMouse.Checked = False Then
CheckBoxMouseEnter.Enabled = False
CheckBoxMouseMove.Enabled = False
CheckBoxMouseDrag.Enabled = False
CheckBoxMouseDragOver.Enabled = False
CheckBoxMousePoints.Enabled = False
Else
CheckBoxMouseEnter.Enabled = True
CheckBoxMouseMove.Enabled = True
CheckBoxMouseDrag.Enabled = True
CheckBoxMousePoints.Enabled = True

' Enable children depending on the state of the parent.


If CheckBoxMouseDrag.Checked = False Then
CheckBoxMouseDragOver.Enabled = False
Else
CheckBoxMouseDragOver.Enabled = True
End If
End If

If CheckBoxKeyboard.Checked = False Then


CheckBoxKeyUpDown.Enabled = False
Else
CheckBoxKeyUpDown.Enabled = True
CheckBoxKeyUpDown.Enabled = True
End If
End Sub

Private Sub LinkLabelDrag_MouseDown(ByVal sender As Object, _


ByVal e As MouseEventArgs) Handles LinkLabelDrag.MouseDown

Dim data As String = "Sample Data"


LinkLabelDrag.DoDragDrop(data, DragDropEffects.All)
End Sub

Private Sub LinkLabelDrag_GiveFeedback(ByVal sender As Object, _


ByVal e As GiveFeedbackEventArgs) _
Handles LinkLabelDrag.GiveFeedback

If ((e.Effect And DragDropEffects.Copy) = _


DragDropEffects.Copy) Then
LinkLabelDrag.Cursor = Cursors.HSplit
Else
LinkLabelDrag.Cursor = Cursors.Default
End If
End Sub

End Class
End Namespace

Compilando o Código
Este exemplo requer:
Referências aos assemblies System, System.Drawing e System.Windows.Forms.

Consulte também
Entrada do usuário no Windows Forms
Validação da entrada do usuário no Windows Forms
24/04/2020 • 13 minutes to read • Edit Online

Quando os usuários inserem dados em seu aplicativo, convém verificar se os dados são válidos antes de seu
aplicativo utilizá-los. Você pode exigir que determinados campos de texto não sejam de comprimento zero, que um
campo seja formatado como um número de telefone ou outros tipos de dados bem formados ou que uma cadeia
de caracteres não contenha caracteres desprotegidos que poderiam ser usados para comprometer a segurança de
um banco de dados. O Windows Forms fornece várias maneiras para validar a entrada em seu aplicativo.

Validação com o controle MaskedTextBox


Se você precisar exigir que os usuários insiram dados em um formato bem definido, como um número de
MaskedTextBox telefone ou um número de peça, você pode conseguir isso rapidamente e com código mínimo
usando o controle. Uma máscara é uma cadeia de caracteres composta de caracteres de uma linguagem de
mascaramento que especifica quais caracteres podem ser inseridos em qualquer posição determinada de uma
caixa de texto. O controle exibe um conjunto de avisos para o usuário. Se o usuário digita uma entrada incorreta,
como digitar uma letra quando é necessário um dígito, o controle rejeitará automaticamente a entrada.
A linguagem de mascaramento MaskedTextBox que é usada por é muito flexível. Ela permite que você especifique
os caracteres exigidos, caracteres opcionais, caracteres literais como hifens e parênteses, caracteres de moeda e
separadores de data. O controle também funciona bem quando associado a uma fonte de dados. O Format evento
em uma vinculação de dados pode ser usado para Parse reformatar os dados de entrada para cumprir com a
máscara, e o evento pode ser usado para reformatar dados de saída para cumprir as especificações do campo de
dados.
Para obter mais informações, consulte Controle MaskedTextBox.

Validação controlada por evento


Se você deseja ter controle total programático sobre a validação ou precisa realizar validações complexas, é
necessário usar os eventos de validação incorporados à maioria dos controles dos Windows Forms. Cada controle
que aceita entrada de Validating usuário de forma livre tem um evento que ocorrerá sempre que o controle exigir
validação de dados. No Validating método de manipulação de eventos, você pode validar a entrada do usuário de
várias maneiras. Por exemplo, se você tiver uma caixa de texto que deve conter um código postal, poderá realizar a
validação das seguintes maneiras:
Se o código postal deve pertencer a um grupo específico de códigos postais, você pode realizar uma
comparação de cadeia de caracteres na entrada para validar os dados inseridos pelo usuário. Por exemplo,
se o código postal deve estar no conjunto {10001, 10002, 10003}, você pode usar uma comparação de
cadeia de caracteres para validar os dados.
Se o código postal deve estar em uma forma específica, você pode usar expressões regulares para validar os
dados inseridos pelo usuário. Por exemplo, para validar a forma ##### ou #####-#### , você pode usar a
expressão regular ^(\d{5})(-\d{4})?$ . Para validar a forma A#A #A# , você pode usar a expressão regular
[A-Z]\d[A-Z] \d[A-Z]\d . Para obter mais informações sobre expressões regulares, consulte Expressões
regulares do .NET Framework e Exemplos de expressão regular.
Se o código postal deve ser um CEP válido dos Estados Unidos, você poderia chamar um serviço Web de
código postal para validar os dados inseridos pelo usuário.
O Validating evento é fornecido CancelEventArgscomo um objeto de tipo. Se você determinar que os dados do
controle não Validating são válidos, Cancel você true pode cancelar o evento definindo a propriedade deste objeto
como . Se você não Cancel definir a propriedade, o Windows Forms assumirá que Validated a validação foi bem
sucedida para esse controle e aumentará o evento.
Para um exemplo de código que TextBoxvalida Validatingum endereço de e-mail em um , veja .
Vinculação de dados e validação controlada por evento
A validação é muito útil quando você tiver associado seus controles a uma fonte de dados, como uma tabela de
banco de dados. Ao usar a validação, você pode verificar se os dados do seu controle satisfazem o formato exigido
pela fonte de dados e, se eles não contêm caracteres especiais, como aspas e barras invertidas, que podem não ser
seguros.
Quando você usa vinculação de dados, os dados em seu Validating controle são sincronizados com a fonte de
dados durante a execução do evento. Se você Validating cancelar o evento, os dados não serão sincronizados com
a fonte de dados.

IMPORTANT
Se você tiver validação personalizada Validating que ocorra após o evento, ela não afetará a vinculação de dados. Por
exemplo, se você Validated tiver código em um caso que tente cancelar a vinculação de dados, a vinculação de dados ainda
ocorrerá. Neste caso, para realizar Validated a validação no evento, altere a propriedade do Modo de Atualização de Fonte
de Dados do controle (em (Databindings) \ (Avançado) ) de OnValidation para Never , e adicione Control
.DataBindings[" <YOURFIELD> "].WriteValue() ao seu código de validação.

Validação explícita e implícita


Então quando os dados de um controle são validados? Isso cabe a você, o desenvolvedor. Você pode usar a
validação implícita ou explícita, dependendo das necessidades do seu aplicativo.
Validação implícita
A abordagem de validação implícita valida os dados enquanto o usuário os digita. Você pode validar os dados
conforme eles são inseridos em um controle através da leitura das teclas enquanto elas são pressionadas ou, mais
comumente, sempre que o usuário retirar o foco de entrada de um controle e movê-lo para o próximo. Essa
abordagem é útil quando você deseja fornecer comentários imediatos sobre os dados, enquanto os usuários
trabalham.
Se você quiser usar validação implícita para um controle, AutoValidate você EnablePreventFocusChange
EnableAllowFocusChangedeve definir a propriedade desse controle para ou . Se você Validating cancelar o evento,
o comportamento do controle será determinado AutoValidatepelo valor a que você atribuiu . Se você
EnablePreventFocusChangeatribuiu, cancelar o Validated evento fará com que o evento não ocorra. O foco de
entrada permanecerá no controle atual até que o usuário altere os dados para uma entrada válida. Se você
EnableAllowFocusChangeatribuído, Validated o evento não ocorrerá quando você cancelar o evento, mas o foco
ainda mudará para o próximo controle.
Atribuir Disable à AutoValidate propriedade impede completamente a validação implícita. Para validar seus
controles, você precisará usar a validação explícita.
Validação explícita
A abordagem de validação explícita valida os dados de uma só vez. Você pode validar os dados em resposta a uma
ação do usuário, como clicar em um botão Salvar ou um link Avançar. Quando a ação do usuário ocorre, você pode
disparar a validação explícita de uma das seguintes maneiras:
Ligue Validate para validar o último controle que perdeu o foco.
Chamada ValidateChildren para validar todos os controles de crianças em um formulário ou controle de
contêiner.
Chamar um método personalizado para validar manualmente os dados nos controles.
Comportamento de validação implícita padrão de controles dos Windows Forms
Diferentes controles do Windows Forms AutoValidate têm padrões diferentes para sua propriedade. A tabela a
seguir mostra os controles mais comuns e seus valores padrão.

C O N T RO L C O M P O RTA M EN TO DE VA L IDA Ç Ã O PA DRÃ O

ContainerControl Inherit

Form EnableAllowFocusChange

PropertyGrid Propriedade não exposta no Visual Studio

ToolStripContainer Propriedade não exposta no Visual Studio

SplitContainer Inherit

UserControl EnableAllowFocusChange

Fechar o formulário e substituir a validação


Quando um controle mantém o foco porque os dados que ele contém são inválidos, é impossível fechar o
formulário pai através das maneiras comuns:
Clicando no botão Fechar .
Selecionando Fechar no menu Sistema .
Chamando Close o método de programática.
No entanto, em alguns casos, você talvez queira permitir que o usuário feche o formulário independentemente se
os valores nos controles são válidos. Você pode substituir a validação e fechar um formulário que ainda contém
FormClosing dados inválidos criando um manipulador para o evento do formulário. No caso, defina Cancel false
a propriedade para . Isso força o formulário a fechar. Para obter mais informações e um exemplo, consulte
Form.FormClosing.

NOTE
Se você forçar o formulário a fechar desta maneira, todos os dados nos controles do formulário que ainda não tiverem sido
salvos serão perdidos. Além disso, os formulários modais não validam o conteúdo dos controles quando eles são fechados.
Você ainda pode usar a validação de controle para bloquear o foco em um controle, mas você não precisa se preocupar com
o comportamento associado ao fechamento do formulário.

Confira também
Control.Validating
Form.FormClosing
System.Windows.Forms.FormClosingEventArgs
Controle MaskedTextBox
Exemplos de expressões regulares
Caixas de diálogo no Windows Forms
29/01/2020 • 2 minutes to read • Edit Online

Caixas de diálogo são usadas para interagir com o usuário e recuperar informações. Em termos simples, uma caixa
de diálogo é um formulário com sua propriedade de enumeração FormBorderStyle definida como FixedDialog .
Você pode construir suas próprias caixas de diálogo personalizadas usando o Designer de Formulários do
Windows no Visual Studio. Adicione controles como Label , Textbox e Button para personalizar caixas de diálogo
conforme suas necessidades específicas. O .NET Framework também inclui caixas de diálogo predefinidas, como
caixas de mensagem e aber tura de arquivo , que você pode adaptar para seus próprios aplicativos. Para obter
mais informações, confira Controles e componentes da caixa de diálogo.

Nesta seção
Como exibir caixas de diálogo para o Windows Forms
Fornece instruções para mostrar caixas de diálogo.

Seções Relacionadas
Controles e componentes da caixa de diálogo
Lista os controles da caixa de diálogo predefinida.
Alterando a aparência dos Windows Forms
Contém links para tópicos que descrevem como alterar a aparência de aplicativos dos Windows Forms.
Visão geral do controle TabControl
Explica como incorporar o controle guia em uma caixa de diálogo.
Como exibir caixas de diálogo para o Windows
Forms
20/03/2020 • 2 minutes to read • Edit Online

Você exibe uma caixa de diálogo da mesma forma que exibe qualquer outro formulário em um aplicativo. O
formulário de inicialização é carregado automaticamente quando o aplicativo é executado. Para fazer aparecer um
segundo formulário ou caixa de diálogo no aplicativo, escreva código para carregá-lo e exibi-lo. Da mesma forma,
para fazer o formulário ou caixa de diálogo desaparecer, escreva código para descarregá-lo ou escondê-lo.
Para exibir uma caixa de diálogo
1. Navegue até o manipulador de eventos com o qual deseja abrir a caixa de diálogo. Isso pode acontecer
quando um comando de menu é selecionado, quando um botão é clicado ou quando qualquer outro evento
ocorre.
2. No manipulador de eventos, adicione código para abrir a caixa de diálogo. Neste exemplo, um evento de
clique de botão é usado para mostrar a caixa de diálogo:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles


Button1.Click
Dim dlg1 as new Form()
dlg1.ShowDialog()
End Sub

private void button1_Click(object sender, System.EventArgs e)


{
Form dlg1 = new Form();
dlg1.ShowDialog();
}

private:
void button1_Click(System::Object ^ sender,
System::EventArgs ^ e)
{
Form ^ dlg1 = gcnew Form();
dlg1->ShowDialog();
}
Associação de dados do Windows Forms
03/02/2020 • 3 minutes to read • Edit Online

A associação de dados no Windows Forms oferece os meios para exibir e realizar alterações nas informações de
uma fonte de dados em controles no formulário. É possível associar a fontes de dados tradicionais e a
praticamente qualquer estrutura que contém dados.

Nesta seção
Associação de dados e o Windows Forms
Fornece uma visão geral da associação de dados no Windows Forms.
Fontes de dados com suporte nos Windows Forms
Descreve as fontes de dados que podem ser usadas com o Windows Forms.
Interfaces relacionadas à vinculação de dados
Descreve várias das interfaces usadas com a associação de dados do Windows Forms.
Como navegar por dados no Windows Forms
Mostra como navegar por itens em uma fonte de dados.
Notificação de alteração na vinculação de dados dos Windows Forms
Descreve os diferentes tipos de notificação de alteração para associação de dados do Windows Forms.
Como implementar a interface INotifyPropertyChanged
Mostra como implementar a interface INotifyPropertyChanged. A interface se comunica com um controle
associado alterado pela propriedade em um objeto de negócios
Como aplicar o padrão PropertyNameChanged
Mostra como aplicar o padrão PropertyNameChanged nas propriedades de um controle de usuário do Windows
Forms.
Como implementar a interface ITypedList
Mostra como habilitar a descoberta do esquema para uma lista vinculável implementando a interface ITypedList.
Como implementar a interface IListSource
Mostra como implementar a interface IListSource para criar uma classe vinculável não implementa IList, mas
fornece uma lista de outro local.
Como assegurar que vários controles associados à mesma fonte de dados permaneçam sincronizados
Mostra como lidar com o evento BindingComplete para garantir que todos os controles vinculados a uma fonte
de dados permaneçam sincronizados.
Como garantir que a linha selecionada em uma tabela filho permaneça na posição correta
Mostra como garantir que a linha selecionada de uma tabela filho não seja alterada quando uma alteração for
feita em um campo da tabela pai.
Consulte também interfaces relacionadas à vinculação de dados, como navegar em dados em Windows Formse
como criar um controle de ligação simples em um Windows Form.

Referência
System.Windows.Forms.Binding
Descreve a classe que representa a associação entre um componente vinculável e uma fonte de dados.
System.Windows.Forms.BindingSource
Descreve a classe que encapsula uma fonte de dados para associação aos controles.

Seções Relacionadas
Componente BindingSource
Contém uma lista de tópicos que demonstram como usar o componente BindingSource.
Controle DataGridView
Fornece uma lista de tópicos que demonstram como usar um controle datagrid vinculável.
Consulte também acessando dados no Visual Studio.
Associação de dados e o Windows Forms
03/02/2020 • 8 minutes to read • Edit Online

No Windows Forms, você pode vincular não apenas a fontes de dados tradicionais, mas também a praticamente
qualquer estrutura que contenha dados. Você pode vincular a uma matriz de valores que você calcula no tempo
de execução, lê de um arquivo ou deriva dos valores de outros controles.
Além disso, você pode vincular qualquer propriedade de qualquer controle à fonte de dados. Na vinculação de
dados tradicional, você geralmente vincula a propriedade de exibição — por exemplo, a propriedade Text de um
controle TextBox — à fonte de dados. Com o .NET Framework, você também tem a opção de definir outras
propriedades por meio de associação também. É possível usar a vinculação para realizar as seguintes tarefas:
Definir o grafo de um controle de imagem.
Definir a cor do plano de fundo de um ou mais controles.
Definir o tamanho dos controles.
Basicamente, a vinculação de dados é uma maneira automática de configurar qualquer propriedade acessível do
tempo de execução de qualquer controle em um formulário.

Tipos de vinculação de dados


O Windows Forms pode tirar proveito de dois tipos de vinculação de dados: vinculação simples e vinculação
complexa. Cada uma oferece vantagens diferentes.

T IP O DE VIN C UL A Ç Ã O DE DA DO S DESC RIÇ Ã O

Vinculação de dados simples A capacidade de um controle em vincular a um elemento de


dados único, tal como um valor em uma coluna em uma
tabela do conjunto de dados. Esse é o tipo de vinculação
típica para controles, tais como um controle TextBox ou um
controle Label, que são controles que normalmente exibem
apenas um único valor. Na verdade, qualquer propriedade em
um controle pode ser vinculada a um campo em um banco de
dados. Há amplo suporte para esse recurso no Visual Studio.

Para obter mais informações, consulte:

Interfaces - relacionadas à associação de dados


- como navegar dados no Windows Forms
- como: criar um controle de associação simples em um
Windows Form

Vinculação de dados complexos A capacidade de um controle para vincular a mais de um


elemento de dados, geralmente mais de um registro em um
banco de dados. A vinculação complexa também é chamada
de vinculação baseada em lista. Exemplos de controles que
suportam vinculação complexa são os controles
DataGridView, ListBox e ComboBox. Para obter um exemplo
de vinculação de dados complexa, consulte como associar um
Windows Forms caixa de combinação ou controle ListBox aos
dados.
Componente BindingSource
Para simplificar a vinculação de dados, o Windows Forms permite que você vincule uma fonte de dados ao
componente BindingSource e, em seguida, vincule controles à BindingSource. Você pode usar a BindingSource em
cenários de vinculação simples ou complexos. Em ambos os casos, a BindingSource atua como intermediário
entre a fonte de dados e os controles de vinculação, fornecendo gerenciamento de moeda para notificação de
alteração e outros serviços.

Cenários comuns que utilizam a vinculação de dados


Praticamente todos os aplicativos comerciais usam leitura de informações de fontes de dados de um tipo ou de
outro, normalmente por meio da vinculação de dados. A lista a seguir mostra alguns dos cenários mais comuns
que utilizam a vinculação de dados, como o método de apresentação de dados e a manipulação.

C EN Á RIO DESC RIÇ Ã O

Reporting Os relatórios fornecem uma maneira flexível para exibir e


resumir dados em um documento impresso. É muito comum
criar um relatório que imprima o conteúdo selecionado de
uma fonte de dados na tela ou em uma impressora. Relatórios
comuns incluem listas, faturas e resumos. Os itens são
geralmente formatados em colunas de listas, com subitens
organizados em cada item da lista, mas você deve escolher o
layout que melhor atenda aos dados.

Entrada de dados É uma forma comum de inserir grandes quantidades de


dados relacionados ou de solicitar informações aos usuários
por meio de um formulário de entrada de dados. Os usuários
podem inserir informações ou selecionar opções usando
caixas de texto, botões de opção, listas suspensas e caixas de
seleção. As informações são então enviadas e armazenadas
em um banco de dados, cuja estrutura se baseia nas
informações inseridas.

Relação mestre/detalhes Um aplicativo mestre/detalhes é um formato para pesquisa


em dados relacionados. Especificamente, há duas tabelas de
dados com uma relação de conexão entre elas — no exemplo
de negócios clássico, uma tabela "Clientes" e uma tabela
"Pedidos" com uma relação entre elas vinculando clientes e
seus respectivos pedidos. Para obter mais informações sobre
como criar um aplicativo mestre/de detalhes com dois
Windows Forms DataGridView controles, consulte como: criar
um formulário mestre/detalhado usando dois controles
DataGridView Windows Forms
C EN Á RIO DESC RIÇ Ã O

Tabela de pesquisa Outro cenário comum de apresentação/manipulação de


dados é a pesquisa de tabela. Geralmente, como parte de
uma exibição de dados maior, um controle ComboBox é
usado para exibir e manipular os dados. A chave é que os
dados exibidos no controle ComboBox sejam diferentes dos
dados gravados no banco de dados. Por exemplo, se você
tiver um controle ComboBox exibindo os itens disponíveis em
uma mercearia, provavelmente gostaria de ver os nomes dos
produtos (pão, leite, ovos). No entanto, para facilitar a
recuperação de informações do banco de dados e para a
normalização do banco de dados, você provavelmente
armazenará as informações dos itens específicos em uma
determinada ordem como números de item (nº 501, nº 603 e
assim por diante). Assim, há uma conexão implícita entre o
"nome amigável" do item na mercearia no controle
ComboBox em seu formulário e o número do item
relacionado que está presente em um pedido. Essa é a
essência de uma pesquisa de tabela. Para obter mais
informações, consulte como: criar uma tabela de pesquisa
com o componente Windows Forms BindingSource.

Consulte também
Binding
Associação de dados do Windows Forms
Como associar o controle DataGrid dos Windows Forms a uma fonte de dados
Componente BindingSource
Fontes de dados com suporte do Windows Forms
03/02/2020 • 7 minutes to read • Edit Online

Tradicionalmente, a associação de dados era usada nos aplicativos para tirar proveito dos dados armazenados em
bancos de dados. Com a associação de dados do Windows Forms, você pode acessar dados de bancos de dados,
bem como dados em outras estruturas, como matrizes e coleções, desde que certos requisitos mínimos sejam
atendidos.

Estruturas às quais associar


No Windows Forms, é possível associar a uma grande variedade de estruturas, desde objetos simples (associação
simples) a listas complexas como tabelas de dados do ADO.NET (associação complexa). Para a associação simples,
o Windows Forms dá suporte à associação às propriedades públicas no objeto simples. Windows Forms
associação baseada em lista geralmente requer que o objeto dê suporte à interface IList ou à interface IListSource.
Além disso, se você estiver ligando com um componente BindingSource, você poderá associar a um objeto que dá
suporte à interface IEnumerable. Para obter mais informações sobre interfaces relacionadas à associação de dados,
consulte Interfaces relacionadas à associação de dados.
A lista a seguir mostra as estruturas a que você pode associar no Windows Forms.
BindingSource
Uma BindingSource é a fonte de dados Windows Forms mais comum e atua como um proxy entre uma fonte de
dados e os controles de Windows Forms. O padrão de uso geral de BindingSource é associar os controles ao
BindingSource e associar os BindingSource à fonte de dados (por exemplo, uma tabela de dados ADO.NET ou um
objeto comercial). O BindingSource fornece serviços que habilitam e melhoram o nível de suporte de vinculação
de dados. Por exemplo, Windows Forms controles baseados em lista, como o DataGridView e ComboBox, não dão
suporte diretamente à associação para IEnumerable fontes de dados no entanto, você pode habilitar esse cenário
ligando-se por meio de um BindingSource. Nesse caso, o BindingSource converterá a fonte de dados em um IList.
Objetos simples
Windows Forms dá suporte a propriedades de controle de ligação de dados para propriedades públicas na
instância de um objeto usando o tipo Binding. Windows Forms também dá suporte a controles baseados em lista
de associação, como um ListControl a uma instância de objeto quando um BindingSource é usado.
Matriz ou coleção
Para atuar como uma fonte de dados, uma lista deve implementar a interface IList; um exemplo seria uma matriz
que é uma instância da classe Array. Para obter mais informações sobre matrizes, consulte Como criar uma matriz
de objetos (Visual Basic).
Em geral, você deve usar BindingList<T> ao criar listas de objetos para associação de dados. BindingList<T> é
uma versão genérica da interface IBindingList. A interface IBindingList estende a interface IList adicionando
Propriedades, métodos e eventos necessários para a ligação de dados bidirecional.
IEnumerable
Windows Forms controles podem ser vinculados a fontes de dados que só dão suporte à interface IEnumerable se
estiverem ligados por um componente BindingSource.
Objetos de dados ADO.NET
O ADO.NET fornece várias estruturas de dados adequadas para a associação ao. Cada uma delas varia em termos
de sofisticação e complexidade.
DataColumn Uma DataColumn é o bloco de construção essencial de uma DataTable, pois várias colunas
compõem uma tabela. Cada DataColumn tem uma propriedade DataType que determina o tipo de dados
que a coluna contém (por exemplo, a marca de um automóvel em uma tabela que descreve carros). Você
pode associar simples um controle (como uma propriedade de Text do controle de TextBox) a uma coluna
em uma tabela de dados.
DataTable Uma DataTable é a representação de uma tabela, com linhas e colunas, em ADO.NET. Uma tabela
de dados contém duas coleções: DataColumn, representando as colunas de dados em uma determinada
tabela (que, por fim, determina os tipos de dados que podem ser inseridos nessa tabela) e DataRow,
representando as linhas de dados em uma determinada tabela. Você pode associar um controle de forma
complexa às informações contidas em uma tabela de dados (como associar o controle de DataGridView a
uma tabela de dados). No entanto, ao associar a um DataTable, você é realmente uma associação à exibição
padrão da tabela.
DataView Uma DataView é uma exibição personalizada de uma única tabela de dados que pode ser filtrada
ou classificada. Uma exibição de dados é o "instantâneo" dos dados usado por controles associados de
forma complexa. Você pode associar de forma simples ou complexa aos dados em uma exibição de dados,
mas lembre-se de que você está associando a uma "imagem" fixa dos dados em vez de uma fonte de dados
limpa e atualizada.
DataSet Uma DataSet é uma coleção de tabelas, relações e restrições dos dados em um banco de dado.
Você pode fazer uma associação simples ou uma associação complexa aos dados em um DataSet, mas
lembre-se de que você está ligando ao DataViewManager padrão para o DataSet (consulte o próximo ponto
de marcador).
DataViewManager Uma DataViewManager é uma exibição personalizada de todo o DataSet, análogo a uma
DataView, mas com as relações incluídas. Com uma coleção de DataViewSettings, você pode definir filtros
padrão e opções de classificação para quaisquer exibições que o DataViewManager tenha para uma
determinada tabela.

Consulte também
Notificação de alteração na vinculação de dados dos Windows Forms
Associação de dados e o Windows Forms
Associação de dados do Windows Forms
Interfaces relacionadas à associação de dados
23/11/2019 • 15 minutes to read • Edit Online

Com o ADO.NET, você pode criar várias estruturas de dados diferentes para atender às necessidades de
associação do seu aplicativo e aos dados com os quais você está trabalhando. Talvez você queira criar suas
próprias classes que forneçam ou consumam dados nos Windows Forms. Esses objetos podem oferecer vários
níveis de funcionalidade e complexidade, desde a vinculação de dados básica até o fornecimento de suporte em
tempo de design, verificação de erros, notificação de alterações ou até mesmo suporte para uma reversão
estruturada das alterações feitas nos próprios dados.

Consumidores de interfaces de associação de dados


As seções a seguir descrevem dois grupos de objetos de interface. O primeiro grupo lista as interfaces que são
implementadas nas fontes de dados por autores de fonte de dados. Essas interfaces são projetadas para serem
consumidas pelos consumidores de fonte de dados, que são, na maioria dos casos, controles ou componentes
dos Windows Forms. O segundo grupo lista as interfaces projetadas para serem usadas por autores de
componente. Os autores de componente usam essas interfaces quando estão criando um componente que dá
suporte à vinculação de dados a ser consumida pelo mecanismo de vinculação de dados dos Windows Forms.
Você pode implementar essas interfaces nas classes associadas ao seu formulário para habilitar a vinculação de
dados. Cada caso apresenta uma classe que implementa uma interface que habilita a interação com os dados. As
ferramentas de experiência de design de dados de desenvolvimento rápido de aplicativos (RAD) do Visual Studio
já aproveitam essa funcionalidade.
Interfaces para implementação por autores de fonte de dados
As seguintes interfaces são projetadas para serem consumidas por controles dos Windows Forms:
interface IList
Uma classe que implementa a interface IList pode ser uma Array, ArrayListou CollectionBase. Essas são
listas indexadas de itens do tipo Object. Essas listas devem conter tipos homogêneos, porque o primeiro
item do índice determina o tipo. IList estaria disponível para associação somente em tempo de execução.

NOTE
Se você quiser criar uma lista de objetos comerciais para associação com Windows Forms, considere usar o
BindingList<T>. O BindingList<T> é uma classe extensível que implementa as interfaces primárias necessárias para
a associação de dados de Windows Forms bidirecional.

interface IBindingList
Uma classe que implementa a interface IBindingList fornece um nível muito mais alto de funcionalidade de
vinculação de dados. Essa implementação oferece recursos básicos de classificação e notificação de
alteração para quando os itens da lista são alterados (por exemplo, o terceiro item em uma lista de clientes
tem uma alteração no campo de endereço), bem como quando a própria lista é alterada (por exemplo, o
número de itens na lista aumenta ou diminui). A notificação de alteração é importante se você planeja ter
vários controles associados aos mesmos dados e deseja que as alterações de dados feitas em um dos
controles sejam propagadas para os outros controles associados.
NOTE
A notificação de alteração está habilitada para a interface de IBindingList por meio da propriedade
SupportsChangeNotification, que, quando true , gera um evento de ListChanged, indicando que a lista foi
alterada ou um item na lista foi alterado.

O tipo de alteração é descrito pela propriedade ListChangedType do parâmetro ListChangedEventArgs.


Portanto, sempre que o modelo de dados for atualizado, quaisquer exibições dependentes, como outros
controles associados à mesma fonte de dados, também serão atualizadas. No entanto, os objetos contidos
na lista terão que notificar a lista quando forem alterados para que a lista possa gerar o evento
ListChanged.

NOTE
O BindingList<T> fornece uma implementação genérica da interface IBindingList.

interface IBindingListView
Uma classe que implementa a interface IBindingListView fornece toda a funcionalidade de uma
implementação de IBindingList, bem como a filtragem e a funcionalidade de classificação avançada. Essa
implementação oferece filtragem baseada em cadeia de caracteres e classificação de várias colunas com
pares de propriedade descritor-direção.
interface IEditableObject
Uma classe que implementa a interface IEditableObject permite que um objeto controle quando as
alterações feitas nesse objeto são permanentes. Essa implementação proporciona os métodos BeginEdit,
EndEdite CancelEdit, que permitem que você Reverta as alterações feitas no objeto. Veja a seguir uma
breve explicação do funcionamento dos métodos BeginEdit, EndEdite CancelEdit e como eles funcionam
em conjunto entre si para permitir uma possível reversão das alterações feitas nos dados:
O método BeginEdit sinaliza o início de uma edição em um objeto. Um objeto que implementa essa
interface precisará armazenar todas as atualizações após a chamada do método BeginEdit de forma
que as atualizações possam ser descartadas se o método CancelEdit for chamado. Na Windows
Forms de vinculação de dados, você pode chamar BeginEdit várias vezes dentro do escopo de uma
única transação de edição (por exemplo, BeginEdit, BeginEdit, EndEdit). As implementações de
IEditableObject devem controlar se BeginEdit já foi chamado e ignorar chamadas subsequentes
para BeginEdit. Como esse método pode ser chamado várias vezes, é importante que as chamadas
subsequentes a ele sejam não destrutivas; ou seja, as chamadas de BeginEdit subsequentes não
podem destruir as atualizações que foram feitas ou alterar os dados que foram salvos na primeira
chamada BeginEdit.
O método EndEdit envia todas as alterações desde que BeginEdit foi chamado no objeto subjacente,
se o objeto estiver em modo de edição no momento.
O método CancelEdit descarta as alterações feitas no objeto.
Para obter mais informações sobre como os métodos BeginEdit, EndEdite CancelEdit funcionam, consulte
salvar dados de volta no banco de dado.
Essa noção transacional de funcionalidade de dados é usada pelo controle de DataGridView.
interface ICancelAddNew
Uma classe que implementa a interface ICancelAddNew geralmente implementa a interface IBindingList e
permite que você Reverta uma adição feita à fonte de dados com o método AddNew. Se sua fonte de
dados implementar a interface IBindingList, você também deverá fazer com que ela implemente a
interface ICancelAddNew.
interface IDataErrorInfo
Uma classe que implementa a interface IDataErrorInfo permite que os objetos ofereçam informações de
erro personalizadas a controles associados:
A propriedade Error retorna texto de mensagem de erro geral (por exemplo, "ocorreu um erro").
A propriedade Item[String] retorna uma cadeia de caracteres com a mensagem de erro específica
da coluna (por exemplo, "o valor na coluna State é inválido").
interface IEnumerable
Uma classe que implementa a interface IEnumerable normalmente é consumida por ASP.NET. Windows
Forms suporte para essa interface só está disponível por meio do componente BindingSource.

NOTE
O componente BindingSource copia todos os itens de IEnumerable em uma lista separada para fins de associação.

interface ITypedList
Uma classe Collections que implementa a interface ITypedList fornece a capacidade de controlar a ordem e
o conjunto de propriedades expostas ao controle associado.

NOTE
Quando você implementar o método GetItemProperties e a matriz PropertyDescriptor não for nula, a última
entrada na matriz será o descritor de propriedade que descreve a Propriedade List que é outra lista de itens.

interface ICustomTypeDescriptor
Uma classe que implementa a interface ICustomTypeDescriptor fornece informações dinâmicas sobre si
mesma. Essa interface é semelhante a ITypedList, mas é usada para objetos em vez de listas. Essa interface
é usada pelo DataRowView para projetar o esquema das linhas subjacentes. Uma implementação simples
de ICustomTypeDescriptor é fornecida pela classe CustomTypeDescriptor.

NOTE
Para dar suporte à associação de tempo de design a tipos que implementam ICustomTypeDescriptor, o tipo
também deve implementar IComponent e existir como uma instância no formulário.

interface IListSource
Uma classe que implementa a interface IListSource habilita a associação baseada em lista em objetos que
não são de lista. O método GetList de IListSource é usado para retornar uma lista vinculável de um objeto
que não herda de IList. IListSource é usado pela classe DataSet.
interface IRaiseItemChangedEvents
Uma classe que implementa a interface IRaiseItemChangedEvents é uma lista vinculável que também
implementa a interface IBindingList. Essa interface é usada para indicar se o tipo gera ListChanged eventos
do tipo ItemChanged por meio de sua propriedade RaisesItemChangedEvents.
NOTE
Você deve implementar a IRaiseItemChangedEvents se sua fonte de dados fornecer a propriedade para listar a
conversão de eventos descrita anteriormente e estiver interagindo com o componente BindingSource. Caso
contrário, a BindingSource também executará a propriedade para listar a conversão de eventos, resultando em um
desempenho mais lento.

interface ISupportInitialize
Um componente que implementa a interface ISupportInitialize aproveita as vantagens das otimizações do
lote para definir propriedades e inicializar propriedades codependentes. O ISupportInitialize contém dois
métodos:
BeginInit sinaliza que a inicialização do objeto está iniciando.
EndInit sinaliza que a inicialização do objeto está sendo concluída.
interface ISupportInitializeNotification
Um componente que implementa a interface ISupportInitializeNotification também implementa a
interface ISupportInitialize. Essa interface permite que você notifique outros componentes do
ISupportInitialize que a inicialização foi concluída. A interface ISupportInitializeNotification contém dois
membros:
IsInitialized retorna um valor de boolean indicando se o componente é inicializado.
Initialized ocorre quando EndInit é chamado.
interface INotifyPropertyChanged
Uma classe que implementa essa interface é um tipo que aciona um evento quando qualquer um dos seus
valores de propriedade são alterados. Essa interface foi projetada para substituir o padrão de ter um
evento de alteração para cada propriedade de um controle. Quando usado em uma BindingList<T>, um
objeto comercial deve implementar a interface INotifyPropertyChanged e a BindingList`1 converterá
PropertyChanged eventos em eventos ListChanged do tipo ItemChanged.

NOTE
Para que a notificação de alteração ocorra em uma associação entre um cliente associado e uma fonte de dados, o
tipo de fonte de dados ligada deve implementar a interface de INotifyPropertyChanged (preferencial) ou você pode
fornecer eventos de Changed PropertyName para o tipo associado, mas você não deve fazer ambos.

Interfaces para implementação por autores de componentes


As seguintes interfaces são projetadas para consumo pelo mecanismo de associação de dados dos Windows
Forms:
interface IBindableComponent
Uma classe que implementa essa interface é um componente de não controle que dá suporte à vinculação
de dados. Essa classe retorna as associações de dados e o contexto de associação do componente por
meio das propriedades DataBindings e BindingContext desta interface.

NOTE
Se o componente herdar de Control, você não precisará implementar a interface IBindableComponent.
interface ICurrencyManagerProvider
Uma classe que implementa a interface ICurrencyManagerProvider é um componente que fornece seu
próprio CurrencyManager para gerenciar as associações associadas a esse componente específico. O
acesso ao CurrencyManager personalizado é fornecido pela propriedade CurrencyManager.

NOTE
Uma classe que herda de Control gerencia associações automaticamente por meio de sua propriedade
BindingContext, portanto, os casos em que você precisa implementar os ICurrencyManagerProvider são bastante
raros.

Consulte também
Associação de dados e o Windows Forms
Como criar um controle associado simples em um Windows Form
Vinculação de dados dos Windows Forms
Notificação de alteração na associação de dados do
Windows Forms
03/02/2020 • 5 minutes to read • Edit Online

Um dos conceitos mais importantes da Associação de dados de Windows Forms é a notificação de alteração. Para
garantir que a fonte de dados e os controles vinculados sempre tenham os dados mais recentes, você deve
adicionar a notificação de alteração para a vinculação de dados. Especificamente, você deseja garantir que os
controles associados sejam notificados sobre as alterações que foram feitas em sua fonte de dados, e a fonte de
dados é notificada sobre as alterações feitas nas propriedades associadas de um controle.
Há diferentes tipos de notificação de alteração, dependendo do tipo de associação de dados:
Associação simples, na qual uma única propriedade de controle está associada a uma única instância de um
objeto.
Associação baseada em lista, que pode incluir uma única propriedade de controle associada à propriedade
de um item em uma lista ou uma propriedade de controle associada a uma lista de objetos.
Além disso, se você estiver criando Windows Forms controles que deseja usar para vinculação de dados, deverá
aplicar o padrão de PropertyNamealterado aos controles, de modo que as alterações na propriedade bound de
um controle sejam propagadas para a fonte de dados.

Notificação de alteração para associação simples


Para associação simples, os objetos comerciais devem fornecer notificação de alteração quando o valor de uma
propriedade associada for alterado. Você pode fazer isso expondo um evento PropertyNamealterado para cada
propriedade do seu objeto comercial e associando o objeto de negócios a controles com o BindingSource ou o
método preferencial no qual seu objeto comercial implementa a interface INotifyPropertyChanged e gera um
evento PropertyChanged quando o valor de uma propriedade é alterado. Para obter mais informações, consulte
como implementar a interface INotifyPropertyChanged. Quando você usa objetos que implementam a interface
INotifyPropertyChanged, não é necessário usar o BindingSource para associar o objeto a um controle, mas é
recomendável usar o BindingSource.

Notificação de alteração para associação baseada em lista


Windows Forms depende de uma lista associada para fornecer alteração de propriedade (alterações de valor de
propriedade de item de lista) e lista alterada (um item é excluído ou adicionado à lista) informações aos controles
associados. Portanto, as listas usadas para a vinculação de dados devem implementar o IBindingList, que fornece
os dois tipos de notificação de alteração. O BindingList<T> é uma implementação genérica de IBindingList e é
projetado para uso com Windows Forms Associação de dados. Você pode criar um BindingList<T> que contém
um tipo de objeto comercial que implementa INotifyPropertyChanged e a lista converterá automaticamente os
eventos de PropertyChanged em eventos de ListChanged. Se a lista associada não for uma IBindingList, você
deverá associar a lista de objetos a Windows Forms controles usando o componente BindingSource. O
componente de BindingSource fornecerá uma conversão de propriedade a lista semelhante à do BindingList<T>.
Para obter mais informações, consulte como: gerar notificações de alteração usando uma BindingSource e a
interface INotifyPropertyChanged.

Alterar notificação para controles personalizados


Por fim, no lado do controle, você deve expor um evento PropertyNameChanged para cada propriedade criada
para ser associada aos dados. As alterações na propriedade de controle são propagadas para a fonte de dados
ligada. Para obter mais informações, consulte como aplicar o padrão PropertyNameChanged

Consulte também
BindingSource
INotifyPropertyChanged
BindingList<T>
Associação de dados do Windows Forms
Fontes de dados com suporte nos Windows Forms
Associação de dados e o Windows Forms
Como: aplicar o padrão PropertyNameChanged
23/10/2019 • 2 minutes to read • Edit Online

O exemplo de código a seguir demonstra como aplicar a PropertyNameChanged padrão para um controle
personalizado. Aplica esse padrão quando você implementa controles personalizados que são usados com o
mecanismo de associação de dados de formulários do Windows.

Exemplo
// This class implements a simple user control
// that demonstrates how to apply the propertyNameChanged pattern.
[ComplexBindingProperties("DataSource", "DataMember")]
public class CustomerControl : UserControl
{
private DataGridView dataGridView1;
private Label label1;
private DateTime lastUpdate = DateTime.Now;

public EventHandler DataSourceChanged;

public object DataSource


{
get
{
return this.dataGridView1.DataSource;
}
set
{
if (DataSource != value)
{
this.dataGridView1.DataSource = value;
OnDataSourceChanged();
}
}
}

public string DataMember


{
get { return this.dataGridView1.DataMember; }

set { this.dataGridView1.DataMember = value; }


}

private void OnDataSourceChanged()


{
if (DataSourceChanged != null)
{
DataSourceChanged(this, new EventArgs());
}
}

public CustomerControl()
{
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.label1 = new System.Windows.Forms.Label();
this.dataGridView1.ColumnHeadersHeightSizeMode =
System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.ImeMode = System.Windows.Forms.ImeMode.Disable;
this.dataGridView1.Location = new System.Drawing.Point(19, 55);
this.dataGridView1.Size = new System.Drawing.Size(350, 150);
this.dataGridView1.TabIndex = 1;
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(19, 23);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(76, 13);
this.label1.TabIndex = 2;
this.label1.Text = "Customer List:";
this.Controls.Add(this.label1);
this.Controls.Add(this.dataGridView1);
this.Size = new System.Drawing.Size(350, 216);
}
}
' This class implements a simple user control
' that demonstrates how to apply the propertyNameChanged pattern.
<ComplexBindingProperties("DataSource", "DataMember")> _
Public Class CustomerControl
Inherits UserControl
Private dataGridView1 As DataGridView
Private label1 As Label
Private lastUpdate As DateTime = DateTime.Now

Public DataSourceChanged As EventHandler

Public Property DataSource() As Object


Get
Return Me.dataGridView1.DataSource
End Get
Set
If DataSource IsNot Value Then
Me.dataGridView1.DataSource = Value
OnDataSourceChanged()
End If
End Set
End Property

Public Property DataMember() As String


Get
Return Me.dataGridView1.DataMember
End Get
Set
Me.dataGridView1.DataMember = value
End Set
End Property

Private Sub OnDataSourceChanged()


If (DataSourceChanged IsNot Nothing) Then
DataSourceChanged(Me, New EventArgs())
End If

End Sub

Public Sub New()


Me.dataGridView1 = New System.Windows.Forms.DataGridView()
Me.label1 = New System.Windows.Forms.Label()
Me.dataGridView1.ColumnHeadersHeightSizeMode = _
System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize
Me.dataGridView1.ImeMode = System.Windows.Forms.ImeMode.Disable
Me.dataGridView1.Location = New System.Drawing.Point(19, 55)
Me.dataGridView1.Size = New System.Drawing.Size(350, 150)
Me.dataGridView1.TabIndex = 1
Me.label1.AutoSize = True
Me.label1.Location = New System.Drawing.Point(19, 23)
Me.label1.Name = "label1"
Me.label1.Size = New System.Drawing.Size(76, 13)
Me.label1.TabIndex = 2
Me.label1.Text = "Customer List:"
Me.Controls.Add(Me.label1)
Me.Controls.Add(Me.dataGridView1)
Me.Size = New System.Drawing.Size(350, 216)
End Sub
End Class

Compilando o código
Para compilar o exemplo de código anterior:
Cole o código em um arquivo de código vazio. Você deve usar o controle personalizado em um formulário do
Windows que contenha um Main método.

Consulte também
Como: Implementar a Interface INotifyPropertyChanged
Notificação de alteração na vinculação de dados dos Windows Forms
Associação de dados do Windows Forms
Como: criar um controle associado e formatar os
dados exibidos
23/10/2019 • 4 minutes to read • Edit Online

Com a associação de dados do Windows Forms, você pode formatar os dados exibidos em um controle associado a
dados usando a caixa de diálogo Formatação e associação avançada .

Associar um controle e formatar os dados exibidos


1. Conecte-se a uma fonte de dados. Para obter mais informações, consulte Conectando a uma fonte de dados.
2. No Visual Studio, selecione o controle no formulário e, em seguida, abra a janela Propriedades .
3. Expanda a propriedade (DataBindings) e, em seguida, na caixa (avançado) , clique no botão na janela
Propriedades do Visual Studio) para exibir a formatação e avançado Caixa de diálogo de associação, que
tem uma lista completa de propriedades para esse controle.
4. Selecione a propriedade que você deseja associar e, em seguida, selecione a seta de vinculação .
Uma lista de fontes de dados disponíveis é exibida.
5. Expanda a fonte de dados a que deseja associar até encontrar o elemento de dados individual desejado.
Por exemplo, se você estiver associando a um valor de coluna na tabela do conjunto de dados, expanda o
nome do conjunto de dados e o nome da tabela para exibir os nomes das colunas.
6. Selecione o nome de um elemento ao qual associar.
7. Na caixa tipo de formato , selecione o formato que você deseja aplicar aos dados exibidos no controle.
Em todos os casos, você pode especificar o valor exibido no controle se a fonte de dados DBNullcontiver.
Caso contrário, as opções variam um pouco, dependendo do tipo de formato escolhido. A tabela a seguir
mostra os tipos e opções de formato.

T IP O DE F O RM ATO O P Ç Ã O DE F O RM ATA Ç Ã O

Sem Formatação Nenhuma opção.

Numeric Especifique o número de casas decimais usando o controle


superior/inferior Casas decimais .

Moeda Especifique o número de casas decimais usando o controle


superior/inferior Casas decimais .

Date Time Selecione como a data e a hora devem ser exibidas


selecionando um dos itens na caixa de seleção Tipo .

Científico Especifique o número de casas decimais usando o controle


superior/inferior Casas decimais .
T IP O DE F O RM ATO O P Ç Ã O DE F O RM ATA Ç Ã O

Personalizado Especifique uma cadeia de caracteres de formato


personalizada usando.

Para obter mais informações, consulte Tipos de


formatação. Obser vação: Cadeias de caracteres de
formato personalizado não têm garantia de ida e volta
com êxito entre a fonte de dados e o controle ligado. Em
vez disso Parse , Format manipule o evento ou para a
associação e aplique a formatação personalizada no código
de manipulação de eventos.

8. Selecione OK para fechar a caixa de diálogo formatação e Associação avançada e retornar para a janela
Propriedades.

Consulte também
Como: Criar um controle de associação simples em um formulário do Windows
Validação da entrada do usuário nos Windows Forms
Associação de dados do Windows Forms
Como: Criar um controle de associação simples em
um formulário do Windows
23/10/2019 • 2 minutes to read • Edit Online

Com a associação simples, é possível exibir um elemento de dados simples, como um valor de coluna de uma
tabela de dados em um controle. Você pode associar de maneira simples qualquer propriedade de um controle a
um valor de dados.

Para associar de maneira simples um controle


1. Conecte-se a uma fonte de dados. Para obter mais informações, consulte Conectando a uma fonte de
dados.
2. No Visual Studio, selecione o controle no formulário e exiba a janela Propriedades .
3. Expanda a propriedade (DataBindings) .
As propriedades geralmente mais associadas são exibidas sob a propriedade (DataBindings) . Por
exemplo, na maioria dos controles, a propriedade Text é vinculada com mais frequência.
4. Se a propriedade que você deseja associar não for uma das propriedades geralmente associadas, clique no
botão de reticências Studio.) na caixa (avançado) para exibir o Caixa de diálogo formatação e
Associação avançada com uma lista completa de propriedades para esse controle.
5. Selecione a propriedade que deseja associar e clique na seta suspensa em Associação .
Uma lista de fontes de dados disponíveis é exibida.
6. Expanda a fonte de dados a que deseja associar até encontrar o elemento de dados individual desejado.
Por exemplo, se você estiver associando a um valor de coluna na tabela do conjunto de dados, expanda o
nome do conjunto de dados e o nome da tabela para exibir os nomes das colunas.
7. Clique no nome de um elemento que receberá a associação.
8. Se você estiver trabalhando na caixa de diálogo Formatação e associação avançada , clique em OK
para voltar para a janela Propriedades .
9. Se deseja associar propriedades adicionais do controle, repita as etapas 3 a 7.

NOTE
Como controles de associação simples mostram apenas um elemento de dados, é muito comum incluir a lógica de
navegação em um Windows Form com controles de associação simples.

Consulte também
Binding
Associação de dados do Windows Forms
Vinculação de dados e os Windows Forms
Como: assegurar que vários controles associados à
mesma fonte de dados permaneçam sincronizados
23/10/2019 • 5 minutes to read • Edit Online

Muitas vezes, ao trabalhar com vinculação de dados nos Windows Forms, vários controles são associados à
mesma fonte de dados. Em alguns casos, pode ser necessário executar etapas adicionais para garantir que as
propriedades associadas dos controles permaneçam sincronizadas entre si e à fonte de dados. Essas etapas são
necessárias em duas situações:
Se a fonte de dados não implementa IBindingListe, portanto, gerar ListChanged eventos do tipo
ItemChanged.
Se a fonte de dados implementa IEditableObject.
No primeiro caso, você pode usar um BindingSource para associar a fonte de dados aos controles. No último caso,
você deve usar um BindingSource e lidar com o BindingComplete eventos e chame EndCurrentEdit em associado
BindingManagerBase.

Exemplo
O exemplo de código a seguir demonstra como associar três controles — dois controles de caixa de texto e um
DataGridView controle — para a mesma coluna em uma DataSet usando um BindingSource componente. Este
exemplo demonstra como lidar com o BindingComplete evento e certifique-se de que quando o valor de texto de
uma caixa de texto é alterado, a caixa de texto adicionais e o DataGridView controle são atualizados com o valor
correto.
O exemplo usa um BindingSource para associar a fonte de dados e os controles. Como alternativa, você pode
associar os controles diretamente à fonte de dados e recuperar o BindingManagerBase para a associação a partir
do formulário BindingContext e, em seguida, lidar com as BindingComplete evento para o BindingManagerBase.
Para obter um exemplo de como fazer isso, consulte a página de ajuda o BindingComplete eventos de
BindingManagerBase.

// Declare the controls to be used.


private BindingSource bindingSource1;
private TextBox textBox1;
private TextBox textBox2;
private DataGridView dataGridView1;

private void InitializeControlsAndDataSource()


{
// Initialize the controls and set location, size and
// other basic properties.
this.dataGridView1 = new DataGridView();
this.bindingSource1 = new BindingSource();
this.textBox1 = new TextBox();
this.textBox2 = new TextBox();
this.dataGridView1.ColumnHeadersHeightSizeMode =
DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Dock = DockStyle.Top;
this.dataGridView1.Location = new Point(0, 0);
this.dataGridView1.Size = new Size(292, 150);
this.textBox1.Location = new Point(132, 156);
this.textBox1.Size = new Size(100, 20);
this.textBox2.Location = new Point(12, 156);
this.textBox2.Size = new Size(100, 20);
this.ClientSize = new Size(292, 266);
this.Controls.Add(this.textBox2);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.dataGridView1);

// Declare the DataSet and add a table and column.


DataSet set1 = new DataSet();
set1.Tables.Add("Menu");
set1.Tables[0].Columns.Add("Beverages");

// Add some rows to the table.


set1.Tables[0].Rows.Add("coffee");
set1.Tables[0].Rows.Add("tea");
set1.Tables[0].Rows.Add("hot chocolate");
set1.Tables[0].Rows.Add("milk");
set1.Tables[0].Rows.Add("orange juice");

// Set the data source to the DataSet.


bindingSource1.DataSource = set1;

//Set the DataMember to the Menu table.


bindingSource1.DataMember = "Menu";

// Add the control data bindings.


dataGridView1.DataSource = bindingSource1;
textBox1.DataBindings.Add("Text", bindingSource1,
"Beverages", true, DataSourceUpdateMode.OnPropertyChanged);
textBox2.DataBindings.Add("Text", bindingSource1,
"Beverages", true, DataSourceUpdateMode.OnPropertyChanged);
bindingSource1.BindingComplete +=
new BindingCompleteEventHandler(bindingSource1_BindingComplete);
}

private void bindingSource1_BindingComplete(object sender, BindingCompleteEventArgs e)


{
// Check if the data source has been updated, and that no error has occurred.
if (e.BindingCompleteContext ==
BindingCompleteContext.DataSourceUpdate && e.Exception == null)

// If not, end the current edit.


e.Binding.BindingManagerBase.EndCurrentEdit();
}

' Declare the controls to be used.


Private WithEvents bindingSource1 As BindingSource
Private WithEvents textBox1 As TextBox
Private WithEvents textBox2 As TextBox
Private WithEvents dataGridView1 As DataGridView

Private Sub InitializeControlsAndDataSource()


' Initialize the controls and set location, size and
' other basic properties.
Me.dataGridView1 = New DataGridView()
Me.bindingSource1 = New BindingSource()
Me.textBox1 = New TextBox()
Me.textBox2 = New TextBox()
Me.dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize
Me.dataGridView1.Dock = DockStyle.Top
Me.dataGridView1.Location = New Point(0, 0)
Me.dataGridView1.Size = New Size(292, 150)
Me.textBox1.Location = New Point(132, 156)
Me.textBox1.Size = New Size(100, 20)
Me.textBox2.Location = New Point(12, 156)
Me.textBox2.Size = New Size(100, 20)
Me.ClientSize = New Size(292, 266)
Me.ClientSize = New Size(292, 266)
Me.Controls.Add(Me.textBox2)
Me.Controls.Add(Me.textBox1)
Me.Controls.Add(Me.dataGridView1)

' Declare the DataSet and add a table and column.


Dim set1 As New DataSet()
set1.Tables.Add("Menu")
set1.Tables(0).Columns.Add("Beverages")

' Add some rows to the table.


set1.Tables(0).Rows.Add("coffee")
set1.Tables(0).Rows.Add("tea")
set1.Tables(0).Rows.Add("hot chocolate")
set1.Tables(0).Rows.Add("milk")
set1.Tables(0).Rows.Add("orange juice")

' Set the data source to the DataSet.


bindingSource1.DataSource = set1

'Set the DataMember to the Menu table.


bindingSource1.DataMember = "Menu"

' Add the control data bindings.


dataGridView1.DataSource = bindingSource1
textBox1.DataBindings.Add("Text", bindingSource1, "Beverages", _
True, DataSourceUpdateMode.OnPropertyChanged)
textBox2.DataBindings.Add("Text", bindingSource1, "Beverages", _
True, DataSourceUpdateMode.OnPropertyChanged)

End Sub

Private Sub bindingSource1_BindingComplete(ByVal sender As Object, _


ByVal e As BindingCompleteEventArgs) Handles bindingSource1.BindingComplete

' Check if the data source has been updated, and that no error has occurred.
If e.BindingCompleteContext = BindingCompleteContext.DataSourceUpdate _
AndAlso e.Exception Is Nothing Then

' If not, end the current edit.


e.Binding.BindingManagerBase.EndCurrentEdit()
End If

End Sub

Compilando o código
Este exemplo de código requer
Referências para o System, System.Windows.Forms, e System.Drawing assemblies.
Um formulário com o Load evento como manipulado e uma chamada para o
InitializeControlsAndDataSource método no exemplo a partir do formulário Load manipulador de eventos.

Consulte também
Como: Compartilhar dados associados entre formulários usando o componente BindingSource
Notificação de alteração na vinculação de dados dos Windows Forms
Interfaces relacionadas à vinculação de dados
Associação de dados do Windows Forms
Como: assegurar que a linha selecionada em uma
tabela filho permaneça na posição correta
23/10/2019 • 14 minutes to read • Edit Online

Muitas vezes, ao trabalhar com a vinculação de dados nos Windows Forms, você exibirá dados no que é chamado
de modo de exibição pai/filho ou detalhes/mestre. Isso se refere a um cenário de associação de dados em que os
dados da mesma fonte são exibidos em dois controles. Alterar a seleção em um controle faz com que os dados
exibidos no segundo controle mudem. Por exemplo, o primeiro controle pode conter uma lista de clientes e o
segundo, uma lista de pedidos relacionada ao cliente selecionado no primeiro controle.
Iniciando com o .NET Framework versão 2.0, quando você exibe dados no modo de exibição pai/filho, pode ser
necessário executar etapas adicionais para que a linha selecionada atualmente na tabela filho não seja redefinida
para a primeira linha da tabela. Para fazer isso, será preciso armazenar em cache a posição da tabela filho e
redefini-la após a alteração da tabela pai. Normalmente, a redefinição do filho ocorre na primeira vez que um
campo em uma linha da tabela pai muda.
Para armazenar em cache a posição filho atual
1. Declare uma variável de inteiro para armazenar a posição de lista filho e uma variável booliana para indicar
se a posição filho deve ser armazenada em cache.

private int cachedPosition = -1;


private bool cacheChildPosition = true;

Private cachedPosition As Integer = - 1


Private cacheChildPosition As Boolean = True

2. Lidar com o ListChanged evento para a associação CurrencyManager e verifique se há um ListChangedType


de Reset.
3. Verifique a posição atual do CurrencyManager. Se for maior que a primeira entrada na lista (normalmente
0), salve-a em uma variável.

void relatedCM_ListChanged(object sender, ListChangedEventArgs e)


{
// Check to see if this is a caching situation.
if (cacheChildPosition && cachePositionCheckBox.Checked)
{
// If so, check to see if it is a reset situation, and the current
// position is greater than zero.
CurrencyManager relatedCM = sender as CurrencyManager;
if (e.ListChangedType == ListChangedType.Reset && relatedCM.Position > 0)

// If so, cache the position of the child table.


cachedPosition = relatedCM.Position;
}
}
Private Sub relatedCM_ListChanged(ByVal sender As Object, _
ByVal e As ListChangedEventArgs)
' Check to see if this is a caching situation.
If cacheChildPosition AndAlso cachePositionCheckBox.Checked Then
' If so, check to see if it is a reset situation, and the current
' position is greater than zero.
Dim relatedCM As CurrencyManager = sender
If e.ListChangedType = ListChangedType.Reset _
AndAlso relatedCM.Position > 0 Then

' If so, cache the position of the child table.


cachedPosition = relatedCM.Position
End If
End If

End Sub

4. Lidar com a lista de pai CurrentChanged evento para o Gerenciador de moeda pai. No manipulador, defina o
valor booliano para indicar que este não é um cenário de cache. Se o CurrentChanged ocorre, a alteração
para o pai é uma alteração de posição de lista e não uma alteração de valor do item.

void bindingSource1_CurrentChanged(object sender, EventArgs e)


{
// If the CurrentChanged event occurs, this is not a caching
// situation.
cacheChildPosition = false;
}

' Handle the current changed event. This event occurs when
' the current item is changed, but not when a field of the current
' item is changed.
Private Sub bindingSource1_CurrentChanged(ByVal sender As Object, _
ByVal e As EventArgs) Handles bindingSource1.CurrentChanged
' If the CurrentChanged event occurs, this is not a caching
' situation.
cacheChildPosition = False

End Sub

Para redefinir a posição filho


1. Lidar com o PositionChanged eventos para o filho da associação CurrencyManager.
2. Redefina a posição da tabela filho para a posição em cache salva no procedimento anterior.
void relatedCM_PositionChanged(object sender, EventArgs e)
{
// Check to see if this is a caching situation.
if (cacheChildPosition && cachePositionCheckBox.Checked)
{
CurrencyManager relatedCM = sender as CurrencyManager;

// If so, check to see if the current position is


// not equal to the cached position and the cached
// position is not out of bounds.
if (relatedCM.Position != cachedPosition && cachedPosition
> 0 && cachedPosition < relatedCM.Count)
{
relatedCM.Position = cachedPosition;
cachedPosition = -1;
}
}
}

Private Sub relatedCM_PositionChanged(ByVal sender As Object, ByVal e As EventArgs)


' Check to see if this is a caching situation.
If cacheChildPosition AndAlso cachePositionCheckBox.Checked Then
Dim relatedCM As CurrencyManager = sender

' If so, check to see if the current position is


' not equal to the cached position and the cached
' position is not out of bounds.
If relatedCM.Position <> cachedPosition AndAlso _
cachedPosition > 0 AndAlso cachedPosition < _
relatedCM.Count Then
relatedCM.Position = cachedPosition
cachedPosition = -1
End If
End If
End Sub

Exemplo
O exemplo a seguir demonstra como salvar a posição atual no CurrencyManagerpara uma tabela filho e redefinir a
posição após a conclusão de uma edição na tabela pai. Este exemplo contém dois DataGridView controles
associados a duas tabelas em um DataSet usando um BindingSource componente. É estabelecido um
relacionamento entre as duas tabelas e o relacionamento é adicionado para o DataSet. A posição na tabela filho
inicialmente é definida como a terceira linha para fins de demonstração.

using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace BT2
{
public class Form1 : Form
{
public Form1()
{
InitializeControlsAndDataSource();
}

// Declare the controls to be used.


private BindingSource bindingSource1;
private DataGridView dataGridView1;
private Button button1;
private DataGridView dataGridView2;
private CheckBox cachePositionCheckBox;
public DataSet set1;

private void InitializeControlsAndDataSource()


{
// Initialize the controls and set location, size and
// other basic properties.
this.dataGridView1 = new DataGridView();
this.bindingSource1 = new BindingSource();
this.button1 = new Button();
this.dataGridView2 = new DataGridView();
this.cachePositionCheckBox = new System.Windows.Forms.CheckBox();
this.dataGridView1.ColumnHeadersHeightSizeMode =
DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Dock = DockStyle.Top;
this.dataGridView1.Location = new Point(0, 20);
this.dataGridView1.Size = new Size(292, 170);
this.button1.Location = new System.Drawing.Point(18, 175);
this.button1.Size = new System.Drawing.Size(125, 23);

button1.Text = "Clear Parent Field";


this.button1.Click += new System.EventHandler(this.button1_Click);
this.dataGridView2.ColumnHeadersHeightSizeMode =
System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView2.Location = new System.Drawing.Point(0, 225);
this.dataGridView2.Size = new System.Drawing.Size(309, 130);
this.cachePositionCheckBox.AutoSize = true;
this.cachePositionCheckBox.Checked = true;
this.cachePositionCheckBox.Location = new System.Drawing.Point(150, 175);
this.cachePositionCheckBox.Name = "radioButton1";
this.cachePositionCheckBox.Size = new System.Drawing.Size(151, 17);
this.cachePositionCheckBox.Text = "Cache and restore position";
this.ClientSize = new System.Drawing.Size(325, 420);
this.Controls.Add(this.dataGridView1);
this.Controls.Add(this.cachePositionCheckBox);
this.Controls.Add(this.dataGridView2);
this.Controls.Add(this.button1);

// Initialize the data.


set1 = InitializeDataSet();

// Set the data source to the DataSet.


bindingSource1.DataSource = set1;

//Set the DataMember to the Menu table.


bindingSource1.DataMember = "Customers";

// Add the control data bindings.


dataGridView1.DataSource = bindingSource1;

// Set the data source and member for the second DataGridView.
dataGridView2.DataSource = bindingSource1;
dataGridView2.DataMember = "custOrders";

// Get the currency manager for the customer orders binding.


CurrencyManager relatedCM =
bindingSource1.GetRelatedCurrencyManager("custOrders");

// Set the position in the child table for demonstration purposes.


relatedCM.Position = 3;

// Handle the current changed event. This event occurs when


// the current item is changed, but not when a field of the current
// item is changed.
bindingSource1.CurrentChanged +=
new EventHandler(bindingSource1_CurrentChanged);
new EventHandler(bindingSource1_CurrentChanged);

// Handle the two events for caching and resetting the position.
relatedCM.ListChanged += new ListChangedEventHandler(relatedCM_ListChanged);
relatedCM.PositionChanged
+= new EventHandler(relatedCM_PositionChanged);

// Set cacheing to true in case current changed event


// occurred on set up.
cacheChildPosition = true;
}

// Establish the data set with two tables and a relationship


// between them.
private DataSet InitializeDataSet()
{
set1 = new DataSet();
// Declare the DataSet and add a table and column.
set1.Tables.Add("Customers");
set1.Tables[0].Columns.Add("CustomerID");
set1.Tables[0].Columns.Add("Customer Name");
set1.Tables[0].Columns.Add("Contact Name");

// Add some rows to the table.


set1.Tables["Customers"].Rows.Add("c1", "Fabrikam, Inc.", "Ellen Adams");
set1.Tables[0].Rows.Add("c2", "Lucerne Publishing", "Don Hall");
set1.Tables[0].Rows.Add("c3", "Northwind Traders", "Lori Penor");
set1.Tables[0].Rows.Add("c4", "Tailspin Toys", "Michael Patten");
set1.Tables[0].Rows.Add("c5", "Woodgrove Bank", "Jyothi Pai");

// Declare the DataSet and add a table and column.


set1.Tables.Add("Orders");
set1.Tables[1].Columns.Add("CustomerID");
set1.Tables[1].Columns.Add("OrderNo");
set1.Tables[1].Columns.Add("OrderDate");

// Add some rows to the table.


set1.Tables[1].Rows.Add("c1", "119", "10/04/2006");
set1.Tables[1].Rows.Add("c1", "149", "10/10/2006");
set1.Tables[1].Rows.Add("c1", "159", "10/12/2006");
set1.Tables[1].Rows.Add("c2", "169", "10/10/2006");
set1.Tables[1].Rows.Add("c2", "179", "10/10/2006");
set1.Tables[1].Rows.Add("c2", "189", "10/12/2006");
set1.Tables[1].Rows.Add("c3", "122", "10/04/2006");
set1.Tables[1].Rows.Add("c4", "130", "10/10/2006");
set1.Tables[1].Rows.Add("c5", "1.29", "10/14/2006");

DataRelation dr = new DataRelation("custOrders",


set1.Tables["Customers"].Columns["CustomerID"],
set1.Tables["Orders"].Columns["CustomerID"]);
set1.Relations.Add(dr);
return set1;
}
private int cachedPosition = -1;
private bool cacheChildPosition = true;

void relatedCM_ListChanged(object sender, ListChangedEventArgs e)


{
// Check to see if this is a caching situation.
if (cacheChildPosition && cachePositionCheckBox.Checked)
{
// If so, check to see if it is a reset situation, and the current
// position is greater than zero.
CurrencyManager relatedCM = sender as CurrencyManager;
if (e.ListChangedType == ListChangedType.Reset && relatedCM.Position > 0)

// If so, cache the position of the child table.


cachedPosition = relatedCM.Position;
}
}
}
void bindingSource1_CurrentChanged(object sender, EventArgs e)
{
// If the CurrentChanged event occurs, this is not a caching
// situation.
cacheChildPosition = false;
}
void relatedCM_PositionChanged(object sender, EventArgs e)
{
// Check to see if this is a caching situation.
if (cacheChildPosition && cachePositionCheckBox.Checked)
{
CurrencyManager relatedCM = sender as CurrencyManager;

// If so, check to see if the current position is


// not equal to the cached position and the cached
// position is not out of bounds.
if (relatedCM.Position != cachedPosition && cachedPosition
> 0 && cachedPosition < relatedCM.Count)
{
relatedCM.Position = cachedPosition;
cachedPosition = -1;
}
}
}
int count = 0;
private void button1_Click(object sender, EventArgs e)
{
// For demo purposes--modifies a value in the first row of the
// parent table.
DataRow row1 = set1.Tables[0].Rows[0];
row1[1] = DBNull.Value;
}

[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}

Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms

Public Class Form1


Inherits Form

Public Sub New()


InitializeControlsAndDataSource()

End Sub

' Declare the controls to be used.


Private WithEvents bindingSource1 As BindingSource
Private dataGridView1 As DataGridView
Private WithEvents button1 As Button
Private dataGridView2 As DataGridView
Private cachePositionCheckBox As CheckBox
Public set1 As DataSet
Private Sub InitializeControlsAndDataSource()
' Initialize the controls and set location, size and
' other basic properties.
Me.dataGridView1 = New DataGridView()
Me.bindingSource1 = New BindingSource()
Me.button1 = New Button()
Me.dataGridView2 = New DataGridView()
Me.cachePositionCheckBox = New System.Windows.Forms.CheckBox()
Me.dataGridView1.ColumnHeadersHeightSizeMode = _
DataGridViewColumnHeadersHeightSizeMode.AutoSize
Me.dataGridView1.Dock = DockStyle.Top
Me.dataGridView1.Location = New Point(0, 20)
Me.dataGridView1.Size = New Size(292, 170)
Me.button1.Location = New System.Drawing.Point(18, 175)
Me.button1.Size = New System.Drawing.Size(125, 23)

button1.Text = "Clear Parent Field"

Me.dataGridView2.ColumnHeadersHeightSizeMode = _
System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize
Me.dataGridView2.Location = New System.Drawing.Point(0, 225)
Me.dataGridView2.Size = New System.Drawing.Size(309, 130)
Me.cachePositionCheckBox.AutoSize = True
Me.cachePositionCheckBox.Checked = True
Me.cachePositionCheckBox.Location = New System.Drawing.Point(150, 175)
Me.cachePositionCheckBox.Name = "radioButton1"
Me.cachePositionCheckBox.Size = New System.Drawing.Size(151, 17)
Me.cachePositionCheckBox.Text = "Cache and restore position"
Me.ClientSize = New System.Drawing.Size(325, 420)
Me.Controls.Add(Me.dataGridView1)
Me.Controls.Add(Me.cachePositionCheckBox)
Me.Controls.Add(Me.dataGridView2)
Me.Controls.Add(Me.button1)

' Initialize the data.


set1 = InitializeDataSet()

' Set the data source to the DataSet.


bindingSource1.DataSource = set1

'Set the DataMember to the Menu table.


bindingSource1.DataMember = "Customers"

' Add the control data bindings.


dataGridView1.DataSource = bindingSource1

' Set the data source and member for the second DataGridView.
dataGridView2.DataSource = bindingSource1
dataGridView2.DataMember = "custOrders"

' Get the currency manager for the customer orders binding.
Dim relatedCM As CurrencyManager = _
bindingSource1.GetRelatedCurrencyManager("custOrders")

' Handle the two events for caching and resetting the position.
AddHandler relatedCM.ListChanged, AddressOf relatedCM_ListChanged
AddHandler relatedCM.PositionChanged, AddressOf relatedCM_PositionChanged

' Set the position in the child table for demonstration purposes.
relatedCM.Position = 3

' Set cacheing to true in case current changed event


' occurred on set up.
cacheChildPosition = True

End Sub
' Establish the data set with two tables and a relationship
' between them.
Private Function InitializeDataSet() As DataSet
set1 = New DataSet()
' Declare the DataSet and add a table and column.
set1.Tables.Add("Customers")
set1.Tables(0).Columns.Add("CustomerID")
set1.Tables(0).Columns.Add("Customer Name")
set1.Tables(0).Columns.Add("Contact Name")

' Add some rows to the table.


set1.Tables("Customers").Rows.Add("c1", "Fabrikam, Inc.", _
"Ellen Adams")
set1.Tables(0).Rows.Add("c2", "Lucerne Publishing", "Don Hall")
set1.Tables(0).Rows.Add("c3", "Northwind Traders", "Lori Penor")
set1.Tables(0).Rows.Add("c4", "Tailspin Toys", "Michael Patten")
set1.Tables(0).Rows.Add("c5", "Woodgrove Bank", "Jyothi Pai")

' Declare the DataSet and add a table and column.


set1.Tables.Add("Orders")
set1.Tables(1).Columns.Add("CustomerID")
set1.Tables(1).Columns.Add("OrderNo")
set1.Tables(1).Columns.Add("OrderDate")

' Add some rows to the table.


set1.Tables(1).Rows.Add("c1", "119", "10/04/2006")
set1.Tables(1).Rows.Add("c1", "149", "10/10/2006")
set1.Tables(1).Rows.Add("c1", "159", "10/12/2006")
set1.Tables(1).Rows.Add("c2", "169", "10/10/2006")
set1.Tables(1).Rows.Add("c2", "179", "10/10/2006")
set1.Tables(1).Rows.Add("c2", "189", "10/12/2006")
set1.Tables(1).Rows.Add("c3", "122", "10/04/2006")
set1.Tables(1).Rows.Add("c4", "130", "10/10/2006")
set1.Tables(1).Rows.Add("c5", "1.29", "10/14/2006")

Dim dr As New DataRelation("custOrders", _


set1.Tables("Customers").Columns("CustomerID"), _
set1.Tables("Orders").Columns("CustomerID"))
set1.Relations.Add(dr)
Return set1

End Function '


Private cachedPosition As Integer = - 1
Private cacheChildPosition As Boolean = True

Private Sub relatedCM_ListChanged(ByVal sender As Object, _


ByVal e As ListChangedEventArgs)
' Check to see if this is a caching situation.
If cacheChildPosition AndAlso cachePositionCheckBox.Checked Then
' If so, check to see if it is a reset situation, and the current
' position is greater than zero.
Dim relatedCM As CurrencyManager = sender
If e.ListChangedType = ListChangedType.Reset _
AndAlso relatedCM.Position > 0 Then

' If so, cache the position of the child table.


cachedPosition = relatedCM.Position
End If
End If

End Sub

' Handle the current changed event. This event occurs when
' the current item is changed, but not when a field of the current
' item is changed.
Private Sub bindingSource1_CurrentChanged(ByVal sender As Object, _
ByVal e As EventArgs) Handles bindingSource1.CurrentChanged
ByVal e As EventArgs) Handles bindingSource1.CurrentChanged
' If the CurrentChanged event occurs, this is not a caching
' situation.
cacheChildPosition = False

End Sub

Private Sub relatedCM_PositionChanged(ByVal sender As Object, ByVal e As EventArgs)


' Check to see if this is a caching situation.
If cacheChildPosition AndAlso cachePositionCheckBox.Checked Then
Dim relatedCM As CurrencyManager = sender

' If so, check to see if the current position is


' not equal to the cached position and the cached
' position is not out of bounds.
If relatedCM.Position <> cachedPosition AndAlso _
cachedPosition > 0 AndAlso cachedPosition < _
relatedCM.Count Then
relatedCM.Position = cachedPosition
cachedPosition = -1
End If
End If
End Sub

Private count As Integer = 0

Private Sub button1_Click(ByVal sender As Object, _


ByVal e As EventArgs) Handles button1.Click
' For demo purposes--modifies a value in the first row of the
' parent table.
Dim row1 As DataRow = set1.Tables(0).Rows(0)
row1(1) = DBNull.Value
End Sub

<STAThread()> _
Shared Sub Main()
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
Application.Run(New Form1())

End Sub
End Class

Para testar o exemplo de código, execute as etapas a seguir:


1. Execute o exemplo.
2. Marque a caixa de seleção Armazenar em cache e redefinir posição .
3. Clique no botão Limpar campo pai para provocar uma alteração em um campo da tabela pai. Observe
que a linha selecionada na tabela filho não muda.
4. Feche e execute o exemplo novamente. Você precisa fazer isso porque o comportamento de reinicialização
ocorre apenas na primeira alteração da linha pai.
5. Desmarque a caixa de seleção Armazenar em cache e redefinir posição .
6. Clique no botão Limpar campo pai . Observe que a linha selecionada na tabela filho muda para a primeira
linha.

Compilando o código
Este exemplo requer:
Referência aos assemblies System, System.Data, System.Drawing, System.Windows.Forms e System.XML.
Consulte também
Como: Certifique-se de vários controles associados à mesma fonte de dados permaneçam sincronizados
Componente BindingSource
Vinculação de dados e os Windows Forms
Como: implementar a interface IListSource
23/10/2019 • 7 minutes to read • Edit Online

Implementar o IListSource interface para criar uma classe vinculável que não implementa IList , mas em vez disso,
fornece uma lista de outro local.

Exemplo
O exemplo de código a seguir demonstra como implementar o IListSource interface. Um componente chamado
EmployeeListSource expõe uma IList para vinculação de dados Implementando o GetList método.

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;

namespace IListSourceCS
{
public class EmployeeListSource : Component, IListSource
{
public EmployeeListSource() {}

public EmployeeListSource(IContainer container)


{
container.Add(this);
}

#region IListSource Members

bool IListSource.ContainsListCollection
{
get { return false; }
}

System.Collections.IList IListSource.GetList()
{
BindingList<Employee> ble = new BindingList<Employee>();

if (!this.DesignMode)
{
ble.Add(new Employee("Aaberg, Jesper", 26000000));
ble.Add(new Employee("Cajhen, Janko", 19600000));
ble.Add(new Employee("Furse, Kari", 19000000));
ble.Add(new Employee("Langhorn, Carl", 16000000));
ble.Add(new Employee("Todorov, Teodor", 15700000));
ble.Add(new Employee("Verebélyi, Ágnes", 15700000));
}

return ble;
}

#endregion
}
}

Imports System.ComponentModel

Public Class EmployeeListSource


Inherits Component
Inherits Component
Implements IListSource

<System.Diagnostics.DebuggerNonUserCode()> _
Public Sub New(ByVal Container As System.ComponentModel.IContainer)
MyClass.New()

'Required for Windows.Forms Class Composition Designer support


Container.Add(Me)

End Sub

<System.Diagnostics.DebuggerNonUserCode()> _
Public Sub New()
MyBase.New()

'This call is required by the Component Designer.


InitializeComponent()

End Sub

'Component overrides dispose to clean up the component list.


<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Component Designer


Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Component Designer


'It can be modified using the Component Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
End Sub

#Region "IListSource Members"

Public ReadOnly Property ContainsListCollection() As Boolean Implements


System.ComponentModel.IListSource.ContainsListCollection
Get
Return False
End Get
End Property

Public Function GetList() As System.Collections.IList Implements System.ComponentModel.IListSource.GetList

Dim ble As New BindingList(Of Employee)

If Not Me.DesignMode Then


ble.Add(New Employee("Aaberg, Jesper", 26000000))
ble.Add(New Employee("Cajhen, Janko", 19600000))
ble.Add(New Employee("Furse, Kari", 19000000))
ble.Add(New Employee("Langhorn, Carl", 16000000))
ble.Add(New Employee("Todorov, Teodor", 15700000))
ble.Add(New Employee("Verebélyi, Ágnes", 15700000))
End If

Return ble

End Function

#End Region

End Class
End Class

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;

namespace IListSourceCS
{
public class Employee : BusinessObjectBase
{
private string _id;
private string _name;
private Decimal parkingId;

public Employee() : this(string.Empty, 0) {}


public Employee(string name) : this(name, 0) {}

public Employee(string name, Decimal parkingId) : base()


{
this._id = System.Guid.NewGuid().ToString();

// Set values
this.Name = name;
this.ParkingID = parkingId;
}

public string ID
{
get { return _id; }
}

const string NAME = "Name";


public string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;

// Raise the PropertyChanged event.


OnPropertyChanged(NAME);
}
}
}

const string PARKING_ID = "Salary";


public Decimal ParkingID
{
get { return parkingId; }
set
{
if (parkingId != value)
{
parkingId = value;

// Raise the PropertyChanged event.


OnPropertyChanged(PARKING_ID);
}
}
}
}
}
Imports System.ComponentModel

Public Class Employee


Inherits BusinessObjectBase

Private _id As String


Private _name As String
Private _parkingId As Decimal

Public Sub New(ByVal name As String, ByVal parkId As Decimal)


MyBase.New()
Me._id = System.Guid.NewGuid().ToString()
' Set values
Me.Name = name
Me.ParkingID = parkId
End Sub

Public ReadOnly Property ID() As String


Get
Return _id
End Get
End Property

Const NAME_Const As String = "Name"

Public Property Name() As String


Get
Return _name
End Get
Set(ByVal value As String)
If _name <> value Then
_name = value
OnPropertyChanged(NAME_Const)
End If
End Set
End Property

Const PARKINGID_Const As String = "ParkingID"

Public Property ParkingID() As Decimal


Get
Return _parkingId
End Get
Set(ByVal value As Decimal)
If _parkingId <> value Then
_parkingId = value
OnPropertyChanged(PARKINGID_Const)
End If
End Set
End Property

End Class
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Diagnostics;

namespace IListSourceCS
{
public class BusinessObjectBase : INotifyPropertyChanged
{
#region INotifyPropertyChanged Members

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(string propertyName)


{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}

private void OnPropertyChanged(PropertyChangedEventArgs e)


{
if (null != PropertyChanged)
{
PropertyChanged(this, e);
}
}

#endregion
}
}

Imports System.ComponentModel

Public Class BusinessObjectBase


Implements INotifyPropertyChanged

#Region "INotifyPropertyChanged Members"

Public Event PropertyChanged(ByVal sender As Object, ByVal e As


System.ComponentModel.PropertyChangedEventArgs) Implements
System.ComponentModel.INotifyPropertyChanged.PropertyChanged

Protected Overridable Sub OnPropertyChanged(ByVal propertyName As String)


OnPropertyChanged(New PropertyChangedEventArgs(propertyName))
End Sub

Private Sub OnPropertyChanged(ByVal e As PropertyChangedEventArgs)


RaiseEvent PropertyChanged(Me, e)
End Sub

#End Region

End Class

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace IListSourceCS
{
public class Form1 : Form
public class Form1 : Form
{
private System.ComponentModel.IContainer components = null;
private FlowLayoutPanel flowLayoutPanel1;
private Label label2;
private DataGridView dataGridView1;
private DataGridViewTextBoxColumn nameDataGridViewTextBoxColumn;
private DataGridViewTextBoxColumn salaryDataGridViewTextBoxColumn;
private DataGridViewTextBoxColumn iDDataGridViewTextBoxColumn;
private EmployeeListSource employeeListSource1;

public Form1()
{
InitializeComponent();
}

protected override void Dispose(bool disposing)


{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

#region Windows Form Designer generated code

private void InitializeComponent()


{
this.components = new System.ComponentModel.Container();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new
System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new
System.Windows.Forms.DataGridViewCellStyle();
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.label2 = new System.Windows.Forms.Label();
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.nameDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.salaryDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.iDDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.employeeListSource1 = new EmployeeListSource(this.components);
this.flowLayoutPanel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.SuspendLayout();
//
// flowLayoutPanel1
//
this.flowLayoutPanel1.AutoSize = true;
this.flowLayoutPanel1.Controls.Add(this.label2);
this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Top;
this.flowLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.flowLayoutPanel1.Name = "flowLayoutPanel1";
this.flowLayoutPanel1.Size = new System.Drawing.Size(416, 51);
this.flowLayoutPanel1.TabIndex = 11;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(3, 6);
this.label2.Margin = new System.Windows.Forms.Padding(3, 6, 3, 6);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(408, 39);
this.label2.TabIndex = 0;
this.label2.Text = "This sample demonstrates how to implement the IListSource interface. In this
sam" +
"ple, a DataGridView is bound at design time to a Component (employeeListSource1)" +
" that implements IListSource.";
//
// dataGridView1
//
//
this.dataGridView1.AllowUserToAddRows = false;
this.dataGridView1.AllowUserToDeleteRows = false;
dataGridViewCellStyle1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)
(((byte)(255)))), ((int)(((byte)(192)))));
this.dataGridView1.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle1;
this.dataGridView1.AutoGenerateColumns = false;
this.dataGridView1.ColumnHeadersHeightSizeMode =
System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.nameDataGridViewTextBoxColumn,
this.salaryDataGridViewTextBoxColumn,
this.iDDataGridViewTextBoxColumn});
this.dataGridView1.DataSource = this.employeeListSource1;
this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
this.dataGridView1.Location = new System.Drawing.Point(0, 51);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.RowHeadersVisible = false;
this.dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
this.dataGridView1.Size = new System.Drawing.Size(416, 215);
this.dataGridView1.TabIndex = 12;
//
// nameDataGridViewTextBoxColumn
//
this.nameDataGridViewTextBoxColumn.DataPropertyName = "Name";
this.nameDataGridViewTextBoxColumn.FillWeight = 131.7987F;
this.nameDataGridViewTextBoxColumn.HeaderText = "Name";
this.nameDataGridViewTextBoxColumn.Name = "nameDataGridViewTextBoxColumn";
//
// salaryDataGridViewTextBoxColumn
//
this.salaryDataGridViewTextBoxColumn.DataPropertyName = "ParkingID";
this.salaryDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle2;
this.salaryDataGridViewTextBoxColumn.FillWeight = 121.8274F;
this.salaryDataGridViewTextBoxColumn.HeaderText = "Parking ID";
this.salaryDataGridViewTextBoxColumn.Name = "salaryDataGridViewTextBoxColumn";
//
// iDDataGridViewTextBoxColumn
//
this.iDDataGridViewTextBoxColumn.AutoSizeMode =
System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
this.iDDataGridViewTextBoxColumn.DataPropertyName = "ID";
this.iDDataGridViewTextBoxColumn.FillWeight = 46.37391F;
this.iDDataGridViewTextBoxColumn.HeaderText = "ID";
this.iDDataGridViewTextBoxColumn.Name = "iDDataGridViewTextBoxColumn";
this.iDDataGridViewTextBoxColumn.ReadOnly = true;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(416, 266);
this.Controls.Add(this.dataGridView1);
this.Controls.Add(this.flowLayoutPanel1);
this.Name = "Form1";
this.Text = "IListSource Sample";
this.flowLayoutPanel1.ResumeLayout(false);
this.flowLayoutPanel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}

#endregion
}

static class Program


{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}

Imports System.ComponentModel
Imports System.Windows.Forms

Public Class Form1


Inherits System.Windows.Forms.Form

Friend WithEvents flowLayoutPanel1 As FlowLayoutPanel


Friend WithEvents label2 As Label
Friend WithEvents dataGridView1 As DataGridView
Friend WithEvents nameDataGridViewTextBoxColumn As DataGridViewTextBoxColumn
Friend WithEvents salaryDataGridViewTextBoxColumn As DataGridViewTextBoxColumn
Friend WithEvents iDDataGridViewTextBoxColumn As DataGridViewTextBoxColumn
Friend WithEvents employeeListSource1 As EmployeeListSource

Public Sub New()


MyBase.New()

Me.InitializeComponent()
End Sub

'Form overrides dispose to clean up the component list.


<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer


Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer


'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()

Dim dataGridViewCellStyle1 = New System.Windows.Forms.DataGridViewCellStyle()


Dim dataGridViewCellStyle2 = New System.Windows.Forms.DataGridViewCellStyle()
Me.flowLayoutPanel1 = New System.Windows.Forms.FlowLayoutPanel()
Me.label2 = New System.Windows.Forms.Label()
Me.dataGridView1 = New System.Windows.Forms.DataGridView()
Me.nameDataGridViewTextBoxColumn = New System.Windows.Forms.DataGridViewTextBoxColumn()
Me.salaryDataGridViewTextBoxColumn = New System.Windows.Forms.DataGridViewTextBoxColumn()
Me.iDDataGridViewTextBoxColumn = New System.Windows.Forms.DataGridViewTextBoxColumn()
Me.employeeListSource1 = New EmployeeListSource(Me.components)
Me.flowLayoutPanel1.SuspendLayout()
CType(Me.dataGridView1, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
' flowLayoutPanel1
'
Me.flowLayoutPanel1.AutoSize = True
Me.flowLayoutPanel1.Controls.Add(Me.label2)
Me.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Top
Me.flowLayoutPanel1.Location = New System.Drawing.Point(0, 0)
Me.flowLayoutPanel1.Name = "flowLayoutPanel1"
Me.flowLayoutPanel1.Size = New System.Drawing.Size(416, 51)
Me.flowLayoutPanel1.TabIndex = 11
'
' label2
'
Me.label2.AutoSize = True
Me.label2.Location = New System.Drawing.Point(3, 6)
Me.label2.Margin = New System.Windows.Forms.Padding(3, 6, 3, 6)
Me.label2.Name = "label2"
Me.label2.Size = New System.Drawing.Size(408, 39)
Me.label2.TabIndex = 0
Me.label2.Text = "This sample demonstrates how to implement the IListSource interface. In this sam" +
_
"ple, a DataGridView is bound at design time to a Component (employeeListSource1)" + _
" that implements IListSource."
'
' dataGridView1
'
Me.dataGridView1.AllowUserToAddRows = False
Me.dataGridView1.AllowUserToDeleteRows = False
dataGridViewCellStyle1.BackColor = System.Drawing.Color.FromArgb(255, 255, 192)
Me.dataGridView1.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle1
Me.dataGridView1.AutoGenerateColumns = False
Me.dataGridView1.ColumnHeadersHeightSizeMode =
System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize
Me.dataGridView1.Columns.AddRange(New System.Windows.Forms.DataGridViewColumn() { _
Me.nameDataGridViewTextBoxColumn, Me.salaryDataGridViewTextBoxColumn, Me.iDDataGridViewTextBoxColumn})
Me.dataGridView1.DataSource = Me.employeeListSource1
Me.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill
Me.dataGridView1.Location = New System.Drawing.Point(0, 51)
Me.dataGridView1.Name = "dataGridView1"
Me.dataGridView1.RowHeadersVisible = False
Me.dataGridView1.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect
Me.dataGridView1.Size = New System.Drawing.Size(416, 215)
Me.dataGridView1.TabIndex = 12
'
' nameDataGridViewTextBoxColumn
'
Me.nameDataGridViewTextBoxColumn.DataPropertyName = "Name"
Me.nameDataGridViewTextBoxColumn.FillWeight = 131.7987F
Me.nameDataGridViewTextBoxColumn.HeaderText = "Name"
Me.nameDataGridViewTextBoxColumn.Name = "nameDataGridViewTextBoxColumn"
'
' salaryDataGridViewTextBoxColumn
'
Me.salaryDataGridViewTextBoxColumn.DataPropertyName = "ParkingID"
Me.salaryDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle2
Me.salaryDataGridViewTextBoxColumn.FillWeight = 121.8274F
Me.salaryDataGridViewTextBoxColumn.HeaderText = "Parking ID"
Me.salaryDataGridViewTextBoxColumn.Name = "salaryDataGridViewTextBoxColumn"
'
' iDDataGridViewTextBoxColumn
'
Me.iDDataGridViewTextBoxColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill
Me.iDDataGridViewTextBoxColumn.DataPropertyName = "ID"
Me.iDDataGridViewTextBoxColumn.FillWeight = 46.37391F
Me.iDDataGridViewTextBoxColumn.HeaderText = "ID"
Me.iDDataGridViewTextBoxColumn.Name = "iDDataGridViewTextBoxColumn"
Me.iDDataGridViewTextBoxColumn.ReadOnly = True
'
' Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0F, 13.0F)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(416, 266)
Me.Controls.Add(Me.dataGridView1)
Me.Controls.Add(Me.flowLayoutPanel1)
Me.Name = "Form1"
Me.Text = "IListSource Sample"
Me.flowLayoutPanel1.ResumeLayout(False)
Me.flowLayoutPanel1.PerformLayout()
CType(Me.dataGridView1, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
Me.PerformLayout()

End Sub

Shared Sub Main()


Application.Run(New Form1())
End Sub
End Class

Compilando o código
Este exemplo requer:
Referências aos assemblies System.Drawing e System.Windows.Forms.

Consulte também
IListSource
ITypedList
BindingList<T>
IBindingList
Vinculação de dados e os Windows Forms
Como: implementar a interface
INotifyPropertyChanged
23/10/2019 • 5 minutes to read • Edit Online

O exemplo de código a seguir demonstra como implementar o INotifyPropertyChanged interface. Implemente


essa interface em objetos de negócios que são usados na associação de dados de formulários do Windows.
Quando implementada, a interface se comunica com um controle associado a alteração de propriedade em um
objeto comercial.

Exemplo
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.CompilerServices;
using System.Windows.Forms;

// Change the namespace to the project name.


namespace TestNotifyPropertyChangedCS
{
// This form demonstrates using a BindingSource to bind
// a list to a DataGridView control. The list does not
// raise change notifications. However the DemoCustomer type
// in the list does.
public partial class Form1 : Form
{
// This button causes the value of a list element to be changed.
private Button changeItemBtn = new Button();

// This DataGridView control displays the contents of the list.


private DataGridView customersDataGridView = new DataGridView();

// This BindingSource binds the list to the DataGridView control.


private BindingSource customersBindingSource = new BindingSource();

public Form1()
{
InitializeComponent();

// Set up the "Change Item" button.


this.changeItemBtn.Text = "Change Item";
this.changeItemBtn.Dock = DockStyle.Bottom;
this.changeItemBtn.Click +=
new EventHandler(changeItemBtn_Click);
this.Controls.Add(this.changeItemBtn);

// Set up the DataGridView.


customersDataGridView.Dock = DockStyle.Top;
this.Controls.Add(customersDataGridView);

this.Size = new Size(400, 200);


}

private void Form1_Load(object sender, EventArgs e)


{
// Create and populate the list of DemoCustomer objects
// which will supply data to the DataGridView.
BindingList<DemoCustomer> customerList = new BindingList<DemoCustomer>();
customerList.Add(DemoCustomer.CreateNewCustomer());
customerList.Add(DemoCustomer.CreateNewCustomer());
customerList.Add(DemoCustomer.CreateNewCustomer());

// Bind the list to the BindingSource.


this.customersBindingSource.DataSource = customerList;

// Attach the BindingSource to the DataGridView.


this.customersDataGridView.DataSource =
this.customersBindingSource;
}

// Change the value of the CompanyName property for the first


// item in the list when the "Change Item" button is clicked.
void changeItemBtn_Click(object sender, EventArgs e)
{
// Get a reference to the list from the BindingSource.
BindingList<DemoCustomer> customerList =
this.customersBindingSource.DataSource as BindingList<DemoCustomer>;

// Change the value of the CompanyName property for the


// first item in the list.
customerList[0].CustomerName = "Tailspin Toys";
customerList[0].PhoneNumber = "(708)555-0150";
}
}

// This is a simple customer class that


// implements the IPropertyChange interface.
public class DemoCustomer : INotifyPropertyChanged
{
// These fields hold the values for the public properties.
private Guid idValue = Guid.NewGuid();
private string customerNameValue = String.Empty;
private string phoneNumberValue = String.Empty;

public event PropertyChangedEventHandler PropertyChanged;

// This method is called by the Set accessor of each property.


// The CallerMemberName attribute that is applied to the optional propertyName
// parameter causes the property name of the caller to be substituted as an argument.
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

// The constructor is private to enforce the factory pattern.


private DemoCustomer()
{
customerNameValue = "Customer";
phoneNumberValue = "(312)555-0100";
}

// This is the public factory method.


public static DemoCustomer CreateNewCustomer()
{
return new DemoCustomer();
}

// This property represents an ID, suitable


// for use as a primary key in a database.
public Guid ID
{
get
{
return this.idValue;
return this.idValue;
}
}

public string CustomerName


{
get
{
return this.customerNameValue;
}

set
{
if (value != this.customerNameValue)
{
this.customerNameValue = value;
NotifyPropertyChanged();
}
}
}

public string PhoneNumber


{
get
{
return this.phoneNumberValue;
}

set
{
if (value != this.phoneNumberValue)
{
this.phoneNumberValue = value;
NotifyPropertyChanged();
}
}
}
}
}

Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Drawing
Imports System.Runtime.CompilerServices
Imports System.Windows.Forms

' This form demonstrates using a BindingSource to bind


' a list to a DataGridView control. The list does not
' raise change notifications. However the DemoCustomer type
' in the list does.

Public Class Form1


Inherits System.Windows.Forms.Form
' This button causes the value of a list element to be changed.
Private changeItemBtn As New Button()

' This DataGridView control displays the contents of the list.


Private customersDataGridView As New DataGridView()

' This BindingSource binds the list to the DataGridView control.


Private customersBindingSource As New BindingSource()

Public Sub New()


InitializeComponent()

' Set up the "Change Item" button.


Me.changeItemBtn.Text = "Change Item"
Me.changeItemBtn.Dock = DockStyle.Bottom
Me.changeItemBtn.Dock = DockStyle.Bottom
AddHandler Me.changeItemBtn.Click, AddressOf changeItemBtn_Click
Me.Controls.Add(Me.changeItemBtn)

' Set up the DataGridView.


customersDataGridView.Dock = DockStyle.Top
Me.Controls.Add(customersDataGridView)

Me.Size = New Size(400, 200)


End Sub

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


ByVal e As System.EventArgs) Handles Me.Load

' Create and populate the list of DemoCustomer objects


' which will supply data to the DataGridView.
Dim customerList As New BindingList(Of DemoCustomer)

customerList.Add(DemoCustomer.CreateNewCustomer())
customerList.Add(DemoCustomer.CreateNewCustomer())
customerList.Add(DemoCustomer.CreateNewCustomer())

' Bind the list to the BindingSource.


Me.customersBindingSource.DataSource = customerList

' Attach the BindingSource to the DataGridView.


Me.customersDataGridView.DataSource = Me.customersBindingSource
End Sub

' This event handler changes the value of the CompanyName


' property for the first item in the list.
Private Sub changeItemBtn_Click(ByVal sender As Object, ByVal e As EventArgs)
' Get a reference to the list from the BindingSource.
Dim customerList As BindingList(Of DemoCustomer) = _
CType(customersBindingSource.DataSource, BindingList(Of DemoCustomer))

' Change the value of the CompanyName property for the


' first item in the list.
customerList(0).CustomerName = "Tailspin Toys"
customerList(0).PhoneNumber = "(708)555-0150"
End Sub
End Class

' This class implements a simple customer type


' that implements the IPropertyChange interface.
Public Class DemoCustomer
Implements INotifyPropertyChanged

' These fields hold the values for the public properties.
Private idValue As Guid = Guid.NewGuid()
Private customerNameValue As String = String.Empty
Private phoneNumberValue As String = String.Empty

Public Event PropertyChanged As PropertyChangedEventHandler _


Implements INotifyPropertyChanged.PropertyChanged

' This method is called by the Set accessor of each property.


' The CallerMemberName attribute that is applied to the optional propertyName
' parameter causes the property name of the caller to be substituted as an argument.
Private Sub NotifyPropertyChanged(<CallerMemberName()> Optional ByVal propertyName As String = Nothing)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub

' The constructor is private to enforce the factory pattern.


Private Sub New()
customerNameValue = "Customer"
phoneNumberValue = "(312)555-0100"
End Sub

' This is the public factory method.


' This is the public factory method.
Public Shared Function CreateNewCustomer() As DemoCustomer
Return New DemoCustomer()
End Function

' This property represents an ID, suitable


' for use as a primary key in a database.
Public ReadOnly Property ID() As Guid
Get
Return Me.idValue
End Get
End Property

Public Property CustomerName() As String


Get
Return Me.customerNameValue
End Get

Set(ByVal value As String)


If Not (value = customerNameValue) Then
Me.customerNameValue = value
NotifyPropertyChanged()
End If
End Set
End Property

Public Property PhoneNumber() As String


Get
Return Me.phoneNumberValue
End Get

Set(ByVal value As String)


If Not (value = phoneNumberValue) Then
Me.phoneNumberValue = value
NotifyPropertyChanged()
End If
End Set
End Property
End Class

Consulte também
Como: Aplicar o padrão PropertyNameChanged
Associação de dados do Windows Forms
Como: Gerar notificações de alteração usando um BindingSource e a Interface INotifyPropertyChanged
Notificação de alteração na vinculação de dados dos Windows Forms
Como: implementar a interface ITypedList
23/10/2019 • 9 minutes to read • Edit Online

Implementar o ITypedList interface para habilitar a descoberta do esquema para uma lista vinculável.

Exemplo
O exemplo de código a seguir demonstra como implementar o ITypedList interface. Um tipo genérico chamado
SortableBindingList deriva de BindingList<T> classe e implementa o ITypedList interface. Uma classe simples
denominada Customer fornece os dados, o que estão associados ao cabeçalho de uma DataGridView controle.
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using System.Collections;
using System.Reflection;

namespace ITypedListCS
{
[Serializable()]
public class SortableBindingList<T> : BindingList<T>, ITypedList
{
[NonSerialized()]
private PropertyDescriptorCollection properties;

public SortableBindingList() : base()


{
// Get the 'shape' of the list.
// Only get the public properties marked with Browsable = true.
PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(
typeof(T),
new Attribute[] { new BrowsableAttribute(true) });

// Sort the properties.


properties = pdc.Sort();
}

#region ITypedList Implementation

public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)


{
PropertyDescriptorCollection pdc;

if (listAccessors!=null && listAccessors.Length>0)


{
// Return child list shape.
pdc = ListBindingHelper.GetListItemProperties(listAccessors[0].PropertyType);
}
else
{
// Return properties in sort order.
pdc = properties;
}

return pdc;
}

// This method is only used in the design-time framework


// and by the obsolete DataGrid control.
public string GetListName(PropertyDescriptor[] listAccessors)
{
return typeof(T).Name;
}

#endregion
}
}
Imports System.ComponentModel
Imports System.Collections.Generic
Imports System.Windows.Forms

<Serializable()> _
Public Class SortableBindingList(Of Tkey)
Inherits BindingList(Of Tkey)
Implements ITypedList

<NonSerialized()> _
Private properties As PropertyDescriptorCollection

Public Sub New()


MyBase.New()

' Get the 'shape' of the list.


' Only get the public properties marked with Browsable = true.
Dim pdc As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(Tkey), New Attribute()
{New BrowsableAttribute(True)})

' Sort the properties.


properties = pdc.Sort()

End Sub

#Region "ITypedList Implementation"

Public Function GetItemProperties(ByVal listAccessors() As System.ComponentModel.PropertyDescriptor) As


System.ComponentModel.PropertyDescriptorCollection Implements
System.ComponentModel.ITypedList.GetItemProperties

Dim pdc As PropertyDescriptorCollection

If (Not (listAccessors Is Nothing)) And (listAccessors.Length > 0) Then


' Return child list shape
pdc = ListBindingHelper.GetListItemProperties(listAccessors(0).PropertyType)
Else
' Return properties in sort order
pdc = properties
End If

Return pdc

End Function

' This method is only used in the design-time framework


' and by the obsolete DataGrid control.
Public Function GetListName( _
ByVal listAccessors() As PropertyDescriptor) As String _
Implements System.ComponentModel.ITypedList.GetListName

Return GetType(Tkey).Name

End Function

#End Region

End Class

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;

namespace ITypedListCS
{
class Customer : INotifyPropertyChanged
{
public Customer() {}

public Customer(int id, string name, string company, string address, string city, string state, string
zip)
{
this._id = id;
this._name = name;
this._company = company;
this._address = address;
this._city = city;
this._state = state;
this._zip = zip;
}

#region Public Properties

private int _id;

public int ID
{
get { return _id; }
set
{
if (_id != value)
{
_id = value;
OnPropertyChanged(new PropertyChangedEventArgs("ID"));
}
}
}

private string _name;

public string Name


{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged(new PropertyChangedEventArgs("Name"));
}
}
}

private string _company;

public string Company


{
get { return _company; }
set
{
if (_company != value)
{
_company = value;
OnPropertyChanged(new PropertyChangedEventArgs("Company"));
}
}
}

private string _address;

public string Address


{
get { return _address; }
set
{
if (_address != value)
{
_address = value;
OnPropertyChanged(new PropertyChangedEventArgs("Address"));
}
}
}

private string _city;

public string City


{
get { return _city; }
set
{
if (_city != value)
{
_city = value;
OnPropertyChanged(new PropertyChangedEventArgs("City"));
}
}
}

private string _state;

public string State


{
get { return _state; }
set
{
if (_state != value)
{
_state = value;
OnPropertyChanged(new PropertyChangedEventArgs("State"));
}
}
}

private string _zip;

public string ZipCode


{
get { return _zip; }
set
{
if (_zip != value)
{
_zip = value;
OnPropertyChanged(new PropertyChangedEventArgs("ZipCode"));
}
}
}

#endregion

#region INotifyPropertyChanged Members

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)


{
if (null != PropertyChanged)
{
PropertyChanged(this, e);
}
}

#endregion
#endregion
}
}

Imports System.ComponentModel

Public Class Customer


Implements INotifyPropertyChanged

Public Sub New()

End Sub

Public Sub New(ByVal id As Integer, ByVal name As String, ByVal company As String, ByVal address As
String, ByVal city As String, ByVal state As String, ByVal zip As String)
Me._id = id
Me._name = name
Me._company = company
Me._address = address
Me._city = city
Me._state = state
Me._zip = zip

End Sub

#Region "Public Properties"

Private _id As Integer


Public Property ID() As Integer
Get
Return _id
End Get
Set(ByVal value As Integer)
If _id <> value Then
_id = value
OnPropertyChanged(New PropertyChangedEventArgs("ID"))
End If
End Set
End Property

Private _name As String

Public Property Name() As String


Get
Return _name
End Get
Set(ByVal value As String)
If _name <> value Then
_name = value
OnPropertyChanged(New PropertyChangedEventArgs("Name"))
End If
End Set
End Property

Private _company As String

Public Property Company() As String


Get
Return _company
End Get
Set(ByVal value As String)
If _company <> value Then
_company = value
OnPropertyChanged(New PropertyChangedEventArgs("Company"))
End If
End Set
End Property
Private _address As String

Public Property Address() As String


Get
Return _address
End Get
Set(ByVal value As String)
If _address <> value Then
_address = value
OnPropertyChanged(New PropertyChangedEventArgs("Address"))
End If
End Set
End Property

Private _city As String

Public Property City() As String


Get
Return _city
End Get
Set(ByVal value As String)
If _city <> value Then
_city = value
OnPropertyChanged(New PropertyChangedEventArgs("City"))
End If
End Set
End Property

Private _state As String

Public Property State() As String


Get
Return _state
End Get
Set(ByVal value As String)
If _state <> value Then
_state = value
OnPropertyChanged(New PropertyChangedEventArgs("State"))
End If
End Set
End Property

Private _zip As String

Public Property ZipCode() As String


Get
Return _zip
End Get
Set(ByVal value As String)
If _zip <> value Then
_zip = value
OnPropertyChanged(New PropertyChangedEventArgs("ZipCode"))
End If
End Set
End Property

#End Region

#Region "INotifyPropertyChanged Members"

Public Event PropertyChanged(ByVal sender As Object, ByVal e As


System.ComponentModel.PropertyChangedEventArgs) Implements
System.ComponentModel.INotifyPropertyChanged.PropertyChanged

Protected Overridable Sub OnPropertyChanged(ByVal e As PropertyChangedEventArgs)


Protected Overridable Sub OnPropertyChanged(ByVal e As PropertyChangedEventArgs)
RaiseEvent PropertyChanged(Me, e)
End Sub

#End Region

End Class

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace ITypedListCS
{
public partial class Form1 : Form
{
private SortableBindingList<Customer> sortableBindingListOfCustomers;
private BindingList<Customer> bindingListOfCustomers;

private System.ComponentModel.IContainer components = null;


private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
private System.Windows.Forms.Label label2;
private DataGridView dataGridView1;
private Button button1;
private Button button2;

public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)


{
this.sortableBindingListOfCustomers = new SortableBindingList<Customer>();
this.bindingListOfCustomers = new BindingList<Customer>();

this.dataGridView1.DataSource = this.bindingListOfCustomers;
}

private void button1_Click(object sender, EventArgs e)


{
this.dataGridView1.DataSource = null;
this.dataGridView1.DataSource = this.sortableBindingListOfCustomers;
}

private void button2_Click(object sender, EventArgs e)


{
this.dataGridView1.DataSource = null;
this.dataGridView1.DataSource = this.bindingListOfCustomers;
}

protected override void Dispose(bool disposing)


{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

#region Windows Form Designer generated code

private void InitializeComponent()


{
{
System.ComponentModel.ComponentResourceManager resources = new
System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.label2 = new System.Windows.Forms.Label();
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.flowLayoutPanel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.SuspendLayout();
//
// flowLayoutPanel1
//
this.flowLayoutPanel1.AutoSize = true;
this.flowLayoutPanel1.Controls.Add(this.label2);
this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Top;
this.flowLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.flowLayoutPanel1.Name = "flowLayoutPanel1";
this.flowLayoutPanel1.Size = new System.Drawing.Size(566, 51);
this.flowLayoutPanel1.TabIndex = 13;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(3, 6);
this.label2.Margin = new System.Windows.Forms.Padding(3, 6, 3, 6);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(558, 39);
this.label2.TabIndex = 0;
this.label2.Text = "This sample demonstrates how to implement the ITypedList interface. Clicking
on the 'Sort Columns' button will bind the DataGridView to a sub-classed BindingList<T> that implements
ITypedList to provide a sorted list of columns. Clicking on the 'Reset' button will bind the DataGridView to
a normal BindingList<T>.";
//
// dataGridView1
//
this.dataGridView1.AllowUserToAddRows = false;
this.dataGridView1.AllowUserToDeleteRows = false;
this.dataGridView1.Anchor = ((System.Windows.Forms.AnchorStyles)
((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.dataGridView1.AutoSizeColumnsMode =
System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
this.dataGridView1.ColumnHeadersHeightSizeMode =
System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Location = new System.Drawing.Point(6, 57);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.ReadOnly = true;
this.dataGridView1.RowHeadersVisible = false;
this.dataGridView1.Size = new System.Drawing.Size(465, 51);
this.dataGridView1.TabIndex = 14;
//
// button1
//
this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top
| System.Windows.Forms.AnchorStyles.Right)));
this.button1.Location = new System.Drawing.Point(477, 57);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(82, 23);
this.button1.TabIndex = 15;
this.button1.Text = "Sort Columns";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top
| System.Windows.Forms.AnchorStyles.Right)));
| System.Windows.Forms.AnchorStyles.Right)));
this.button2.Location = new System.Drawing.Point(477, 86);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(82, 23);
this.button2.TabIndex = 16;
this.button2.Text = "Reset";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(566, 120);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Controls.Add(this.dataGridView1);
this.Controls.Add(this.flowLayoutPanel1);
this.Name = "Form1";
this.Text = "ITypedList Sample";
this.Load += new System.EventHandler(this.Form1_Load);
this.flowLayoutPanel1.ResumeLayout(false);
this.flowLayoutPanel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}

#endregion
}

static class Program


{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}

Imports System.ComponentModel
Imports System.Windows.Forms

Public Class Form1


Inherits System.Windows.Forms.Form

Friend WithEvents flowLayoutPanel1 As FlowLayoutPanel


Friend WithEvents label2 As System.Windows.Forms.Label
Friend WithEvents dataGridView1 As DataGridView
Friend WithEvents button1 As Button
Friend WithEvents button2 As Button

Dim sortableBindingListOfCustomers As SortableBindingList(Of Customer)


Dim bindingListOfCustomers As BindingList(Of Customer)

Public Sub New()


MyBase.New()

Me.InitializeComponent()
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

sortableBindingListOfCustomers = New SortableBindingList(Of Customer)()


bindingListOfCustomers = New BindingList(Of Customer)()

Me.dataGridView1.DataSource = bindingListOfCustomers
End Sub

Private Sub button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles


button1.Click
Me.dataGridView1.DataSource = Nothing
Me.dataGridView1.DataSource = sortableBindingListOfCustomers
End Sub

Private Sub button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles


button2.Click
Me.dataGridView1.DataSource = Nothing
Me.dataGridView1.DataSource = bindingListOfCustomers
End Sub

'Form overrides dispose to clean up the component list.


<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer


Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer


'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Dim resources As System.ComponentModel.ComponentResourceManager = New
System.ComponentModel.ComponentResourceManager(GetType(Form1))
Me.flowLayoutPanel1 = New System.Windows.Forms.FlowLayoutPanel
Me.label2 = New System.Windows.Forms.Label
Me.dataGridView1 = New System.Windows.Forms.DataGridView
Me.button1 = New System.Windows.Forms.Button
Me.button2 = New System.Windows.Forms.Button
Me.flowLayoutPanel1.SuspendLayout()
CType(Me.dataGridView1, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'flowLayoutPanel1
'
Me.flowLayoutPanel1.AutoSize = True
Me.flowLayoutPanel1.Controls.Add(Me.label2)
Me.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Top
Me.flowLayoutPanel1.Location = New System.Drawing.Point(0, 0)
Me.flowLayoutPanel1.Name = "flowLayoutPanel1"
Me.flowLayoutPanel1.Size = New System.Drawing.Size(566, 51)
Me.flowLayoutPanel1.TabIndex = 13
'
'label2
'
Me.label2.AutoSize = True
Me.label2.Location = New System.Drawing.Point(3, 6)
Me.label2.Margin = New System.Windows.Forms.Padding(3, 6, 3, 6)
Me.label2.Name = "label2"
Me.label2.Size = New System.Drawing.Size(558, 39)
Me.label2.TabIndex = 0
Me.label2.Text = "This sample demonstrates how to implement the ITypedList interface. Clicking on the
'Sort Columns' button will bind the DataGridView to a sub-classed BindingList<T> that implements ITypedList to
'Sort Columns' button will bind the DataGridView to a sub-classed BindingList<T> that implements ITypedList to
provide a sorted list of columns. Clicking on the 'Reset' button will bind the DataGridView to a normal
BindingList<T>."
'
'dataGridView1
'
Me.dataGridView1.AllowUserToAddRows = False
Me.dataGridView1.AllowUserToDeleteRows = False
Me.dataGridView1.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or
System.Windows.Forms.AnchorStyles.Bottom) _
Or System.Windows.Forms.AnchorStyles.Left) _
Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.dataGridView1.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill
Me.dataGridView1.ColumnHeadersHeightSizeMode =
System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize
Me.dataGridView1.Location = New System.Drawing.Point(6, 57)
Me.dataGridView1.Name = "dataGridView1"
Me.dataGridView1.ReadOnly = True
Me.dataGridView1.RowHeadersVisible = False
Me.dataGridView1.Size = New System.Drawing.Size(465, 51)
Me.dataGridView1.TabIndex = 14
'
'button1
'
Me.button1.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or
System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.button1.Location = New System.Drawing.Point(477, 57)
Me.button1.Name = "button1"
Me.button1.Size = New System.Drawing.Size(82, 23)
Me.button1.TabIndex = 15
Me.button1.Text = "Sort Columns"
Me.button1.UseVisualStyleBackColor = True
'
'button2
'
Me.button2.Location = New System.Drawing.Point(477, 86)
Me.button2.Name = "button2"
Me.button2.Size = New System.Drawing.Size(82, 23)
Me.button2.TabIndex = 16
Me.button2.Text = "Reset"
Me.button2.UseVisualStyleBackColor = True
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(566, 120)
Me.Controls.Add(Me.button2)
Me.Controls.Add(Me.button1)
Me.Controls.Add(Me.dataGridView1)
Me.Controls.Add(Me.flowLayoutPanel1)
Me.Name = "Form1"
Me.Text = "ITypedList Sample"
Me.flowLayoutPanel1.ResumeLayout(False)
Me.flowLayoutPanel1.PerformLayout()
CType(Me.dataGridView1, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub

Shared Sub Main()


Application.Run(New Form1())
End Sub

End Class
Compilando o código
Este exemplo requer:
Referências aos assemblies System.Drawing e System.Windows.Forms.

Consulte também
ITypedList
BindingList<T>
IBindingList
Vinculação de dados e os Windows Forms
Como navegar por dados no Windows Forms
03/02/2020 • 4 minutes to read • Edit Online

Em um aplicativo do Windows, a maneira mais fácil de navegar pelos registros em uma fonte de dados é associar
um componente BindingSource à fonte de dados e, em seguida, associar os controles à BindingSource. Você pode
usar o método de navegação interno no BindingSource MoveNext, MoveLast, MovePrevious e MoveFirst. O uso
desses métodos ajustará as propriedades Position e Current do BindingSource adequadamente. Você também
pode encontrar um item e defini-lo como o item atual definindo a propriedade Position.
Incrementar a posição em uma fonte de dados
1. Defina a propriedade Position do BindingSource para os dados associados à posição do registro para a
qual ir. O exemplo a seguir ilustra o uso do método MoveNext da BindingSource para incrementar a
propriedade Position quando o nextButton é clicado. O BindingSource está associado à tabela de
Customers de um conjunto de Northwind de um DataSet.

NOTE
Definir a propriedade Position como um valor além do primeiro ou último registro não resulta em um erro, pois o
.NET Framework não permitirá que você defina a posição como um valor fora dos limites da lista. Se, no aplicativo,
for importante saber se você passou do primeiro ou do último registro, inclua a lógica para testar se a contagem de
elementos de dados será excedida.

private void nextButton_Click(object sender, System.EventArgs e)


{
this.customersBindingSource.MoveNext();
}

Private Sub nextButton_Click(ByVal sender As Object, _


ByVal e As System.EventArgs) Handles nextButton.Click
Me.customersBindingSource.MoveNext()
End Sub

Verificar se você passou do final ou do início


1. Crie um manipulador de eventos para o evento PositionChanged. No manipulador, é possível testar se o
valor da posição proposta excedeu a contagem de elementos de dados real.
O exemplo a seguir ilustra como testar se o último elemento de dados foi alcançado. No exemplo, se você
estiver no último elemento, o botão Próximo do formulário estará desabilitado.

NOTE
Lembre-se de que é necessário alterar a lista em que você está navegando no código, reabilite o botão Próximo ,
para que os usuários possam pesquisar a totalidade da nova lista. Além disso, lembre-se de que o evento de
PositionChanged acima para o BindingSource específico com o qual você está trabalhando precisa estar associado ao
seu método de manipulação de eventos. Veja a seguir um exemplo de um método para manipular o evento de
PositionChanged:
void customersBindingSource_PositionChanged(object sender, EventArgs e)
{
if (customersBindingSource.Position == customersBindingSource.Count - 1)
nextButton.Enabled = false;
else
nextButton.Enabled = true;
}

Sub customersBindingSource_PositionChanged(ByVal sender As Object, _


ByVal e As EventArgs)

If customersBindingSource.Position = _
customersBindingSource.Count - 1 Then
nextButton.Enabled = False
Else
nextButton.Enabled = True
End If
End Sub

Localizar um item e defini-lo como o item atual


1. Localize o registro que deseja definir como o item atual. Você pode fazer isso usando o método Find da
BindingSource, se sua fonte de dados implementar IBindingList. Alguns exemplos de fontes de dados que
implementam IBindingList são BindingList<T> e DataView.

void findButton_Click(object sender, EventArgs e)


{
int foundIndex = customersBindingSource.Find("CustomerID", "ANTON");
customersBindingSource.Position = foundIndex;
}

Sub findButton_Click(ByVal sender As Object, ByVal e As EventArgs) _


Handles findButton.Click
Dim foundIndex As Integer = customersBindingSource.Find("CustomerID", _
"ANTON")
customersBindingSource.Position = foundIndex
End Sub

Consulte também
Fontes de dados com suporte nos Windows Forms
Notificação de alteração na vinculação de dados dos Windows Forms
Associação de dados e o Windows Forms
Associação de dados do Windows Forms
Segurança do Windows Forms
03/02/2020 • 3 minutes to read • Edit Online

O Windows Forms oferece um modelo de segurança baseado em código (os níveis de segurança são definidos
para o código, independentemente do usuário que o executa). Isso vai além de qualquer esquema de segurança
que já pode estar em vigor no seu sistema de computador. Eles podem incluir os do navegador (como a segurança
baseada em zonas disponível no Internet Explorer) ou do sistema operacional (como a segurança baseada em
credenciais do Windows NT).

Nesta seção
Visão geral da segurança dos Windows Forms
Explica brevemente o modelo de segurança do .NET Framework e as etapas básicas necessárias para garantir que
o Windows Forms no seu aplicativo esteja seguro.
Acesso mais seguro a arquivos e a dados nos Windows Forms
Descreve como acessar arquivos e dados em um ambiente de confiança parcial.
Impressão mais segura nos Windows Forms
Descreve como acessar recursos de impressão em um ambiente de confiança parcial.
Considerações adicionais sobre segurança nos Windows Forms
Descreve como realizar manipulação de janela, como usar a Área de Transferência e como fazer chamadas a
código não gerenciado em um ambiente de confiança parcial.

Seções Relacionadas
Política de segurança padrão
Lista as permissões padrão concedidas nos conjuntos de permissão de Confiança Total, Intranet Local e Internet.
Administração de política de segurança geral
Fornece informações sobre como administrar a política de segurança do .NET Framework e elevar as permissões.
Permissões perigosas e administração de política
Discute algumas permissões do .NET Framework que podem potencialmente permitir que o sistema de segurança
seja contornado.
Diretrizes de codificação segura
Fornece links para tópicos que explicam as práticas recomendadas para escrever código com segurança no .NET
Framework.
Solicitando permissões
Discute o uso de atributos que permitem que o runtime saiba quais permissões seu código precisa executar.
Principais conceitos de segurança
Links para tópicos que abrangem aspectos básicos de segurança de código.
Noções Básicas da Segurança de Acesso do Código
Discute as noções básicas de trabalhar com a política de segurança de tempo de execução do .NET Framework.
Determinando quando modificar a política de segurança
Explica como determinar quando seus aplicativos precisam divergir da política de segurança padrão.
Implantando política de segurança
Discute a melhor maneira de implantar alterações de política de segurança.
Visão geral da Segurança do Windows Forms
03/02/2020 • 18 minutes to read • Edit Online

Antes do lançamento da .NET Framework, todo o código em execução no computador de um usuário tinha os
mesmos direitos ou permissões para acessar os recursos que um usuário do computador tinha. Por exemplo, se o
usuário era autorizado a acessar o sistema de arquivos, o código era autorizado a acessar o sistema de arquivos.
Se o usuário era autorizado a acessar um banco de dados, o código era autorizado a acessar o banco de dados.
Embora esses direitos ou permissões possam ser aceitáveis para código em executáveis que o usuário
explicitamente instalou no computador local, eles podem não ser aceitáveis para código potencialmente mal-
intencionado proveniente da Internet ou de uma intranet local. Esse código não deveria ser capaz de acessar
recursos do computador do usuário sem permissão.
O .NET Framework introduz uma infraestrutura chamada segurança de acesso ao código que permite diferenciar
as permissões, ou direitos, que o código tem dos direitos que o usuário tem. Por padrão, o código proveniente da
Internet e da intranet somente pode executar no que é conhecido como confiança parcial. A confiança parcial
sujeita um aplicativo a uma série de restrições: entre outras coisas, um aplicativo é impedido de acessar o disco
rígido local e não pode executar código não gerenciado. O .NET Framework controla os recursos que o código tem
permissão para acessar com base na identidade desse código: de onde ele veio, se ele tem um assembly de nome
forte, se ele está assinado com um certificado e assim por diante.
A tecnologia ClickOnce, que você usa para implantar Windows Forms aplicativos, ajuda a facilitar o
desenvolvimento de aplicativos que são executados em confiança parcial, com confiança total ou em confiança
parcial com permissões elevadas. O ClickOnce fornece recursos como elevação de permissão e implantação de
aplicativo confiável para que seu aplicativo possa solicitar confiança total ou permissões elevadas do usuário local
de uma maneira responsável.

Noções básicas sobre segurança no .NET Framework


A segurança de acesso do código permite que o código seja confiável em graus variáveis, dependendo da origem
do código e de outros aspectos de sua identidade. Para obter mais informações sobre a evidência que o Common
Language Runtime usa para determinar a política de segurança, consulte Evidências. Ele ajuda a proteger os
sistemas do computador contra código mal-intencionado e ajuda a proteger o código confiável contra
intencionalmente ou acidentalmente comprometer a segurança. A segurança de acesso do código também
oferece mais controle sobre quais ações seu aplicativo pode realizar, porque você pode especificar somente as
permissões que você precisa que seu aplicativo tenha. A segurança de acesso do código afeta todo código
gerenciado que se destina ao Common Language Runtime, mesmo que esse código não faça nenhuma verificação
de permissão de segurança de acesso do código. Para obter mais informações sobre segurança na .NET
Framework, consulte conceitos principais de segurança e noções básicas de segurança de acesso ao código.
Se o usuário executar um arquivo executável dos Windows Forms diretamente de um servidor Web ou de um
compartilhamento de arquivos, o grau de confiança concedido ao seu aplicativo dependerá de onde reside o
código e de como ele foi iniciado. Quando um aplicativo é executado, ele é automaticamente avaliado e recebe um
conjunto de permissões nomeadas do Common Language Runtime. Por padrão, o conjunto de permissões de
Confiança Total é concedido ao código do computador local, o conjunto de permissões de Intranet Local é
concedido ao código de uma rede local e o conjunto de permissões de Internet é concedido ao código da Internet.
NOTE
No .NET Framework versão 1,0 Service Pack 1 e Service Pack 2, o grupo de códigos de zona da Internet recebe o conjunto
de permissões Nothing. Em todas as outras versões do .NET Framework, o grupo de códigos de zona da Internet recebe as
permissões da Internet definidas.
As permissões padrão concedidas em cada um desses conjuntos de permissão são listadas no tópico Política de segurança
padrão. Dependendo das permissões que o aplicativo recebe, ele é executado corretamente ou gera uma exceção de
segurança.
Muitos aplicativos Windows Forms serão implantados usando o ClickOnce. As ferramentas usadas para gerar uma
implantação do ClickOnce têm padrões de segurança diferentes do que o que foi discutido anteriormente. Para obter mais
informações, veja a seguinte discussão.

As permissões reais concedidas ao seu aplicativo podem ser diferentes dos valores padrão, porque a política de
segurança pode ser modificada. Isso significa que seu aplicativo pode ter permissão em um computador, mas não
em outro.

Desenvolvendo um aplicativo mais seguro dos Windows Forms


A segurança é importante em todas as etapas do desenvolvimento de aplicativos. Comece revisando e seguindo
as Diretrizes de codificação segura.
Em seguida, decida se seu aplicativo deve ser executado em confiança total ou em confiança parcial. Executar o
aplicativo em confiança total facilita o acesso a recursos no computador local, mas expõe seu aplicativo e os
usuários a altos riscos de segurança, caso você não crie e desenvolva seu aplicativo estritamente de acordo com o
tópico Diretrizes de codificação segura. Executar o aplicativo em confiança parcial facilita o desenvolvimento de
um aplicativo mais seguro e reduz muito o risco, mas exige mais planejamento sobre como implementar
determinados recursos.
Se você escolher a confiança parcial (isto é, os conjuntos de permissões de Internet ou de Intranet Local), decida
como deseja que o aplicativo se comporte nesse ambiente. O Windows Forms fornece maneiras alternativas e
mais seguras para implementar recursos quando em um ambiente semi-confiável. Certas partes do seu aplicativo,
como o acesso a dados, podem ser projetadas e escritas de maneiras diferentes para ambientes de confiança total
e de confiança parcial. Alguns recursos dos Windows Forms, como as configurações de aplicativo, são projetados
para funcionar em confiança parcial. Para obter mais informações, consulte Visão geral de configurações de
aplicativo.
Se seu aplicativo precisa de mais permissões que as concedidas pela confiança parcial, mas você não deseja
executar em confiança total, você pode executar em confiança parcial, declarando somente as permissões
adicionais que são necessárias. Por exemplo, se você deseja executar com confiança parcial, mas deve conceder a
seu aplicativo acesso somente leitura a um diretório no sistema de arquivos do usuário, você pode solicitar
FileIOPermission somente para esse diretório. Se for usada corretamente, essa abordagem pode fornecer
funcionalidade aumentada ao seu aplicativo e minimizar os riscos de segurança para seus usuários.
Ao desenvolver um aplicativo que será executado em confiança parcial, mantenha o controle sobre quais
permissões seu aplicativo deve executar e quais permissões seu aplicativo pode usar opcionalmente. Quando
todas as permissões forem conhecidas, você deverá fazer uma solicitação declarativa de permissão no nível do
aplicativo. A solicitação de permissões informa o .NET Framework tempo de execução sobre quais permissões seu
aplicativo precisa e quais permissões ele não deseja especificamente. Para obter mais informações sobre a
solicitação de permissões, consulte Solicitando permissões.
Ao solicitar permissões opcionais, você deverá tratar as exceções de segurança que serão geradas se o aplicativo
realizar uma ação que exija permissões que não foram concedidas a ele. O tratamento apropriado do
SecurityException garantirá que seu aplicativo possa continuar a operar. Seu aplicativo pode usar a exceção para
determinar se um recurso deve ser desabilitado para o usuário. Por exemplo, um aplicativo poderá desabilitar a
opção de menu Salvar se a permissão de arquivo necessária não for concedida.
Às vezes é difícil saber se você declarou todas as permissões apropriadas. Uma chamada de método que parece
inofensiva na superfície, por exemplo, pode acessar o sistema de arquivos em algum ponto durante sua execução.
Se você não implantar seu aplicativo com todas as permissões necessárias, poderá ser bem sucedido em teste,
quando você depurá-lo na área de trabalho, mas falhar ao ser implantado. O SDK .NET Framework 2,0 e o Visual
Studio 2005 contêm ferramentas para calcular as permissões que um aplicativo precisa: a ferramenta de linha de
comando MT. exe e o recurso Calculate Permissions do Visual Studio, respectivamente.
Os tópicos a seguir descrevem recursos adicionais de segurança dos Windows Forms.

TÓ P IC O DESC RIÇ Ã O

- Acesso mais seguro a arquivos e a dados nos Windows Descreve como acessar arquivos e dados em um ambiente de
Forms confiança parcial.

- Impressão mais segura nos Windows Forms Descreve como acessar os recursos de impressão em um
ambiente de confiança parcial.

- Considerações adicionais sobre segurança nos Windows Descreve como realizar manipulação de janela, como usar a
Forms área de transferência e como fazer chamadas a código não
gerenciado em um ambiente de confiança parcial.

Implantando um aplicativo com as permissões apropriadas


O meio mais comum de implantar um aplicativo Windows Forms em um computador cliente é com o ClickOnce,
uma tecnologia de implantação que descreve todos os componentes que seu aplicativo precisa executar. O
ClickOnce usa arquivos XML chamados manifestos para descrever os assemblies e arquivos que compõem seu
aplicativo e também as permissões que seu aplicativo requer.
O ClickOnce tem duas tecnologias para solicitar permissões elevadas em um computador cliente. As duas
tecnologias contam com o uso de certificados Authenticode. Os certificados ajudam a fornecer alguma garantia
para os usuários de que o aplicativo é proveniente de uma fonte confiável.
A tabela a seguir descreve essas tecnologias.

T EC N O LO GIA DE P ERM ISSÕ ES EL EVA DA S DESC RIÇ Ã O

Elevação de permissões Exibe ao usuário uma caixa de diálogo de segurança na


primeira vez que seu aplicativo é executado. A caixa de
diálogo de Elevação de permissões informa ao usuário
sobre quem publicou o aplicativo, para que o usuário possa
tomar uma decisão informada sobre se deve conceder
confiança adicional

Implantação de aplicativo confiável Envolve um administrador do sistema realizando a instalação


de um certificado Authenticode de editor em um computador
cliente uma única vez. Daí em diante, todos os aplicativos
assinados com o certificado serão considerados confiáveis e
poderão ser executados em confiança total no computador
local, sem avisos adicionais.

A tecnologia escolhida dependerá de seu ambiente de implantação. Para obter mais informações, consulte
Escolhendo uma estratégia de implantação do ClickOnce.
Por padrão, os aplicativos ClickOnce implantados usando o Visual Studio ou as ferramentas SDK do .NET
Framework (Mage. exe e MageUI. exe) são configurados para serem executados em um computador cliente com
confiança total. Se você estiver implantando seu aplicativo usando a confiança parcial ou usando somente
algumas permissões adicionais, você terá que alterar esse padrão. Isso pode ser feito com o Visual Studio ou com
a ferramenta SDK do .NET Framework MageUI. exe quando você configura a implantação. Para obter mais
informações sobre como usar o MageUI. exe, consulte passo a passos: Implantando manualmente um aplicativo
ClickOnce. Consulte também Como definir permissões personalizadas para um aplicativo ClickOnce ou Como
definir permissões personalizadas para um aplicativo ClickOnce.
Para obter mais informações sobre os aspectos de segurança do ClickOnce e a elevação de permissões, consulte
Securing ClickOnce Applications. Para obter mais informações sobre a implantação de aplicativo confiável,
consulte Visão geral da implantação de aplicativos confiáveis.
Testando o aplicativo
Se você tiver implantado seu aplicativo Windows Forms usando o Visual Studio, poderá habilitar a depuração em
confiança parcial ou um conjunto de permissões restritos do ambiente de desenvolvimento. Consulte também
como: Depurar um aplicativo ClickOnce com permissões restritas.

Consulte também
Segurança do Windows Forms
Noções Básicas da Segurança de Acesso do Código
Segurança e implantação do ClickOnce
Visão geral da implantação de aplicativos confiáveis
Mage.exe (Manifest Generation and Editing Tool)
MageUI.exe (Manifest Generation and Editing Tool, cliente gráfico)
Acesso mais seguro a arquivos e dados no Windows
Forms
20/03/2020 • 15 minutes to read • Edit Online

O .NET Framework usa permissões para ajudar a proteger recursos e dados. Onde seu aplicativo pode ler ou
gravar dados depende das permissões concedidas ao aplicativo. Quando seu aplicativo é executado em um
ambiente de confiança parcial, talvez você não tenha acesso aos seus dados ou talvez você precise alterar a
maneira como você acessa os dados.
Quando você encontrar uma restrição de segurança, você tem duas opções: declarar a permissão (supondo que
ela foi concedida ao seu aplicativo) ou use uma versão do recurso escrita para trabalhar em confiança parcial. As
seções a seguir abordam como trabalhar com arquivos, o banco de dados e o acesso ao Registro de aplicativos
que são executados em um ambiente parcialmente confiável.

NOTE
Por padrão, as ferramentas que geram implantações clickOnce padrão essas implantações para solicitar full trust a partir dos
computadores em que eles são executados. Se você decidir que deseja os benefícios adicionais de segurança de executar em
confiança parcial, você deve alterar esse padrão no Visual Studio ou em uma das ferramentas do Windows SDK (Mage.exe
ou MageUI.exe). Para obter mais informações sobre segurança dos Windows Forms e sobre como determinar o nível de
confiança apropriado para seu aplicativo, consulte Visão geral de Segurança nos Windows Forms.

Acesso a arquivos
A FileIOPermission classe controla o acesso a arquivos e pastas no Quadro .NET. Por padrão, o sistema de
FileIOPermission segurança não concede a parte de ambientes de confiança, como a intranet local e zonas de
Internet. No entanto, um aplicativo que requer acesso a arquivos ainda funcionará nesses ambientes se você
modificar o design do seu aplicativo ou usa métodos diferentes para acessar arquivos. Por padrão, a zona da
intranet local recebe o direito de ter o mesmo acesso a sites e o mesmo acesso a diretórios, para conectar-se
novamente ao site de sua origem e ler seu diretório de instalação. Por padrão, a zona da Internet, é apenas o
direito para se conectar novamente ao site de sua origem.
Arquivos especificados pelo usuário
Uma maneira de lidar com a não permissão de acesso ao OpenFileDialog arquivo SaveFileDialog é solicitar ao
usuário que forneça informações específicas do arquivo usando a ou a classe. Essa interação de usuário ajuda a
fornecer alguma garantia de que o aplicativo não pode carregar arquivos particulares ou substituir arquivos
importantes maliciosamente. Os OpenFile OpenFile métodos fornecem acesso a arquivos de leitura e gravação
abrindo o fluxo de arquivos para o arquivo que o usuário especificou. Os métodos também ajudam a proteger o
arquivo do usuário ocultando o caminho do arquivo.

NOTE
Essas permissões são diferentes dependendo se o seu aplicativo estiver na zona da Internet ou zona da Intranet. Os
aplicativos da região OpenFileDialogda Internet só podem usar o , enquanto os aplicativos Intranet têm permissão de
diálogo de arquivo irrestrita.

A FileDialogPermission classe especifica que tipo de caixa de diálogo de arquivo seu aplicativo pode usar. A tabela
a seguir mostra o FileDialog valor que você deve ter para usar cada classe.
C L A SSE VA LO R DE A C ESSO N EC ESSÁ RIO

OpenFileDialog Open

SaveFileDialog Save

NOTE
A permissão específica não OpenFile é solicitada até que o método seja realmente chamado.

A permissão para exibir uma caixa de diálogo de FileDialogarquivo OpenFileDialognão SaveFileDialog concede ao
seu aplicativo acesso total a todos os membros das classes e classes. Para obter as permissões exatas necessárias
para chamar cada método, consulte o tópico de referência para esse método na documentação da biblioteca de
classe .NET Framework.
O exemplo de OpenFile código a seguir usa o método RichTextBox para abrir um arquivo especificado pelo
usuário em um controle. O exemplo FileDialogPermission requer Open e o valor de enumeração associado. O
exemplo demonstra como SecurityException lidar com o para determinar se o recurso de salvamento deve ser
desativado. Este exemplo requer Form que Button o ButtonOpen seu RichTextBox tenha RtfBoxMain um controle
chamado , e um controle chamado .

NOTE
A lógica de programação para o recurso de gravação não é mostrado no exemplo.
Private Sub ButtonOpen_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles ButtonOpen.Click

Dim editingFileName as String = ""


Dim saveAllowed As Boolean = True

' Displays the OpenFileDialog.


If (OpenFileDialog1.ShowDialog() = DialogResult.OK) Then
Dim userStream as System.IO.Stream
Try
' Opens the file stream for the file selected by the user.
userStream =OpenFileDialog1.OpenFile()
Me.RtfBoxMain.LoadFile(userStream, _
RichTextBoxStreamType.PlainText)
Finally
userStream.Close()
End Try

' Tries to get the file name selected by the user.


' Failure means that the application does not have
' unrestricted permission to the file.
Try
editingFileName = OpenFileDialog1.FileName
Catch ex As Exception
If TypeOf ex Is System.Security.SecurityException Then
' The application does not have unrestricted permission
' to the file so the save feature will be disabled.
saveAllowed = False
Else
Throw ex
End If
End Try
End If
End Sub
private void ButtonOpen_Click(object sender, System.EventArgs e)
{
String editingFileName = "";
Boolean saveAllowed = true;

// Displays the OpenFileDialog.


if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
// Opens the file stream for the file selected by the user.
using (System.IO.Stream userStream = openFileDialog1.OpenFile())
{
this.RtfBoxMain.LoadFile(userStream,
RichTextBoxStreamType.PlainText);
userStream.Close();
}

// Tries to get the file name selected by the user.


// Failure means that the application does not have
// unrestricted permission to the file.
try
{
editingFileName = openFileDialog1.FileName;
}
catch (Exception ex)
{
if (ex is System.Security.SecurityException)
{
// The application does not have unrestricted permission
// to the file so the save feature will be disabled.
saveAllowed = false;
}
else
{
throw ex;
}
}
}
}

NOTE
No Visual C#, certifique-se de adicionar código para ativar o manipulador de eventos. Ao usar o código do exemplo anterior,
o código a seguir mostra como habilitar o manipulador de eventos.
this.ButtonOpen.Click += newSystem.Windows.Forms.EventHandler(this.ButtonOpen_Click);

Outros arquivos
Às vezes, você precisará ler ou gravar em arquivos que o usuário não especifica, como quando você precisa salvar
as configurações do aplicativo. Na intranet local e zonas da Internet, o aplicativo não terá permissão para
armazenar dados em um arquivo local. No entanto, seu aplicativo poderá armazenar dados no armazenamento
isolado. Armazenamento isolado é um compartimento de dados abstrato (não um local de armazenamento
específico) que contém um ou mais arquivos de armazenamento isolados, chamados de armazenamentos, que
contêm os locais reais dos diretórios nos quais os dados são armazenados. Permissões de FileIOPermission
acesso ao arquivo não são necessárias; em vez IsolatedStoragePermission disso, a classe controla as permissões
para armazenamento isolado. Por padrão, os aplicativos que são executados na intranet local e zonas da Internet
podem armazenar dados usando armazenamento isolado; No entanto, configurações como cota de disco podem
variar. Para obter mais informações sobre armazenamento isolado, consulte Armazenamento Isolado.
O exemplo a seguir usa armazenamento isolado para gravar dados em um arquivo localizado em um repositório.
O exemplo IsolatedStorageFilePermission requer DomainIsolationByUser e o valor de enumeração. O exemplo
demonstra a leitura e Button a escrita de certos valores de propriedade do controle para um arquivo em
armazenamento isolado. A função Read é chamada depois que o aplicativo é iniciado e a função Write é
chamada antes do aplicativo terminar. O exemplo requer Read Write que as funções Form e funções existam
como membros de um que contém um Button controle chamado MainButton .

' Reads the button options from the isolated storage. Uses Default values
' for the button if the options file does not exist.
Public Sub Read()
Dim isoStore As System.IO.IsolatedStorage.IsolatedStorageFile = _
System.IO.IsolatedStorage.IsolatedStorageFile. _
GetUserStoreForDomain()

Dim filename As String = "options.txt"


Try
' Checks to see if the options.txt file exists.
If (isoStore.GetFileNames(filename).GetLength(0) <> 0) Then

' Opens the file because it exists.


Dim isos As New System.IO.IsolatedStorage.IsolatedStorageFileStream _
(filename, IO.FileMode.Open,isoStore)
Dim reader as System.IO.StreamReader
Try
reader = new System.IO.StreamReader(isos)

' Reads the values stored.


Dim converter As System.ComponentModel.TypeConverter
converter = System.ComponentModel.TypeDescriptor.GetConverter _
(GetType(Color))

Me.MainButton.BackColor = _
CType(converter.ConvertFromString _
(reader.ReadLine()), Color)
me.MainButton.ForeColor = _
CType(converter.ConvertFromString _
(reader.ReadLine()), Color)

converter = System.ComponentModel.TypeDescriptor.GetConverter _
(GetType(Font))
me.MainButton.Font = _
CType(converter.ConvertFromString _
(reader.ReadLine()), Font)

Catch ex As Exception
Debug.WriteLine("Cannot read options " + _
ex.ToString())
Finally
reader.Close()
End Try
End If

Catch ex As Exception
Debug.WriteLine("Cannot read options " + ex.ToString())
End Try
End Sub

' Writes the button options to the isolated storage.


Public Sub Write()
Dim isoStore As System.IO.IsolatedStorage.IsolatedStorageFile = _
System.IO.IsolatedStorage.IsolatedStorageFile. _
GetUserStoreForDomain()

Dim filename As String = "options.txt"


Try
' Checks if the file exists, and if it does, tries to delete it.
If (isoStore.GetFileNames(filename).GetLength(0) <> 0) Then
isoStore.DeleteFile(filename)
End If
Catch ex As Exception
Debug.WriteLine("Cannot delete file " + ex.ToString())
End Try

' Creates the options.txt file and writes the button options to it.
Dim writer as System.IO.StreamWriter
Try
Dim isos As New System.IO.IsolatedStorage.IsolatedStorageFileStream _
(filename, IO.FileMode.CreateNew, isoStore)

writer = New System.IO.StreamWriter(isos)


Dim converter As System.ComponentModel.TypeConverter

converter = System.ComponentModel.TypeDescriptor.GetConverter _
(GetType(Color))
writer.WriteLine(converter.ConvertToString( _
Me.MainButton.BackColor))
writer.WriteLine(converter.ConvertToString( _
Me.MainButton.ForeColor))

converter = System.ComponentModel TypeDescriptor.GetConverter _


(GetType(Font))
writer.WriteLine(converter.ConvertToString( _
Me.MainButton.Font))

Catch ex as Exception
Debug.WriteLine("Cannot write options " + ex.ToString())

Finally
writer.Close()
End Try
End Sub

// Reads the button options from the isolated storage. Uses default values
// for the button if the options file does not exist.
public void Read()
{
System.IO.IsolatedStorage.IsolatedStorageFile isoStore =
System.IO.IsolatedStorage.IsolatedStorageFile.
GetUserStoreForDomain();

string filename = "options.txt";


try
{
// Checks to see if the options.txt file exists.
if (isoStore.GetFileNames(filename).GetLength(0) != 0)
{
// Opens the file because it exists.
System.IO.IsolatedStorage.IsolatedStorageFileStream isos =
new System.IO.IsolatedStorage.IsolatedStorageFileStream
(filename, System.IO.FileMode.Open,isoStore);
System.IO.StreamReader reader = null;
try
{
reader = new System.IO.StreamReader(isos);

// Reads the values stored.


TypeConverter converter ;
converter = TypeDescriptor.GetConverter(typeof(Color));

this.MainButton.BackColor =
(Color)(converter.ConvertFromString(reader.ReadLine()));
this.MainButton.ForeColor =
(Color)(converter.ConvertFromString(reader.ReadLine()));

converter = TypeDescriptor.GetConverter(typeof(Font));
this.MainButton.Font =
(Font)(converter.ConvertFromString(reader.ReadLine()));
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine
("Cannot read options " + ex.ToString());
}
finally
{
reader.Close();
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine
("Cannot read options " + ex.ToString());
}
}

// Writes the button options to the isolated storage.


public void Write()
{
System.IO.IsolatedStorage.IsolatedStorageFile isoStore =
System.IO.IsolatedStorage.IsolatedStorageFile.
GetUserStoreForDomain();

string filename = "options.txt";


try
{
// Checks if the file exists and, if it does, tries to delete it.
if (isoStore.GetFileNames(filename).GetLength(0) != 0)
{
isoStore.DeleteFile(filename);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine
("Cannot delete file " + ex.ToString());
}

// Creates the options file and writes the button options to it.
System.IO.StreamWriter writer = null;
try
{
System.IO.IsolatedStorage.IsolatedStorageFileStream isos = new
System.IO.IsolatedStorage.IsolatedStorageFileStream(filename,
System.IO.FileMode.CreateNew,isoStore);

writer = new System.IO.StreamWriter(isos);


TypeConverter converter ;

converter = TypeDescriptor.GetConverter(typeof(Color));
writer.WriteLine(converter.ConvertToString(
this.MainButton.BackColor));
writer.WriteLine(converter.ConvertToString(
this.MainButton.ForeColor));

converter = TypeDescriptor.GetConverter(typeof(Font));
writer.WriteLine(converter.ConvertToString(
this.MainButton.Font));

}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine
("Cannot write options " + ex.ToString());
}
finally
{
writer.Close();
}
}

Acesso a banco de dados


As permissões necessárias para acessar um banco de dados variam de acordo com o provedor de banco de
dados. No entanto, somente os aplicativos que estão executando com as permissões apropriadas podem acessar
um banco de dados por meio de uma conexão de dados. Para obter mais informações sobre as permissões
necessárias para acessar um banco de dados, consulte Segurança de Acesso ao Código e ADO.NET.
Se você não pode acessar um banco de dados diretamente, porque você deseja que o aplicativo seja executado
em confiança parcial, você pode usar um serviço Web como um meio alternativo para acessar seus dados. Um
serviço Web é um componente de software que pode ser acessado programaticamente através de uma rede. Com
os serviços Web, aplicativos podem compartilhar dados entre zonas de grupos de códigos. Por padrão, a
aplicativos na intranet local e zonas da Internet têm o direito de acessar seus sites de origem, que permite a
chamar um serviço Web hospedado no mesmo servidor. Para obter mais informações, consulte Serviços Web em
ASP.NET AJAX ou Windows Communication Foundation.

Acesso ao Registro
A RegistryPermission classe controla o acesso ao registro do sistema operacional. Por padrão, somente aplicativos
que estão sendo executados localmente podem acessar o Registro. RegistryPermissionapenas concede a um
aplicativo o direito de tentar o acesso ao registro; não garante que o acesso será bem sucedido, pois o sistema
operacional ainda impõe segurança no registro.
Como você não pode acessar o Registro sob confiança parcial, você precisará encontrar outros métodos para
armazenar seus dados. Quando você armazena configurações do aplicativo, use o armazenamento isolado em vez
de no Registro. Armazenamento isolado também pode ser usado para armazenar outros arquivos específicos do
aplicativo. Você também pode armazenar informações globais do aplicativo sobre o servidor ou site de origem,
porque, por padrão, um aplicativo recebe o direito de acessar o seu site de origem.

Confira também
Impressão mais segura no Windows Forms
Considerações adicionais sobre segurança nos Windows Forms
Visão geral da Segurança do Windows Forms
Segurança de formulários do Windows
Mage.exe (Manifest Generation and Editing Tool)
MageUI.exe (Manifest Generation and Editing Tool, cliente gráfico)
Impressão mais segura no Windows Forms
03/02/2020 • 2 minutes to read • Edit Online

Aplicativos dos Windows Forms com frequência incluem recursos de impressão. O .NET Framework usa a classe
PrintingPermission para controlar o acesso a recursos de impressão e o valor de enumeração
PrintingPermissionLevel associado para indicar o nível de acesso. Por padrão, a impressão é habilitada por padrão
nas zonas da Internet e da Intranet Local. No entanto, o nível de acesso é restrito em ambas as zonas. Não
importa se o seu aplicativo pode imprimir, requer interação do usuário ou não pode imprimir, isso dependerá do
valor da permissão concedida ao aplicativo. Por padrão, a zona da intranet local recebe DefaultPrinting acesso e a
zona da intranet recebe acesso SafePrinting.
A tabela a seguir mostra a funcionalidade disponível em cada nível de permissão de impressão.

P RIN T IN GP ERM ISSIO N L EVEL DESC RIÇ Ã O

AllPrinting Fornece acesso completo a todas as impressoras instaladas.

DefaultPrinting Habilita a impressão programática para a impressora padrão


e a impressão mais segura por meio de uma caixa de diálogo
de impressão restritiva. DefaultPrinting é um subconjunto de
AllPrinting.

SafePrinting Fornece impressão apenas em uma caixa de diálogo mais


restrita. SafePrinting é um subconjunto de DefaultPrinting.

NoPrinting Impede o acesso a impressoras. NoPrinting é um subconjunto


de SafePrinting.

Consulte também
Acesso mais seguro a arquivos e a dados nos Windows Forms
Considerações adicionais sobre segurança nos Windows Forms
Visão geral da segurança dos Windows Forms
Segurança do Windows Forms
Considerações adicionais sobre Segurança do
Windows Forms
03/02/2020 • 13 minutes to read • Edit Online

.NET Framework configurações de segurança podem fazer com que seu aplicativo seja executado de forma
diferente em um ambiente de confiança parcial do que no computador local. O .NET Framework restringe o
acesso a recursos locais críticos como o sistema de arquivos, a rede e as APIs não gerenciadas, entre outras coisas.
As configurações de segurança afetam a capacidade de chamar a API do Microsoft Windows ou outras APIs que
não podem ser verificadas pelo sistema de segurança. A segurança também afeta outros aspectos do seu
aplicativo, incluindo acesso a arquivos e dados e impressão. Para obter mais informações sobre o acesso a
arquivos e dados em um ambiente de confiança parcial, consulte acesso a dados e arquivos mais seguros em
Windows Forms. Para obter mais informações sobre como imprimir em um ambiente de confiança parcial,
consulte impressão mais segura em Windows Forms.
As seções a seguir discutem como trabalhar com a área de transferência, executar a manipulação de janela e
chamar a API do Windows de aplicativos que estão sendo executados em um ambiente de confiança parcial.

Acesso à área de transferência


A classe UIPermission controla o acesso à área de transferência e o valor de Enumeração associada
UIPermissionClipboard indica o nível de acesso. A tabela a seguir mostra os níveis de permissão possíveis.

VA LO R DE UIP ERM ISSIO N C L IP B O A RD DESC RIÇ Ã O

AllClipboard A área de transferência pode ser usada sem restrição.

OwnClipboard A área de transferência pode ser usada com algumas


restrições. A capacidade de colocar dados na área de
transferência (operações de comando copiar ou recortar) é
irrestrita. Controles intrínsecos que aceitam colar, como uma
caixa de texto, podem aceitar dados da área de transferência,
mas os controles de usuário não podem ler
programaticamente da área de transferência.

NoClipboard Não é possível usar a área de transferência.

Por padrão, a zona da intranet local recebe AllClipboard acesso e a zona da Internet recebe acesso OwnClipboard.
Isso significa que o aplicativo pode copiar dados para a área de transferência, mas o aplicativo não pode colar ou
ler de forma programática a partir da área de transferência. Essas restrições impedem que programas sem
confiança total leiam conteúdo copiado para a área de transferência por outro aplicativo. Se seu aplicativo exigir
acesso completo à área de transferência, mas você não tiver as permissões, você precisará elevar as permissões
para seu aplicativo. Para obter mais informações sobre como elevar permissões, consulte Administração de
política de segurança geral.

Manipulação de janela
A classe UIPermission também controla a permissão para executar a manipulação de janela e outras ações
relacionadas à interface do usuário, e o valor de enumeração associado UIPermissionWindow indica o nível de
acesso. A tabela a seguir mostra os níveis de permissão possíveis.
Por padrão, a zona da intranet local recebe AllWindows acesso e a zona da Internet recebe acesso
SafeTopLevelWindows. Isso significa que, na zona da Internet, o aplicativo pode executar a maioria das ações da
janela e da interface do usuário, mas a aparência da janela será modificada. A janela modificado exibe uma
notificação de balão quando executada pela primeira vez, contém texto de barra de título modificado e requer um
botão fechar na barra de título. A notificação de balão e a barra de título identificam o usuário do aplicativo que o
aplicativo está executando sob confiança parcial.

VA LO R DE UIP ERM ISSIO N W IN DO W DESC RIÇ Ã O

AllWindows Os usuários podem usar todas as janelas e os eventos de


entrada do usuário sem restrição.

SafeTopLevelWindows Os usuários podem usar somente janelas de nível superior


mais seguras e subjanelas mais seguras para desenhar e
podem usar apenas eventos de entrada do usuário para a
interface do usuário nessas janelas e subjanelas de nível
superior. Essas janelas mais seguras são claramente rotuladas
e têm restrições de tamanho mínimo e máximo. As restrições
impedem ataques de falsificação potencialmente prejudiciais,
como a imitação de telas de logon do sistema ou a área de
trabalho do sistema, e restringem o acesso programático a
janelas pai, APIs relacionadas ao foco e o uso do controle de
ToolTip,

SafeSubWindows Os usuários podem usar somente subwindows mais seguros


para desenhar e podem usar apenas eventos de entrada do
usuário para a interface do usuário dentro dessa subjanela.
Um controle exibido em um navegador é um exemplo de uma
subjanela mais segura.

NoWindows Os usuários não podem usar as janelas ou os eventos da


interface do usuário. Nenhuma interface do usuário pode ser
usada.

Cada nível de permissão identificado pela enumeração de UIPermissionWindow permite menos ações do que o
nível acima. As tabelas a seguir indicam as ações que são restritas pelo SafeTopLevelWindows e valores de
SafeSubWindows. Para obter permissões exatas que são necessárias para cada membro, consulte a referência
para esse membro na documentação da biblioteca de classes do .NET Framework.
SafeTopLevelWindows permissão restringe as ações listadas na tabela a seguir.

C O M P O N EN T E A Ç Õ ES REST RITA S

Application -Definindo a propriedade SafeTopLevelCaptionFormat.

Control -Obtendo a propriedade Parent.


-Definindo a propriedade Region .
-Chamando o método FindForm, Focus, FromChildHandle e
FromHandle, PreProcessMessage, ReflectMessageou
SetTopLevel.
-Chamar o método GetChildAtPoint se o controle retornado
não for um filho do controle de chamada.
-Modificar o foco de controle dentro de um controle de
contêiner.

Cursor -Definindo a propriedade Clip.


-Chamando o método Hide.
C O M P O N EN T E A Ç Õ ES REST RITA S

DataGrid -Chamando o método ProcessTabKey.

Form -Obtendo a propriedade ActiveForm ou MdiParent.


-Definindo a propriedade ControlBox, ShowInTaskbarou
TopMost.
-Definindo a propriedade Opacity abaixo de 50%.
-Definindo a propriedade WindowState como Minimized
programaticamente.
-Chamando o método Activate.
-Usando o None, FixedToolWindowe
SizableToolWindowFormBorderStyle valores de enumeração.

NotifyIcon -O uso do componente NotifyIcon é completamente restrito.

O valor de SafeSubWindows restringe as ações listadas na tabela a seguir, além das restrições colocadas pelo
valor de SafeTopLevelWindows.

C O M P O N EN T E A Ç Õ ES REST RITA S

CommonDialog -Mostrando uma caixa de diálogo derivada da classe


CommonDialog.

Control -Chamando o método CreateGraphics.


-Definindo a propriedade Cursor.

Cursor -Definindo a propriedade Current.

MessageBox -Chamando o método Show.

Hospedando controles de terceiros


Outro tipo de manipulação de janela pode ocorrer se seus formulários hospedarem controles de terceiros. Um
controle de terceiros é qualquer UserControl personalizado que você não tenha desenvolvido e compilado por
conta própria. Embora o cenário de hospedagem seja difícil de explorar, é teoricamente possível que um controle
de terceiros expanda sua superfície de renderização para cobrir toda a área do formulário. Esse controle poderia,
então, imitar uma caixa de diálogo crítica e solicitar informações como combinações de nome de usuário/senha
ou números de conta bancária de seus usuários.
Para limitar esse risco potencial, use controles de terceiros apenas de fornecedores nos quais você pode confiar.
Se você usar controles de terceiros que você baixou de uma fonte não verificável, recomendamos que você
examine o código-fonte em busca de possíveis explorações. Depois de verificar que a origem é não-mal-
intencionada, você deve compilar o assembly por conta própria para garantir que a origem corresponda ao
assembly.

Chamadas à API do Windows


Se o design do aplicativo exigir a chamada de uma função da API do Windows, você está acessando código não
gerenciado. Nesse caso, as ações do código para a janela ou sistema operacional não podem ser determinadas
quando você está trabalhando com valores ou chamadas da API do Windows. A classe SecurityPermission e o
valor de UnmanagedCode da enumeração SecurityPermissionFlag controlam o acesso ao código não gerenciado.
Um aplicativo pode acessar código não gerenciado somente quando ele recebe a permissão UnmanagedCode.
Por padrão, somente os aplicativos que estão sendo executados localmente podem chamar código não
gerenciado.
Alguns membros de Windows Forms fornecem acesso não gerenciado que requer a permissão UnmanagedCode.
A tabela a seguir lista os membros no namespace System.Windows.Forms que exigem a permissão. Para obter
mais informações sobre as permissões que são necessárias para um membro, consulte a documentação da
biblioteca de classes .NET Framework.

C O M P O N EN T E { 1>M EM B RO <1}

Application método de AddMessageFilter de -


- CurrentInputLanguage Propriedade
método de Exit de -
método de ExitThread de -
evento de ThreadException de -

CommonDialog método de HookProc de -


- OwnerWndProcmétodo
método de Reset de -
método de RunDialog de -

Control método de CreateParams de -


método de DefWndProc de -
método de DestroyHandle de -
método de WndProc de -

Help métodos de ShowHelp -


método de ShowHelpIndex de -

NativeWindow classe de NativeWindow de -

Screen método de FromHandle de -

SendKeys método de Send de -


método de SendWait de -

Se seu aplicativo não tiver permissão para chamar código não gerenciado, seu aplicativo deverá solicitar
UnmanagedCode permissão ou você deve considerar maneiras alternativas de implementar recursos; em muitos
casos, o Windows Forms fornece uma alternativa gerenciada para funções de API do Windows. Se nenhum meio
alternativo existir e o aplicativo precisar acessar o código não gerenciado, você precisará elevar as permissões
para o aplicativo.
A permissão para chamar código não gerenciado permite que um aplicativo execute a maioria de qualquer coisa.
Portanto, a permissão para chamar código não gerenciado só deve ser concedida para aplicativos provenientes de
uma fonte confiável. Como alternativa, dependendo do aplicativo, a parte da funcionalidade do aplicativo que faz
a chamada para código não gerenciado poderia ser opcional ou habilitada somente no ambiente de confiança
total. Para obter mais informações sobre permissões perigosas, consulte permissões perigosas e administração de
diretivas. Para obter mais informações sobre como elevar permissões, consulte Administração de política de
segurança geral.

Consulte também
Acesso mais seguro a arquivos e a dados nos Windows Forms
Impressão mais segura nos Windows Forms
Visão geral da segurança dos Windows Forms
Segurança do Windows Forms
Protegendo aplicativos ClickOnce
Implantação do ClickOnce para o Windows Forms
03/02/2020 • 3 minutes to read • Edit Online

Os tópicos a seguir descrevem o ClickOnce, uma tecnologia usada para implantar facilmente Windows Forms
aplicativos em computadores cliente.

Seções Relacionadas
Escolhendo uma estratégia de implantação do ClickOnce
Apresenta várias opções para implantar aplicativos ClickOnce.
Escolhendo uma estratégia de atualização do ClickOnce
Apresenta várias opções para atualizar aplicativos ClickOnce.
Protegendo aplicativos ClickOnce
Explica as implicações de segurança da implantação do ClickOnce.
Solução de problemas de implantações ClickOnce
Descreve vários problemas que podem ocorrer ao implantar aplicativos ClickOnce e documenta as mensagens de
erro de nível superior que o ClickOnce pode gerar.
O ClickOnce e as configurações de aplicativo
Descreve como a implantação do ClickOnce funciona com as configurações do aplicativo, que armazena as
configurações do aplicativo e do usuário para recuperação futura.
Visão geral da implantação de aplicativos confiáveis
Descreve um recurso do ClickOnce que permite que aplicativos confiáveis sejam executados com um nível mais
alto de permissão em computadores cliente.
ClickOnce e Authenticode
Descreve como a tecnologia Authenticode é usada na implantação de aplicativos confiáveis.
Passo a passo: implantando um aplicativo ClickOnce manualmente
Demonstra o uso de ferramentas de linha de comando e SDK para implantar um aplicativo ClickOnce sem usar o
Visual Studio.
Como adicionar um fornecedor confiável a um computador cliente para aplicativos ClickOnce
Demonstra a configuração única de computadores cliente necessários para a implantação de aplicativos confiáveis.
Como especificar um local alternativo para atualizações da implantação
Demonstra a configuração de um aplicativo ClickOnce, usando ferramentas do SDK, para verificar um local
diferente para novas versões de um aplicativo.
Passo a passo: baixando assemblies sob demanda com a API de implantação do ClickOnce
Demonstra o uso de chamadas de API para recuperar um assembly na primeira vez que seu aplicativo tenta
carregá-lo.
Como recuperar informações de cadeia de caracteres de consulta em um aplicativo ClickOnce online
Demonstra a recuperação de parâmetros da URL usada para executar um aplicativo ClickOnce.
Visão geral do cache do ClickOnce
Descreve o cache usado para armazenar aplicativos ClickOnce no computador local.
Acessando dados locais e remotos em aplicativos ClickOnce
Descreve como acessar arquivos de dados locais e fontes de dados remotas de um aplicativo ClickOnce.
Como incluir um arquivo de dados em um aplicativo ClickOnce
Demonstra como marcar um arquivo para que ele esteja disponível no diretório de dados do ClickOnce.

Consulte também
Visão Geral das Configurações do Aplicativo
Publicando aplicativos ClickOnce
Compilando aplicativos ClickOnce por meio da linha de comando
Depurando aplicativos ClickOnce que usam System.Deployment.Application
Implantando componentes do COM com o ClickOnce
Como publicar um aplicativo ClickOnce usando o Assistente de Publicação
Melhorias de acessibilidade nos controles do
Windows Forms para .NET Core 3.0
21/04/2020 • 9 minutes to read • Edit Online

O Windows Forms continua a melhorar a forma como funciona com as tecnologias de acessibilidade para melhor
apoiar os clientes do Windows Forms. essas melhorias incluem as seguintes alterações:
Mudanças em várias áreas de interação com aplicativos clientes de acessibilidade, incluindo o Narrator.
Alterações na hierarquia acessível (melhora da navegação por meio da árvore de automação de interface do
usuário).
Alterações na navegação do teclado.

IMPORTANT
As alterações de acessibilidade feitas no Quadro .NET 4.7.1 até o .NET Framework 4.8 estão incluídas no .NET Core 3.0 ou
superior, e são habilitadas por padrão. O .NET Framework suportava switches de compatibilidade que permitiam que os
aplicativos optassem por não usar o novo comportamento de acessibilidade. Por outro lado, o .NET Core não suporta essas
configurações e não permite que os aplicativos optem pelo comportamento de acessibilidade.

A partir do .NET Core 3.0, os aplicativos do Windows Forms se beneficiam de todos os novos recursos de
acessibilidade (introduzidos no .NET Framework 4.7.1 - 4.8) sem configuração adicional.

Suporte à acessibilidade do ListBox


As seguintes alterações se aplicam ao ListBox controle:
Suporte de automação de ListBox iu de ui habilitado para controle.
Melhor ListBox suporte à acessibilidade ScrollItemPattern adicionando os ListBox itens e melhorando o
evento de acessibilidade de elevação e manuseio e navegação do Narrador através dos itens (a navegação de
bloqueio de tampas não é correta e não joga a navegação fora do controle involuntariamente).

Suporte à acessibilidade do CheckedListBox


As seguintes alterações se aplicam ao CheckedListBox controle:
Limites CheckedListBox corrigidos fornecidos por propriedades de acessibilidade para entradas.
Melhora ListBox geral CheckedListBox e acessibilidade: valores de propriedade corrigidos e modelo de evento.

Suporte à acessibilidade do ComboBox


As seguintes alterações se aplicam ao ComboBox controle:
Atualizei o ComboBox processo de obtenção de objetos de acessibilidade de itens para permitir a geração de IDs
para GetHashCode itens em vez de obter códigos hash de itens, o que pode ser inseguro no caso de a função
ser substituída.

Suporte à acessibilidade do DataGridView


As seguintes alterações se aplicam ao DataGridView controle:
Corrigido DataGridView.Bounds fornecido pelas propriedades de acessibilidade para colunas, linhas, células e
cabeçalhos correspondentes, melhor desempenho do cálculo retângulo delimitador. Todos os limites de
acessibilidade são representados corretamente levando em conta os limites de todo o controle, juntamente com
sua porta de visualização.
Valor Value.IsReadOnly de propriedade corrigido fornecendo aplicações acessíveis ao cliente. A propriedade
agora IsReadOnly mostra o status correto para as células.
Corrigimos o CellParsing problema com a elevação do evento para a primeira mudança de célula. O valor
celular pode ser alterado DataGridView sem problemas, incluindo a primeira interação de controle.
Contraste DataGridView de cor de fundo melhorado ao usar temas do Windows High Contrast. Alterou
DataGridView a cor de volta padrão ao usar os temas HC#1, HC#2 e HC Black.

Suporte à acessibilidade do PropertyGrid


As seguintes alterações se aplicam ao PropertyGrid controle:
Corrigido PropertyGrid.Bounds fornecido por propriedades de acessibilidade para entradas de grade, melhor
desempenho do cálculo retângulo delimitador. Por enquanto, todos os limites de acessibilidade são
representados corretamente levando em conta os limites de todo o controle, juntamente com sua porta de
visão.
Corrigido nomes acessíveis e descrições de subcontroles para não incluir nomes de tipo de controle e para
evitar anúncio duplo para nomes de tipo de controle.

Suporte à acessibilidade ToolStrip


As seguintes alterações se aplicam ao ToolStrip controle:
Navegação melhorada ToolStrip através MenuStrip , StatusStrip e itens. Navegação ToolStrip corrigida e
MenuStrip de guia de turno, retroceder os itens do menu quando a seta para cima da guia de turno é
pressionada, que navega até o elemento do menu inferior.
Navegação MenuStrip acessível melhorada, menu corrigido tipos de controle acessíveis para submenus para
fazer submenus do tipo 'Menu' em vez de 'MenuItem'.

PrintPreviewControl e PrintPreviewSuporteSuporte acessibilidade de


diálogo
As seguintes alterações se aplicam aos controles de impressão:
Navegação acessível melhorada (incluindo navegação narradora) através de itens de menu.
Melhorados temas de Alto Contraste suportam e tornaram o elemento de controle mais contrastado.

Suporte à acessibilidade StringCollectionEditor


O designer do Windows Forms agora usa o editor de coleção de strings com suporte de acessibilidade aprimorado.

Suporte de acessibilidade monthcalendar (disponível em .NET Core 3.1)


As seguintes alterações se aplicam ao MonthCalendar controle:
Adicionou provedores de MonthCalendar servidores de automação de ui para controlar, adicionou o padrão de
grade de automação de ui e provedores de padrão de tabela.
Alterou o tipo de controle acessível à tabela para o tipo de MonthCalendar controle acessível ao calendário,
MonthCalendar exceto no caso em que o controle possui um controle de rótulo anterior que define o nome
acessível ao controle, neste caso específico, o tipo de controle acessível torna-se tabela.
Anúncio aprimorado da data MonthCalendar selecionada para controle.
Suporte MonthCalendar de controle aprimorado para leitores de tela e outras ferramentas de acessibilidade.
Neste momento, os usuários podem navegar pelos elementos de controle e interagir com esses elementos
usando a entrada somente para teclado. Com o Narrador, use caps + teclas de seta para navegação através dos
elementos de controle e CAPS + Enter para invocar a ação padrão do elemento.
Navegação melhorada da MonthCalendar tecla de seta através de elementos infantis com um retângulo focal:
retângulo de foco azul para Narrador.
Acessibilidade aprimorada para ação de MonthCalendar teste de MonthCalendar impacto para elementos de
controle para permitir obter elementos acessíveis à criança por coordenadas fornecidas.

Acessibilidade ToolTips (disponível no .NET Core 3.1)


Adicionada capacidade de anunciar um texto de dica de ferramenta por aplicativos de leitor de tela, como NVDA
e Narrator. O aplicativo do leitor de tela agora pode anunciar o texto da dica de ferramenta do teclado ou mouse
de qualquer controle do Windows Forms configurado para mostrar dicas de ferramentas.

Suporte à automação de IU para DataGridView, PropertyGrid, ListBox,


ComboBox, ToolStrip e outros controles
O suporte à automação de ia é habilitado para controles em tempo de execução, mas não é usado durante o tempo
de projeto. Para obter uma visão geral de automação da interface do usuário, confira a Visão geral de automação
da interface do usuário.

Confira também
Práticas recomendadas de acessibilidade.
Como acessar coleções indexadas por chave no
Windows Forms
03/02/2020 • 2 minutes to read • Edit Online

Você pode acessar itens de coleção individuais por chave. Essa funcionalidade foi adicionada a muitas
classes de coleção que normalmente são usadas por aplicativos dos Windows Forms. A lista a seguir exibe
algumas das classes de coleção que têm coleções acessíveis por chave:
ListView.ListViewItemCollection
ListViewItem.ListViewSubItemCollection
Control.ControlCollection
TabControl.TabPageCollection
TreeNodeCollection
Normalmente, a chave associada a um item em uma coleção é o nome do item. Os procedimentos a seguir
mostram como usar classes de coleção para executar tarefas comuns.
Para localizar e colocar em foco um controle aninhado em uma coleção de controles
Use os métodos Find e Focus para especificar o nome do controle para localizar e dar o foco.

OrderForm OrderForm1 = new OrderForm();


OrderForm1.Show();
OrderForm1.Controls.Find("textBox1", true)[0].Focus();

Dim OrderForm1 As New OrderForm()


OrderForm1.Show()
OrderForm1.Controls.Find("textBox1", True)(0).Focus()

Para acessar uma imagem em uma coleção de imagens


Use a propriedade Item[Int32] para especificar o nome da imagem que você deseja acessar.

this.BackgroundImage = imageList1.Images["logo.gif"];

Me.BackgroundImage = imageList1.Images("logo.gif")

Para definir uma página da guia como a guia selecionada


Use a propriedade SelectedTab junto com a propriedade Item[String] para especificar o nome da página da
guia a ser definida como a guia selecionada.

tabControl1.SelectedTab = tabControl1.TabPages["shippingOptions"];

tabControl1.SelectedTab = tabControl1.TabPages("shippingOptions")
Consulte também
Introdução ao Windows Forms
Como adicionar ou remover imagens com o componente ImageList dos Windows Forms
Aprimorando aplicativos do Windows Forms
03/02/2020 • 3 minutes to read • Edit Online

O Windows Forms contém muitos recursos que você pode usar para aprimorar seus aplicativos do Windows para
atender às necessidades específicas dos seus usuários. Os tópicos a seguir descrevem esses recursos e como usá-
los.

Nesta seção
Elementos Gráficos e Desenho nos Windows Forms
Contém links para tópicos que descrevem e mostram como usar a interface gráfica nos Windows Forms.
Configurações de aplicativo para Windows Forms.
Contém links para tópicos que descrevem e mostram como usar o recurso de Configurações de Aplicativo .
Suporte à impressão nos Windows Forms
Contém links para tópicos que descrevem e mostram como imprimir arquivos de Aplicativos dos Windows Forms.
Operações do Tipo "Arrastar e Soltar" e Suporte à Área de Transferência
Contém links para tópicos que descrevem e mostram como usar o recurso do tipo "arrastar e soltar" e a área de
transferência nos Windows Forms.
Rede em Aplicativos dos Windows Forms
Contém links para tópicos que descrevem e mostram como usar redes nos Windows Forms.
Globalizando aplicativos Windows Forms
Contém links para tópicos que mostram como globalizar aplicativos dos Windows Forms.
Windows Forms e aplicativos não gerenciados
Contém links para tópicos que descrevem e mostram como acessar componentes COM de Aplicativos do
Windows Form.
Informações do Sistema e o Windows Forms
Descreve como usar informações do sistema nos Windows Forms.
Gerenciamento de Energia nos Windows Forms
Descreve como gerenciar o uso de energia em Aplicativos dos Windows Forms.
Herança Visual dos Windows Forms
Descreve como herdar de um formulário base.
Aplicativos da interface MDI (Interface de Vários Documentos)
Descreve como criar aplicativos de interface MDI (Interface de Vários Documentos).
Integrando a Ajuda do Usuário nos Windows Forms
Descreve como integrar a Ajuda do usuário aos seus aplicativos.
Acessibilidade dos Windows Forms
Descreve como disponibilizar seus aplicativos para uma ampla variedade de usuários.
Usando Controles do WPF
Descreve como usar controles WPF em seus aplicativos dos Windows Forms.

Seções Relacionadas
Sistemas de Ajuda em Aplicativos dos Windows Forms
Contém links para tópicos que descrevem e mostram como fornecer Ajuda do usuário em Aplicativos dos
Windows Forms.
Introdução ao Windows Forms
Contém links para tópicos que descrevem como usar os recursos básicos dos Windows Forms.

Você também pode gostar