significa que o cursor ja esta em posicao para substituir o proximo caracter.*/ break; default: break; } break; case 1: /*Cursor na posicao um. Significa que o caracter a ser substituido e o segundo.*/ if (((TextBox)sender).Text[0] == '2') switch (e.KeyChar) { /*No caso de o primeiro caracter ser '2', limitados o segundo entre 0 e 3.*/ case '0': case '1': case '2': case '3': ((TextBox)sender).SelectedText = e.KeyChar.ToString(); /*Aqui e necessario incrementar a SelectionStart, pois o cursor esta em frente ao ':' da mascara, o que faria com que ele fosse o substituido na proxima digitacao, e isto nao deve acontecer.*/ ((TextBox)sender).SelectionStart++; break; default: break; } /*Se o primeiro caracter for diferente de '2' vai para default, que e para inserir caracteres de 0 a 9. Muitas pessoas me trucidariam por causa do 'goto'. Vou escrever um pouco sobre isso depois.*/ else goto default; break; case 3: switch (e.KeyChar) { /*Limitado para aceitar de 0 a 5.*/ case '0': case '1': case '2': case '3': case '4': case '5': ((TextBox)sender).SelectedText = e.KeyChar.ToString(); break; default: break; } break; case 5: /*Se o usuario por acaso colocar o cursor na ultima posicao da TextBox, o caracter substituido sera o primeiro.*/ ((TextBox)sender).SelectionStart = 0; ((TextBox)sender).SelectionLength = 1; goto case 0; default: switch (e.KeyChar) { /*Por default a TextBox aceitara caracteres de 0 a 9. Isso acontecera no segundo caracter, quando ele for diferente de dois, e no quinto caracter. Resolvi deixar essa parte no default, ja que outras posicoes nao deverao existir na TextBox com mascara.*/ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ((TextBox)sender).SelectedText = e.KeyChar.ToString(); /*Se a SelectionStart for igual a 2 significa que o cursor esta na frente do ':', por isso ela deve ser incrementada, impedindo que o ':' seja substituido. Se ela for igual a 5, significa que chegou no final da mascara, entao ela volta para o comeco.*/ if (((TextBox)sender).SelectionStart == 2) ((TextBox)sender).SelectionStart++; else if (((TextBox)sender).SelectionStart == 5) ((TextBox)sender).SelectionStart = 0; break; default: break; } break; } /*Aqui e uma questao visual. Pode parecer repetitivo executar essa instrucao no inicio e no fim do evento, mas la no inicio ela era uma questao de seguranca. Aqui o que ela fara e deixar o proximo caracter selecionado, deixando o usuario saber qual o caracter que ele esta prestes a substituir na proxima digitacao.*/ ((TextBox)sender).SelectionLength = 1; } private void MascaraHorario_KeyDown(object sender KeyEventArgs e) { e.Handled = true; } }}Bom. Nao consigo imaginar muito mais o que explicar.A maioria das explicacoes eu preferi colocar no meio do codigo como comentarios.Depois de feito o codigo do evento e preciso associar ele ao(s) controle(s). Nao vou entrar nesses detalhes porque acredito que qualquer um que tenha chegado ao ponto de ler o post ate aqui ja sabe como isso funciona.Uma observacao importante e o fato de eu estar usando o object sender do evento.Esse object sender e uma referencia ao controle que disparou o evento.Usar o sender evita que eu tenha que criar esse evento para varias TextBox, caso eu tenha mais