Delphi TImage32 - how to make the component invisible if no picture is loaded?

烈酒焚心 提交于 2019-12-24 13:47:12

问题


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. :(


回答1:


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)




回答2:


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.



来源:https://stackoverflow.com/questions/46119152/delphi-timage32-how-to-make-the-component-invisible-if-no-picture-is-loaded

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!