Artigo Clube Delphi Edição 10 - Invisíveis e Transparentes

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (0)  (0)

Artigo da Revista Clube Delphi Edição 10.

Esse artigo faz parte da revista Clube Delphi edição 10. Clique aqui para ler todos os artigos desta edição



Atenção: por essa edição ser muito antiga não há arquivo PDF para download. Os artigos dessa edição estão disponíveis somente através do formato HTML. 

 

Invisíveis e Transparentes

Fabio fala de seu guru e faz mágica com os Forms !

 

Peter Norton foi o guru de muitos programadores de minha geração. Com suas obras especializadas, contribuiu para formar muitos de meus conceitos, alguns renovados com as novas tecnologias, outros resistentes ao tempo.

         A chuva de obras publicadas em seu nome, me deixaram confuso, será que foi ele quem realmente escreveu todos? Baseado em assuntos bem variados, eu comecei a fazer algumas contas: Pelo menos 1 ano para formar conceitos sólidos sobre o assunto e mais seis meses no mínimo para escrever um livro com 250 a 300 páginas. Seria impossível comparado ao número de títulos. Já seus aplicativos, temos certeza que foi uma grande equipe.

         Com a revolução visual pós Windows 95, muitos aplicativos começaram a chamar a atenção pelas telas de splash (tela inicial enquanto o programa é carregado). O Norton Crash Guard, com seu splash em forma de escudo me fascinou. Pensei: Tenho que imitá-lo!

         A forma mais simples seria arrumar um bitmap com fundo transparente, na forma desejada, e colocar o form transparente também alterando sua propriedade brush, e finalmente esconder o caption do form.

(* Coloca o Form transparente *)

  Form1.Brush.Style := bsclear;

         Trabalhoso, mas mais trabalhoso ainda é fazer isto utilizando funções APIs. Porém, este é o nosso desafio!

         O problema do código acima é que ele não atualiza a área transparente, e não adianta dar um simples Invalidate em um evento qualquer - chega de "gambiarras", vamos escrever uma solução definitiva. O efeito do form transparente é executado pelo princípio de Regiões. Primeiro crie uma região que cerca o form inteiro. Então, ache a área de cliente da forma (Client vs. non-Client). Após isto basta mostrar ou esconder o form, preocupando-se com o refresh da parte invisível, ou seja, atualizar o fundo em caso de você mover o form. Vamos para a prática !

 

Var

  Form1: TForm1;

  FullRgn, ClientRgn, CtlRgn : THandle;

procedure TForm1.DoInvisible;

var

  AControl : TControl;

  A, Margin, X, Y, CtlX, CtlY : Integer;

begin

  Margin := ( Width - ClientWidth ) div 2;

  //Pegamos a região do form

  FullRgn := CreateRectRgn(0, 0, Width, Height);

  //Procuramos a área Client

  X := Margin;

  Y := Height - ClientHeight - Margin;

  ClientRgn := CreateRectRgn( X, Y, X + ClientWidth, Y + ClientHeight );

  CombineRgn( FullRgn, FullRgn, ClientRgn, RGN_DIFF );

  //Agora procuramos nossos controles no form

 for A := 0 to ControlCount - 1 do begin

    AControl := Controls[A];

    if ( AControl is TWinControl ) or ( AControl is TGraphicControl )

        then with AControl do begin

      if Visible then begin

        CtlX := X + Left;

        CtlY := Y + Top;

        CtlRgn := CreateRectRgn( CtlX, CtlY, CtlX + Width, CtlY + Height );

        CombineRgn( FullRgn, FullRgn, CtlRgn, RGN_OR );

      end;

    end;

  end;

  //Depois de todas as regiões registradas, executamos o efeito

  SetWindowRgn(Handle, FullRgn, TRUE);

end;

 

