Form.Show vs Form.ShowModal
Sim, existe diferença. Vamos nos aprofundar um pouco mais e destacar a principal diferente entre os dois.
Você sabe exatamente o que acontece por trás do ShowModal que o torna diferente do Show? Inicialmente temos os tipos de cada método que diferem entre si. O ShowModal é uma function que retorna um integer e o Show, por sua vez, é uma procedure, logo, não conta com um resultado.
Ao criarmos um novo formulário partindo do menu “File -> New -> VCL Form” o RAD Studio cria um novo formulário com base em um template. Esse novo formulário em branco herda da classe TForm. Essa classe, a TForm, herda de uma outra classe chamada TCustomForm.
O método Show está implementado na classe TCustomForm
1 2 3 4 5 |
procedure TCustomForm.Show; begin Visible := True; BringToFront; end; |
Podemos invocar o método Show graças ao recurso de herança oferecido pela Programação Orientada a Objetos. O Show contém uma implementação bastante simples. Ele apenas altera a visibilidade do formulário para true e invoca o método BringToFront para dar o foco da aplicação ao recém “visível” formulário.
O .Show não é tão Show assim
Uma das desvantagens do Form.Show é que o formulário “principal” (o que deu origem ao novo form) ainda pode receber o foco do usuário, e isso nem sempre é interessante. Em uma típica aplicação de vendas, por exemplo, quando vamos adicionar um novo produto na venda, não é nada legal ter o usuário alterando dos dados do endereço de entrega enquanto a tela de produtos está aberta e em edição, não é?
Sendo assim, o Show é fortemente indicado em aplicações onde múltiplas janelas precisam ou podem ter o foco do usuário alternado a qualquer momento e sem restrições. Um excelente exemplo para o uso é o caso de um bate-papo. Lembram do MSN? Hehe…
O método ShowModal está implementado na classe TCustomForm
Assim como o Show, o ShowModal também está implementado na TCustomForm. Ligeiramente maior (muito maior, muito mesmo) que a implementação do Show, o ShowModal oferece um maior controle do foco do usuário.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//code... try Show; try SendMessage(Handle, CM_ACTIVATE, 0, 0); ModalResult := 0; repeat Application.HandleMessage; if Application.Terminated then ModalResult := mrCancel else if ModalResult <> 0 then CloseModal; until ModalResult <> 0; Result := ModalResult; SendMessage(Handle, CM_DEACTIVATE, 0, 0); if GetActiveWindow <> Handle then ActiveWindow := 0; finally Hide; end; finally //code... end; //code... |
Destaquei esse trecho da implementação do ShowModal pois é aqui que o bicho pega. Logo na primeira instrução temos o método Show sendo invocado seguido de um SendMessage, que é a forma de “comunicação por baixo dos panos” entre as aplicações e o sistema operacional.
1 2 3 4 |
ModalResult := 0 repeat ... until ModalResult <> 0; |
Antes de iniciar um loop com o repeat, a propriedade ModalResult é definida como 0 e (ModalResult = 0) é a condição para o loop manter-se vivo. Esse loop é tão rápido que acaba sendo imperceptível para nós humanos. A grande “jogada” está no Application.HandleMessage que é onde a aplicação, digamos, conversa com o sistema operacional e captura as interações do usuário com a aplicação, e uma delas é quando a propriedade ModalResult tem o seu valor atualizado.
Em resumo, o ShowModal executa o Show e, através do repeat until, cria um loop infinito que mantém o foco da janela ativo enquanto o usuário não toma uma “ação decisiva” em relação ao que lhe é apresentado no novo formulário exibido, impedindo assim, que ele possa interagir com o formulário anterior. Um excelente exemplo de janelas assim é o caso de uma confirmação ou uma tela para selecionar uma lista produtos, por exemplo.
Nem tudo são flores
Manter o foco da janela sempre ativo é a vida e a morte do guerreiro ShowModal. Há quem não aceite muito bem essa característica entregue pelo método, e por isso é sempre importante levar em consideração a real necessidade do seu uso. Eu uso sempre, haha.
Quem é o ModalResult?
Ele é só um Integer.
Mesmo sendo um simples integer, o ModalResult carrega um grande significado semântico para quem está codificando ou lendo o código de alguém. Utilizando a ajuda do TModalResult podemos aplicar um comportamento diferenciado com base nas escolhas do usuário. Isso vai ser assunto para o nosso próximo artigo, onde eu pretendo abordar as diversas aplicações do TModalResult.