Pesquisar

quinta-feira, 11 de março de 2021

O que significa a propriedade Handle que alguns componentes possui?

    Primeiro vamos entender o que é um Handle no Windows.

    Handle é um índice atribuído para cada componente que o SO pode manipula, por exemplo, uma janela, um arquivo, um driver, uma porta seria ou USB, alguns componentes de tecla, absolutamente TUDO que o SO pode manipular possui seu índice (Handle), que nada mais é do que um inteiro de 32 ou 64 bits (dependendo da arquitetura do SO).

    O Handle sozinho nada pode fazer sem a utilização da API do SO.

    Muito bem, agora definido o que é um Handle, vamos definir algumas coisas sobre a VCL.

    Já sabemos o que é a VCL, é a biblioteca de componentes visuais do Delphi. Na hierarquia dos componentes temos a seguinte estrutura:

 

    TObject ->  TPersistent -> TComponent -> TControl

 

    Todos os componentes da VCL possuem TControl em sua herança, então podemos assumir que todos os componentes visuais primordialmente são herdados de TControl.

    Muito bem, neste ponto, o que deve ficar bem claro é que cada componente que precise ser desenhado na tela deve herdar de TControl (o que não nos impede de herdar de algum componente mais a frente da hierarquia, como um TEdit, TButton ou TLabel).

    No entanto, a VCL neste ponto possui dois grandes troncos de herança:

    TGraphicControl e TWinControl

    Como mostra a imagem abaixo:



    Como vocês podem perceber, o tronco TWinControl possui os componentes mais utilizados, TButton, TEdit, TListBox, etc...
    O TWinControl representam os componentes que são criados e podem ser manipulados pelo SO (Windows). Os componentes TButton, TEdit e outros são de criação exclusiva do SO, e como esses componentes podem ser manipulados (criados e destruídos) pelo SO, eles devem possuir um Handle.

    Mas ainda existem componentes que não possuem Handle, como por exemplo o TImage e TLabel, isso ocorre porque a VCL possui o tronco chamado TGraphicControl que são componentes criados especificamente por ela, o SO não tem como interferir no funcionamento (manipulador de eventos nem de destruição e muito menos criação) destes componentes.

    Inclusive, a melhor maneira de entender a utilização do handle no delphi, é entendendo como funciona o sistema de mensageria do Windows.

    Tudo no Windows é notificado através de mensagens, é através de mensagens que um componentes da VCL sabe que foi clicado, que alguma tecla foi pressionada, ou se o componente deve ser ou não redesenhado na tela.

    Por exemplo, se queremos simular um click em um TButton, utilizamos a função da API do windows chamada SendMessage (também podemos utilizar a PostMessage, mas entrarei nisso com mais detalhes em outra postagem).

    Ex: Queremos que determinado componente receba a mensagem de passar para o próximo controle, sem que a gente tecle <Tab> no teclado, podemos enviar uma mensagem pra isso.

    SendMessage(Edit1.handle, WM_NEXTDLGCTL, 0, 0);

    Como vocês perceberam, dizemos ao SO que  do Edti1, ele colocar o foco no próximo componente, isso é bem comum quando queremos trocar o <Tab> por <Enter> em um edit.

    E é neste ponto que vemos a importância do Handle, como se nota na função, em vez de passarmos o componente, passamos apenas o Handle do mesmo e junto com ele, a mensagem de pular para o próximo controle.

    Agora vamos supor que tenhamos que mandar uma mensagem de redesenho para um TLabel. Como vimos anteriormente, este é um componente herdado de TGraphControl, portanto ele não é controlado pelo SO, e sim pela VCL, então como mandamos uma msg pra ele? Simples, todos os componentes TControl (TWinControl e TGraphControl) possui uma função chamada Perform, onde simulamos um envio de uma msg para eles.

    Ex:

        Label.Perform(WM_PAINT, 0, 0);

    Desse modo dizemos a VCL que queremos que o componente deve ser redesenhado em seu DC (Device Context e não os heróis dos filmes :) ).


    Espero ter ajudado um pouco a todos a entender um pouco mais sobre o funcionamento do Handle.


    Abraço a todos!