Craig
Craig

Reputation: 1946

How do I define a color when using AlphaBlend?

I have an image which is drawn onto a paintbox, I want to be able to show a translucent filled rectangle above any given area of the paintbox which will show the underneath paintbox canvas in a darker color, kind of like the selection box from Windows Explorer.

After much trial and error (and some reading), I managed to do the following:

procedure OpacityRectangle(ACanvas: TCanvas; ARect: TRect; AColor: TColor;
  AOpacity: Integer);
var
  BlendFunc: BLENDFUNCTION;
  W, H: Integer;
  Bitmap: TBitmap;
begin
  W := ARect.Width;
  H := ARect.Height;

  BlendFunc.BlendOp := AC_SRC_OVER;
  BlendFunc.BlendFlags := 0;
  BlendFunc.SourceConstantAlpha := AOpacity;
  BlendFunc.AlphaFormat := 0;

  Bitmap := TBitmap.Create;
  try
    Bitmap.PixelFormat := pf32Bit;
    Bitmap.SetSize(W, H);    
    BitBlt(Bitmap.Canvas.Handle, ARect.Left + W, ARect.Top + H, W, H,
      ACanvas.Handle, 0, 0, SRCCOPY);
    AlphaBlend(ACanvas.Handle, ARect.Left, ARect.Top,
        W, H, Bitmap.Canvas.Handle, 0, 0, W, H, BlendFunc);
  finally
    Bitmap.Free;
  end;
end;

As you can see the AColor parameter is unused as I am unsure exactly as to how I would implement it above. Currently the color of the alpha blended rectangle is a shade of gray (default color I assume), I need to know how I can change the tint color of the alpha blended rectangle.

How could I modify the above to allow choosing a custom color for the tinted alpha blended rectangle?

Upvotes: 2

Views: 584

Answers (1)

Sertac Akyuz
Sertac Akyuz

Reputation: 54772

Currently you are using white, the reason you think it's gray is the translucency. You can verify it by passing 255 as 'AOpacity', you'll see a white rectangle.

The tint color is white because that's the color of your temporary bitmap. All you need to do is to use a colored bitmap. You should remove the BitBlt call, a solid color bitmap is sufficient to apply a tinted color when it is copied transparently to the destination canvas.

  ...
  try
    Bitmap.PixelFormat := pf32Bit;
    Bitmap.Canvas.Brush.Color := AColor;  // <- set tint color
    Bitmap.SetSize(W, H);
    AlphaBlend(ACanvas.Handle, ARect.Left, ARect.Top,
      ...


In case of Lazarus, explicitly paint the bitmap surface, fpc graphics does not honor brush color when enlarging bitmap (hence the bitmap is initially black).

  ..
  try
    Bitmap.PixelFormat := pf32Bit;
    Bitmap.SetSize(W, H);
    Bitmap.Canvas.Brush.Color := AColor;
    Bitmap.Canvas.FillRect(Bitmap.Canvas.ClipRect);
    AlphaBlend(ACanvas.Handle, ARect.Left, ARect.Top,
      ...

Upvotes: 8

Related Questions