C# – Trocando a navegação dos controles Windows do TAB para o ENTER

Essa é um pouco velha, mas tão eminente quanto a necessidade de migração de sistemas legados.

Poderia citar inúmeros motivos que levam a essa “cultura” de utilização de sistemas comerciais, mas vou enfatizar alguns:

  • Legado de sistemas orientados a caracter, geralmente feitos em CLIPPER
  • Legado de linguagens de quarta-geração, ou pelo daqueles aplicativos que o tentam ser, como Access e FoxPro
  • Facilidade na utlização do teclado numérico, já que nele além das teclas númericas há também o ENTER facilitando o acesso

O fato é que, é quase certo que os usuários do sistema antigo solicitarão que a navegação entre campos seja trocada do tradicional TAB pelo ENTER.

Para fazer isso em C# (e qualquer outra linguagem .NET, guardadas as devidas conversões), primeiramente é preciso habilitar a propriedade KeyPreview do Formulário principal para que o controle esteja habilitado a interceptar as teclas digitadas.

Depois, para trocar a navegação, bastaria interceptar o evento KeyDown e fazer o tratamento. Mas para fazer um tratamento mais completo, vamos inteceptar o KeyDown para suprimir o ENTER e o KeyUp para trocar a tecla enviada. O código abaixo faz isso:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/// inibe a ação do Enter para evitar o comportamento de
/// Accept em alguns casos
private void _ctrl_KeyDown(object sender, KeyEventArgs e)
{
	if (e.KeyCode == Keys.Enter)
		e.SuppressKeyPress = true;
}
/// adiciona a tratativa à tecla Enter e envia o TAB para
/// promover a navegação
private void _ctrl_KeyUp(object sender, KeyEventArgs e)
{
	if (e.KeyCode == Keys.Enter)
	{
		// SendKeys.Send("{TAB}");
		_ctrl.FindForm().SelectNextControl(_ctrl, true, true, true, false);
	}
}

Percebam que no KeyUp há uma parte do código comentada (SendKeys.Send(“{TAB}”);) que faria com que a tecla TAB fosse acionada no lugar do ENTER, porém, é mais elegante usar o método SelectNextControl do objeto Form, que faz a ação sem a necessidade de simular um comportamento, o que em alguns casos pode causar um comportamento não desejado.

Isso resolve o problema. Para tentar ajudar um pouco mais, disponilizo abaixo um método mais completo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/// <summary>
/// Adiciona o comportamento de navegação através da tecla Enter,
/// da mesma forma como o TAB
/// </summary>
/// <param name="_ctrl">O controle pai que contém os controles em que
/// serão adicionados os eventos</param>
public static void TrocaTABporEnter(Control _ctrl)
{
	if (_ctrl.HasChildren)
	{
		foreach (Control _child in _ctrl.Controls)
		{
			if (_ctrl.HasChildren)
				TrocaTABporEnter(_child);
		}
	}
	else
	{
		///Não funciona para Numeric Up Down
		if (_ctrl is TextBox ||
		_ctrl is MaskedTextBox ||
		_ctrl is ListBox ||
		_ctrl is CheckBox ||
		_ctrl is TabPage ||
		_ctrl is DateTimePicker ||
		_ctrl is ComboBox)
		{
			/// inibe a ação do Enter para evitar o comportamento de
			/// Accept em alguns casos
			_ctrl.KeyDown += delegate(object sender, KeyEventArgs e)
			{
				if (e.KeyCode == Keys.Enter)
					e.SuppressKeyPress = true;
			};
			/// adiciona a tratativa à tecla Enter e envia o TAB para
			/// promover a navegação
			_ctrl.KeyUp += delegate(object sender, KeyEventArgs e)
			{
				if (e.KeyCode == Keys.Enter)
				{
					// SendKeys.Send("{TAB}");
					_ctrl.FindForm().SelectNextControl(_ctrl, true, true, true, false);
				}
			};
		}
	}
}

Este método pode ser chamado em qualquer momento do seu código e faz com que todos os controles filhos do controle passado por parâmetro adiquiram o comportamento, sem a necessidade de mapear o evento para todos os controles.

Como comentado, o código não funciona com alguns controles, em particular o NumericUpDown. Para que isso seja possível, é preciso sobrescrever alguns métodos da classe, mas isso já outra história.

Abraços

Tomás Vásquez
www.tomasvasquez.com.br

Comentários

comentários