Melhorando a aparência de imagens desabilitas no TImageList

 

Uma imagem pode explicar melhor o sentido deste post, veja como a aparência dos botões desabilitados da segunda imagem são melhores que da primeira imagem.

Desabled Images

Para deixar as imagens deste jeito eu usei 2 experts, primeiro o expert IDE Gradient para definir a aparência da barra de ferramentas com ou sem gradiente e o expert Delphi Nice Toolbar para melhorar a aparência das imagens.

Mas que tal se aplicar isto para todos os seus programas, além da IDE do Delphi? Para isto é necessário reimplementar parte do código do TImageList, então eu criei um QC para isto no Quality Central:

Report No: 80997            Status: Reported
Better look for TImageList disabled Images
http://qc.codegear.com/wc/qcmain.aspx?d=80997
QCWIN:Defect_No=80997

Se quer ver esta melhoria implementada por padrão no Delphi, vote neste QC, só clicar no link, fazer login com sua conta do EDN e votar, lembre-se que você pode dar até 10 votos por cada QC, se este QC tiver um bom número de votos, você pode ter esta melhoria na próxima versão do Delphi.

Este QC parece ser bem recebido pela comunidade, alguns grandes programadores conhecidos entraram em contato, um deles foi Anders Melander que até enviou um código que já pode ser utilizado nos nossos programas pra melhorar a aparência das imagens desabilitadas. Já que ele mandou o código para que eu incluísse no QC, não vejo problemas em divulgar aqui.

interface

uses
  ...

//---------------------------------------------------------------
//
//      TImageList work around for disabled glyph state
//
//---------------------------------------------------------------
// Insert this declaration before your form is declared to enable the
// workaround.
// This class can be deleted if TImageList is ever fixed.
//---------------------------------------------------------------
type
  TImageList = class(Controls.TImageList)
  protected
    procedure DoDraw(Index: Integer; Canvas: TCanvas; X, Y: Integer;
      Style: Cardinal; Enabled: Boolean = True); override;
  end;

implementation

uses
  CommCtrl,
  ...;

procedure TImageList.DoDraw(Index: Integer; Canvas: TCanvas; X, Y: Integer;
  Style: Cardinal; Enabled: Boolean);
var
  i: integer;
  Glyph, Mask: TBitmap;
begin
  if HandleAllocated then
  begin
    if (Enabled) then
    begin
      inherited;
      exit;
    end;

    Glyph := TBitmap.Create;
    try
      Glyph.SetSize(Width, Height);
      Glyph.PixelFormat := pf32bit;
      Glyph.Transparent := (ColorDepth <> cd32Bit);

      // Clear entire glyph - including alpha
      for i := 0 to Glyph.Height-1 do
        FillChar(Glyph.ScanLine[i]^, Glyph.Width*SizeOf(DWORD), $00);

      // Get glyph from imagelist
      ImageList_Draw(Handle, Index, Glyph.Canvas.Handle, 0, 0,
        ILD_TRANSPARENT);

      // Synthesize the disabled glyph image
      // TODO : Increase contrast of desaturated image.
      Desaturate(Glyph, 255);

      if (ColorDepth = cd32Bit) then
      begin
        // Note: Glyph.AlphaFormat should be done after the image has been
        // desaturated; afDefined premultiplies the RGB.
        Glyph.AlphaFormat := afDefined;
        // Alpha blended glyph
        // Draw glyph with AlphaBlend() via TBitmap.Draw().
        Canvas.Draw(X, Y, Glyph);
      end else
      begin
        // Masked glyph
        Mask := TBitmap.Create;
        try
          Mask.SetSize(Width, Height);
          Mask.Monochrome := True;
          Mask.Canvas.Brush.Color := clWhite;
          Mask.Canvas.FillRect(Rect(0, 0, Width, Height));
          // Get glyph mask from imagelist
          ImageList_Draw(Handle, Index, Mask.Canvas.Handle, 0, 0, ILD_MASK);

          // Draw glyph masked with MaskBlt
          //
          // MakeROP4($00AA0029, SRCCOPY):
          //   if (Mask = 1) then Dest := Dest
          //   if (Mask = 0) then Dest := SRCCOPY (translate black to
          //     TextColor, white to BkColor)
          // For each white pixel in the mask do nothing ($00AA0029 = NOOP).
          // For each black pixel in the mask draw the glyph.
          // Note: The special handling required by palette target devices
          // has not been implemented.
          MaskBlt(Canvas.Handle, 0, 0, Width, Height,
            Glyph.Canvas.Handle, 0, 0,
            Mask.Handle, 0, 0,
            MakeROP4($00AA0029, SRCCOPY));
        finally
          Mask.Free;
        end;
      end;

    finally
      Glyph.Free;
    end;
  end;
end;

Para utilizar este código, basta colocar na mesma unit do form onde está o componente TImageList. O compilador vai utilizar esta versão de TImageList.DoDraw no lugar da versão original da VCL.

O código do expert Delphi Nice Toolbar também pode ser utilizado para melhorar a aparência da ToolBar nos seus programas, ele usa o método de “patch” em memória, método utilizado pelo Andreas Hausladen no DelphiSpeedUP e no IDE Fix Pack.

 
 
 

4 Comments

 
  1. Fausto Alves disse:

    Interessante esta dica Cesar, muito boa mesmo.
    Você ficou um tempo desaparecido e agora retorna em grande estilo.
    FELIZ 2010.
    Abraços
    Fausto

  2. Roberto disse:

    Gastei meus 10 votos….
    Eu preciso colocar em cada unit, ou apenas em uma do projeto ?

    Roberto.

  3. Cesar disse:

    @Roberto:

    Se vc fizer patch em memória é só uma vez, se adicionar este código que está no post, tem de ser nas units que usa TImageList.

    Obrigado por votar. Os 10 votos são pra cada QC, então você poderá votar em outros QC sem problemas.

  4. Carlos Gonzaga disse:

    Também achei muito interessante.
    Mas quando coloquei o codigo do blog, ele naõ o metodo Desaturate(Glyph, 255) na linh a 58. Será q falta alguma unit para usar?

 

Leave a Comment

 

You must be logged in to post a comment.