Search code examples
delphidelphi-7virtualtreeviewtvirtualstringtree

How to color blend cells with a background image in VirtualTreeView?


I'm using VT.Background to display a background image in VT with a few columns.
But I can't find a way to use different colors for cells because they hide the background image.

I have tried to use OnBeforeItemErase but if I useEraseAction := eaColor the background bitmap area on the cell is also being painted, if I use eaDefault the color is not being applied.

Any idea how this can be done?


Solution

  • Just an attempt to guess if that's what you are looking for:

    Update:
    Added a color blending function for non MMX CPU machines.

    procedure ColorBlend(const ACanvas: HDC; const ARect: TRect;
      const ABlendColor: TColor; const ABlendValue: Integer);
    var
      DC: HDC;
      Brush: HBRUSH;
      Bitmap: HBITMAP;
      BlendFunction: TBlendFunction;
    begin
      DC := CreateCompatibleDC(ACanvas);
      Bitmap := CreateCompatibleBitmap(ACanvas, ARect.Right - ARect.Left,
        ARect.Bottom - ARect.Top);
      Brush := CreateSolidBrush(ColorToRGB(ABlendColor));
      try
        SelectObject(DC, Bitmap);
        Windows.FillRect(DC, Rect(0, 0, ARect.Right - ARect.Left,
          ARect.Bottom - ARect.Top), Brush);
        BlendFunction.BlendOp := AC_SRC_OVER;
        BlendFunction.BlendFlags := 0;
        BlendFunction.AlphaFormat := 0;
        BlendFunction.SourceConstantAlpha := ABlendValue;
        Windows.AlphaBlend(ACanvas, ARect.Left, ARect.Top,
          ARect.Right - ARect.Left, ARect.Bottom - ARect.Top, DC, 0, 0,
          ARect.Right - ARect.Left, ARect.Bottom - ARect.Top, BlendFunction);
      finally
        DeleteObject(Brush);
        DeleteObject(Bitmap);
        DeleteDC(DC);
      end;
    end;
    
    procedure TForm1.VirtualStringTree1BeforeCellPaint(Sender: TBaseVirtualTree;
      TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
      CellPaintMode: TVTCellPaintMode; CellRect: TRect; var ContentRect: TRect);
    var
      BlendColor: TColor;
      BlendValue: Integer;
    begin
      if CellPaintMode = cpmPaint then
      begin
        case Column of
          0: BlendColor := $000080FF;
          1: BlendColor := $0046C2FF;
          2: BlendColor := $0046F5FF;
        end;
        BlendValue := 145;
        if not VirtualTrees.MMXAvailable then
          ColorBlend(TargetCanvas.Handle, CellRect, BlendColor, BlendValue)
        else
          VirtualTrees.Utils.AlphaBlend(0, TargetCanvas.Handle, CellRect, Point(0, 0),
            bmConstantAlphaAndColor, BlendValue, ColorToRGB(BlendColor));
      end;
    end;
    

    Preview of the code above:

    enter image description here