1
votes

If you place a normal TImage component on a form or panel over other components >> it is invisible at runtime as long no picture is loaded. So other things under it are visible.

But TImage32 is painting a gray box by default.

How do I make the it invisible while leaving the setting: .Visible:=True; if no picture is loaded?
(I still need events working on the component, like OnClick...)

Yes, this is a duplicate question, BUT the solution-link from the previous topic is dead. :(

2

2 Answers

1
votes

While I still have access to the newsgroup posts, I don't know how the topic ID relates to the topic title (which is all I have). However, based an a search in the newsgroup I found several places where TImage32Ex was mentioned. I guess that this component (which is not part of the core library) was part of the solution in some way.

So, while the extension pack where this component comes from is no longer maintained, let's dig deeper in what it did.

First, I must say that TImage32 will always paint (copy) the content of its buffer to the display. This means whatever graphic is behind this component will get overwritten by default.

The trick TImage32Ex does is to get the parents content and draws it into the buffer.

With adaptions the code looks like this

var
  P: TPoint;
  SaveIndex: Integer;
begin
  SaveIndex := SaveDC(Buffer.Handle);
  try
    GetViewportOrgEx(Buffer.Handle, P);
    SetViewportOrgEx(Buffer.Handle, P.X - Left, P.Y - Top, nil);
    IntersectClipRect(Buffer.Handle, 0, 0, Parent.ClientWidth, Parent.ClientHeight);
    Parent.Perform(WM_ERASEBKGND, Buffer.Handle, 0);
    Parent.Perform(WM_PAINT, Buffer.Handle, 0);
  finally
    RestoreDC(Buffer.Handle, SaveIndex);
  end;
end;

The above code draws (WM_PAINT) the parent's content onto the buffer.

For example if you want to make the TPaintBox32 instance called PaintBox32 to be transparent just add the following code to the 'PaintBuffer' handler:

procedure TForm3.PaintBox32PaintBuffer(Sender: TObject);
var
  P: TPoint;
  SaveIndex: Integer;
begin
  SaveIndex := SaveDC(PaintBox32.Buffer.Handle);
  try
    GetViewportOrgEx(PaintBox32.Buffer.Handle, P);
    SetViewportOrgEx(PaintBox32.Buffer.Handle, P.X - PaintBox32.Left, P.Y - PaintBox32.Top, nil);
    IntersectClipRect(PaintBox32.Buffer.Handle, 0, 0, PaintBox32.Parent.ClientWidth, PaintBox32.Parent.ClientHeight);
    PaintBox32.Parent.Perform(WM_ERASEBKGND, PaintBox32.Buffer.Handle, 0);
    PaintBox32.Parent.Perform(WM_PAINT, PaintBox32.Buffer.Handle, 0);
  finally
    RestoreDC(PaintBox32.Buffer.Handle, SaveIndex);
  end;
end;

Note: While this works basically, it might not capture the parent's sub controls properly. This is especially true for TWinControl descendants. While there are solutions around to cover this scenario as well, it's far more complicated to cover this in every detail (e.g. the blinking cursor of an underlying TEdit instance)

0
votes

I use a timage to mask a progress bar and give it a shape.

What I do is load a png with parts that are transparent and then place it over my progress bar.

I think this should achieve your goal. Place a transparent png in your timage.

Cheers, E.