6

Look at the image below:

enter image description here

As you can see I cannot send Buttons to back. This only works for labels.

So how can I send TImage to front with its transparency.

By the way I've read This related question but didn't help me. Because you cannot even click on a button after running Andreas Rejbrand's code. Not only buttons, everything (like the scrollbar in this image)

Edit: I don't want to make the button reachable after I send that back to the image. Just want to bring TImage to front of everything.

Thanks.

Community
  • 1
  • 1
Sky
  • 4,244
  • 7
  • 54
  • 83
  • So your question is *"how can I bring a TImage to front of a TWinControl and at the same time make clicks go through it?"* (As you know you can click an image.) – Sertac Akyuz Sep 20 '13 at 20:53
  • 5
    Since components derived from TGraphicControl (like TLabel,TImage,TSpeedbutton) are painted on their parents DC there is no way to bring a TGraphicControl in front of a TWincontrol with his own DC. – bummi Sep 20 '13 at 21:03
  • 3
    As Bummi says. Your 'bring to front is working for labels' assertion is wrong. – Sertac Akyuz Sep 20 '13 at 21:04
  • 1
    I tried to display the very different behavior of GraphicControls in opposite to Wincontrols in a tiny [screenshot](http://www.bummisoft.de/TranspPanel.png). – bummi Sep 20 '13 at 21:54
  • @Sky - re (edit): Does none of the answers fit your requirement? – Sertac Akyuz Sep 22 '13 at 21:37
  • @SertacAkyuz They were helpful but not the answers I was looking for. I think it's impossible. – Sky Sep 24 '13 at 20:20
  • @Sky - You're right. I guess one of the answers mentioned that it is impossible before proceeding with the proposed solution. Thanks for the feedback. – Sertac Akyuz Sep 24 '13 at 20:35

3 Answers3

12

One way which could you near the goal would be to use interposer classes for the TWincontrols and paint the image moved on them, after they have been painted already, using a TControlCanvas and "hooking" WM_PAINT.
The code is showing a raw draft using a semitransparent PNG image and may be enhanced.

enter image description here

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, dxGDIPlusClasses, ExtCtrls;

type
  TButton=Class (StdCtrls.TButton)
      Procedure WMPaint(var MSG:TMessage);Message WM_Paint;
  End;
  TEdit=Class (StdCtrls.TEdit)
      Procedure WMPaint(var MSG:TMessage);Message WM_Paint;
  End;

  TForm2 = class(TForm)
    Image1: TImage;
    SpeedButton1: TSpeedButton;
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

{ TButton }

procedure TButton.WMPaint(var MSG: TMessage);
var
  cc:TControlCanvas;
begin
   inherited;
    CC:=TControlCanvas.Create;
    CC.Control := TControl(Self);
    CC.Draw(-Left,-Top,Form2.Image1.Picture.Graphic);
    CC.Free;
end;

procedure TEdit.WMPaint(var MSG: TMessage);
var
  cc:TControlCanvas;
begin
   inherited;
    CC:=TControlCanvas.Create;
    CC.Control := TControl(Self);
    CC.Draw(-Left,-Top,Form2.Image1.Picture.Graphic);
    CC.Free;

end;

end.

Another (better) place to "hook" would be overriding PaintWindow

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, dxGDIPlusClasses, ExtCtrls;

type
  TButton=Class (StdCtrls.TButton)
      procedure PaintWindow(DC: HDC);override;
  End;
  TEdit=Class (StdCtrls.TEdit)
      procedure PaintWindow(DC: HDC);override;
  End;

  TForm2 = class(TForm)
    Image1: TImage;
    SpeedButton1: TSpeedButton;
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

{ TButton }

procedure TButton.PaintWindow(DC: HDC);
var
  cc:TCanvas;
begin
   inherited;
    CC:=TCanvas.Create;
    CC.Handle := DC;
    CC.Draw(-Left,-Top,Form2.Image1.Picture.Graphic);
    CC.Free;
end;

procedure TEdit.PaintWindow(DC: HDC);
var
  cc:TCanvas;
begin
   inherited;
    CC:=TCanvas.Create;
    CC.Handle := DC;
    CC.Draw(-Left,-Top,Form2.Image1.Picture.Graphic);
    CC.Free;

end;

end.
bummi
  • 27,123
  • 14
  • 62
  • 101
8

You do not want the Image brought to front (which by the way is impossible over a windowed control), because you want the button also reachable.

Although your question is contradicting itself, and it is not at all clear what exactly you want to achieve, I think you mean to have a transparent button over an image.

If so, then use a TSpeedButton, and set its Transparent and Flat property to True.

Here an example with the three button states: normal, hovered, pressed:

enter image description here

NGLN
  • 43,011
  • 8
  • 105
  • 200
  • We don't know what he wants to achieve but the other question is clear: "how do I set a Timage on top of other controls". nd bummi answer it nicely. – Gabriel Oct 18 '18 at 11:16
4

You can use the solution you linked in your question. For the controls that you want the clicks go through - disable them. Since you're putting the image on a panel, disabling both the panel and the image will let the button to be clicked.

Sertac Akyuz
  • 54,131
  • 4
  • 102
  • 169