Obs.: Primeiro crie a rotina para esconder o form, aproveite e declare as variáveis locais ao form (não a procedure, pois utilizaremos elas em outros procedimentos também).

         Apesar de a primeira vista parecer confuso, uma análise mais calma demonstra claramente o passo a passo do código, Aonde procuramos delimitar as regiões do form, sua área total, sua área cliente e a área preenchida com seus controles.

         Como todo veneno tem seu antídoto, vamos agora desfazer, torna-lo visível:

 

procedure TForm1.DoVisible;

begin

// devolve a visibilidade para a região

FullRgn := CreateRectRgn(0, 0, Width, Height);

CombineRgn(FullRgn, FullRgn, FullRgn, RGN_COPY);

SetWindowRgn(Handle, FullRgn, TRUE);

end;

        

         Bem mais simples, né? Talvez. Na verdade precisamos entender o vilão dos dois procedimentos, a função API CombineRgn e seus parâmetros.

A função CombineRgn, combina duas regiões e retorna seu valor numa terceira região. Veja a sintaxe:

 

Int CombineRgn(

    HRGN hrgnDest, // handle to destination            region

    HRGN hrgnSrc1,   // handle to source               region

    HRGN hrgnSrc2,   // handle to source

   region

    int fnCombineMode // region combining

    mode

   );

 

         Os três primeiros parâmetros são intuitivos, o macete está no quarto parâmetro, que possui uma lista de opções e responsável diretamente pelo efeito desejado, veja algumas destas opções abaixo:

RGN_AND                  Cria a interseção das duas regiões combinadas.

RGN_COPY             Cria uma cópia da região identificada por hrgnSrc1.

RGN_DIFF               Combina as partes de hrgnSrc1 sem a parte de hrgnSrc2.

RGN_OR                  Cria a união de duas regiões combinadas.

RGN_XOR                Cria a união de duas regiões combinadas com exceção de qualquer área sobrepondo-a.

        

         Revelamos o motivo da mágica, as demais APIs utilizadas podem ter uma explicação mais breve:

 

CreateRectRgn       Cria uma região retangular.

SetWindowRgn       Desenha, aplica uma região em uma janela.

        

         Aproveitarei para fazer meu comercial. Precisando de maiores explicações sobre estas ou outras APIs, basta mandar um email para:  Visual Books Editora e encomendar meu novo livro, entitulado "Delphi, API's e Sockets - A caixa preta das tecnologias".

         Voltando ao nosso problema, ainda não terminamos, precisamos criar um botão para mostrar e esconder o form. Ao finalizar nosso aplicativo, devemos destruir as regiões criadas (que são consideradas objetos).

 

procedure TForm1.FormDestroy(Sender: TObject);

begin

  DeleteObject(ClientRgn);

  DeleteObject(FullRgn);

  DeleteObject(CtlRgn);

end;

procedure TForm1.Button1Click(Sender: TObject);

begin

  if Button1.Caption = 'Mostra Form' then begin

  DoVisible;

  Button1.Caption := 'Esconde Form';

end

else begin

   DoInvisible;

   Button1.Caption := 'Mostra Form';

end;

end;

 

         Para finalizar nosso projeto com qualidade, inclua também um procedimento para o evento FormResize:

 

procedure TForm1.FormResize(Sender: TObject);

begin

 if Button1.Caption = 'Mostra Form' then

    DoInvisible

  else

    DoVisible;

end;

 

         Vamos agora testar sua lógica de programador: Porque o primeiro código (...Brush.Style := bsClear;) não atualiza a área invisível de nosso form quando ele é movido? A resposta é: Window Region!!!

         Vou te contar uma coisa impressionante, quando o a área Client do form está invisível, e você tentar clicar nela com o mouse, ela simplesmente não existe e o foco passa para o aplicativo que esta por baixo, ou seja, ela esta invisível aos olhos e ao toque - Gostei!

 

Fabio Camara é coordenador de projetos da Stefanini Consultoria, autor do livro “Banco de Dados com Delphi” e sócio fundador da Delphi Bahia

 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?