Search code examples
delphiwinapidelphi-xe4

Delphi - re-build click-through transparent area after form resizing


I'm testing some specially-shaped window using VCL.

On the (border-less) main form there is a TImage which I use for making a rectangular click-through transparent area by utilizing TForm.TransparentColor and TForm.TransparentColorValue, like this:

imgTrans.Canvas.Brush.Color := self.TransparentColorValue; imgTrans.Canvas.FillRect(Rect(0, 0, imgTrans.ClientWidth, imgTrans.ClientHeight));

The window's transparent area works, except that after the form's resized, the client-aligned TImage is supposed to be resized thus the transparent area is supposed to be resized too, but it did not.

I tried several approaches trying to make the transparent area resize along with its parent form, but failed, things I tried:

  • After the form's resized, Reseting the parent form's TransparentColor property.
  • After the form's resized, manually resizing the TImage's dimension.

I use xe4 and testing it on Win7.

Any advises? Thanks.


Solution

  • TImage.Canvas property is directly linked to underlying Bitmap image. When you resize TImage control you are not actually resizing its bitmap.

    imgTrans.Picture.Bitmap.Width := imgTrans.Width;
    imgTrans.Picture.Bitmap.Height := imgTrans.Height;
    

    I would also use imgTrans.Picture.Bitmap.Canvas instead of imgTrans.Canvas to make it more clear what your code is doing.

    imgTrans.Picture.Bitmap.Canvas.Brush.Color := TransparentColorValue;
    imgTrans.Picture.Bitmap.Canvas.FillRect(Rect(0, 0, imgTrans.Width, imgTrans.Height));
    

    Another simpler way would be using TPaintBox control instead of TImage. If TPaintBox is re-aligned than its paint method will be called and automatically to paint proper area. This way you also avoid having TImage Bitmap sitting in memory for the whole time.

    procedure TForm1.PaintBox1Paint(Sender: TObject);
    begin
      PaintBox1.Canvas.Brush.Color := TransparentColorValue;
      PaintBox1.Canvas.FillRect(Rect(0, 0, PaintBox1.Width, PaintBox1.Height));
    end;