Probablemente haya notado que cuando usa imágenes en elementos de menú y botones en la barra de herramientas, éstas se ven como globos grises indistinguibles cuando dichos componentes están inhabilitados... Este parche de la VCL corrige el problema.

Formas grises casi indistinguibles en elementos de menú inhabilitados

Por Vladimir S. <shvetadvipa@mtu-net.ru>

Boletín Pascal. Newsletter gratuito para programadores Delphi (y Kylix) con artículos, noticias, trucos, componentes y enlaces a nuevo contenido Delphi en la red.

Si desea ver consejos y trucos Delphi interesantes vaya con su navegador a http://www.webmachine.ru/delphi donde encontrará el archivo KULIBA.CHM por Valentin Ozerov que contiene más de 1.500 trucos y consejos (en ruso). Ozerov recolectó soluciones de programadores de Rusia y de todo el mundo, entre las que se encuentran algunas de mis soluciones también. En una de ellas describo como superar una falla para ciertos elementos de menú inhabilitados, que es el objeto de este artículo.

Probablemente haya notado que cuando usa imágenes en elementos de menú y botones en barras de herramientas, éstas se ven como figuras grises casi indistinguibles cuando dichos componentes están inhabilitados:

 
 
 
Menú y Barra de
Herramientas sin el parche

Una posible solución a este problema es moficar el código fuente de la VCL (necesita tener la Edición Empresarial de Delphi para esto). Antes que nada, busque el fichero ImgList.pas, habitualmente ubicado en la carpeta

${Delphi}\Source\Vcl

donde ${Delphi} es el camino donde instaló Delphi, como por ejemplo

C:\Archivos de programa\Borland\Delphi5

Luego ubique la implementación del método TCustomImageList.DoDraw. Coméntela (para mantener la versión original por si acaso) y copie el siguiente código:

procedure TCustomImageList.DoDraw(Index: Integer; Canvas: TCanvas;
    X, Y: Integer; Style: Cardinal; Enabled: Boolean);

  procedure ScrambleBitmap(var BMP: TBitmap);
  const
    RMask = $0000FF;
    RAMask = $FFFF00;
    GMask = $00FF00;
    GAMask = $FF00FF;
    BMask = $FF0000;
    BAMask = $00FFFF;
  var
    R,C: integer;
    Color: LongWord;
  begin
    with Bmp.Canvas do begin
      for C:= 0 to Bmp.Height - 1 do
        for R:= 0 to Bmp.Width - 1 do begin
          Color:= Pixels[R,C];
          if (Color = 0) or (Color = $FFFFFF) then Continue;
          if (Color and RMask > $7F) and (Color and RAMask > $0) or
             (Color and GMask > $7F00) and (Color and GAMask > $0) or
             (Color and BMask > $7F000) and (Color and BAMask > $0)
          then
            Pixels[R,C]:= $FFFFFF
          else
            Pixels[R,C]:= 0;
        end;
    end;
  end;

const
  ROP_DSPDxax = $00E20746;

var
  R: TRect;
  DestDC, SrcDC: HDC;

begin
  if HandleAllocated then begin
    if Enabled then
      ImageList_DrawEx(Handle, Index, Canvas.Handle, X, Y, 0, 0,
        GetRGBColor(BkColor), GetRGBColor(BlendColor), Style)
    else begin
      if FMonoBitmap = nil then begin
        FMonoBitmap:= TBitmap.Create;
        with FMonoBitmap do begin
           // Monochrome:= True;            commented!!!
           Width:= Self.Width;
           Height:= Self.Height;
        end;
      end;
     { Store masked version of image temporarily in FBitmap  }
      FMonoBitmap.Canvas.Brush.Color:= clWhite;
      FMonoBitmap.Canvas.FillRect(Rect(0, 0, Self.Width,
        Self.Height));
      ImageList_DrawEx(Handle, Index, FMonoBitmap.Canvas.Handle,
        0, 0, 0, 0, CLR_DEFAULT, 0, ILD_NORMAL);
      ScrambleBitmap(FMonoBitmap);        // call patch
      R:= Rect(X, Y, X+Width, Y+Height);
      SrcDC:= FMonoBitmap.Canvas.Handle;
      BitBlt(SrcDC, 0, 0, Width, Height, SrcDC, 0, 0,
        DSTINVERT); // add!!!
     { Convert Black to clBtnHighlight  }
      Canvas.Brush.Color:= clBtnHighlight;
      DestDC:= Canvas.Handle;
      Windows.SetTextColor(DestDC, clWhite);
      Windows.SetBkColor(DestDC, clBlack);
      BitBlt(DestDC, X+1, Y+1, Width, Height, SrcDC, 0, 0,
        ROP_DSPDxax);
      { Convert Black to clBtnShadow  }
      Canvas.Brush.Color:= clBtnShadow;
      DestDC:= Canvas.Handle;
      Windows.SetTextColor(DestDC, clWhite);
      Windows.SetBkColor(DestDC, clBlack);
      BitBlt(DestDC, X, Y, Width, Height, SrcDC, 0, 0, ROP_DSPDxax);
    end;
  end;
end;

Ahora debe compilar esta unidad. Esto normalmente se hace copiando el archivo ImgList.pas en el mismo directorio donde reside su proyecto y luego compilando el proyecto, produciendo así el archivo ImgList.dcu que debe mover por ejemplo a la carpeta ${Delphi}\Lib para que aplique a todas las aplicaciones que compile en el futuro.

Los gráficos que resultan con este parche se ven muchísimo mejor:

 
 
 
Menú y Barra de
Herramientas con el parche
 
JfControls Library - para Delphi y C++ Builder