Link to home
Start Free TrialLog in
Avatar of nashing_nasher
nashing_nasher

asked on

Fading Controls

OK. The flickering was ok, but what I do need is a way to fade a TGroupBox in and out (two seperate procedures or functions) as well as their contents. Any ideas:-/ P.S. Really, really sorry about the last question.
Avatar of Slavak
Slavak

If your program should run on Windows NT/2000/XP you can try layered windows functions.

Look at
 SetLayeredWindowAttributes
 UpdateLayeredWindow

Avatar of nashing_nasher

ASKER

Oh, sorry, the program has to run on win 9x/2K/NT4/ME/XP
Ok, I don't know a way to do a window semi-transparent on win9x. So the way I see to do the same visual effect is:

Fade Out:

1. Get appearence of the window to the bitmap image.
2. Hide the window
3. show/draw the image semitransparent (you can use AlphaBlend function) in loop.

I managed to fade the window itself out using the AlphaBlend and AlphaBlendValue properties of the form, but i don't want the window to be transparent, only my TPanel and its contents. Is this possible?
Take it to image, now it possible
how do you get the TPanel to the bitmap image (sorry, i'm a newbie) and how do you draw it back?
TBitmap?
Try something like this:

procedure FadeControl(AControl : TWinControl);
Var
 Bitmap  : TBitmap;
 Canvas  : TControlCanvas;

 Func    : TBlendFunction;
 R       : TRect;

 Opacity : Integer;
Begin
 If (AControl = nil) or (AControl.Parent = nil) or not AControl.Visible Then
   Exit;

 Bitmap  := TBitmap.Create;
 Canvas  := TControlCanvas.Create;
 Try
   With AControl Do Begin
    Bitmap.Width   := Width;
    Bitmap.Height  := Height;

    Canvas.Control :=  AControl;
    Bitmap.Canvas.CopyRect(ClientRect, Canvas, ClientRect);

    Hide;

    Func.BlendOp             := AC_SRC_OVER;
    Func.BlendFlags          := 0;
    Func.AlphaFormat         := 0;


    Canvas.Control         := Parent;
    Parent.DoubleBuffered  := True;

    Opacity := 255;
    While Opacity > 20 Do Begin
      R := ClientRect;
      OffsetRect(R, Left, Top);
      InvalidateRect(Parent.Handle, @R, False);
      Parent.Update;

      Func.SourceConstantAlpha := Opacity;
      AlphaBlend(Canvas.Handle, Left, Top, Width, Height,
                 Bitmap.Canvas.Handle, 0, 0, Width, Height,
                 Func);

      Sleep(50);
      Dec(Opacity, 20);
    End;
   End;

   Canvas.Control.Invalidate;

 finally
   Bitmap.Free;
   Canvas.Free;
 End;
End;

procedure TForm1.Button1Click(Sender: TObject);
begin
 FadeControl(Panel1);
end;
Almost there:)
Just one more problem.

This line returns the error "Missing Operator or semi colon":
AlphaBlend(Canvas.Handle, Left, Top, Width, Height,

And this line returns the error "Statement expected but expression of type 'boolean' found":
Func);

How do I fix this:-/
I compiled it without errors
OK. Thanx very, very, very much. Just one FINAL question. Is there any way to make it less flickery:-/
Oh....I'm really, really, really sorry about this and very gratefull to you for your help, but how do I fade the control back in again:-/
Save the bitmap from fadeout.
Give it to fade in and reverse the loop.

Do it less flickery may be a little difficult with delphi own components. I suppose to use some 3rd party image components.
For example, TDIBComponents from Peter Morris:
http://www.torry.net/vcl/graphics/bitmap/dibcomponents.zip
Oh....I'm really, really, really sorry about this and very gratefull to you for your help, but how do I fade the control back in again:-/
Try it:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, imgList;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Label1: TLabel;
    Edit1: TEdit;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    ControlImage : TBitmap;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure FadeOutControl(AControl : TWinControl; var AControlImage : TBitmap);
Var
 Bitmap  : TBitmap;
 Canvas  : TControlCanvas;

 Func    : TBlendFunction;
 R       : TRect;

 Opacity : Integer;
Begin
 If (AControl = nil) or (AControl.Parent = nil) or not AControl.Visible Then
   Exit;

 Bitmap  := TBitmap.Create;
 Canvas  := TControlCanvas.Create;
 Try
   With AControl Do Begin
    Bitmap.Width   := Width;
    Bitmap.Height  := Height;

    Canvas.Control :=  AControl;
    Bitmap.Canvas.CopyRect(ClientRect, Canvas, ClientRect);

    Hide;

    Func.BlendOp             := AC_SRC_OVER;
    Func.BlendFlags          := 0;
    Func.AlphaFormat         := 0;

    Canvas.Control         := Parent;
    Parent.DoubleBuffered  := True;

    Opacity := 255;
    While Opacity > 20 Do Begin
      R := ClientRect;
      OffsetRect(R, Left, Top);
      InvalidateRect(Parent.Handle, @R, False);
      Parent.Update;

      Func.SourceConstantAlpha := Opacity;
      AlphaBlend(Canvas.Handle, Left, Top, Width, Height,
                 Bitmap.Canvas.Handle, 0, 0, Width, Height,
                 Func);

      Sleep(50);
      Dec(Opacity, 20);
    End;
   End;

   Canvas.Control.Invalidate;

   AControlImage.Assign(Bitmap);
 finally
   Bitmap.Free;
   Canvas.Free;
 End;
End;

procedure FadeInControl(AControl : TWinControl; AControlImage : TBitmap);
Var
 Bitmap  : TBitmap;
 Canvas  : TControlCanvas;

 Func    : TBlendFunction;
 R       : TRect;

 Opacity : Integer;
Begin
 If (AControl = nil) or (AControl.Parent = nil) or AControl.Visible or
 (AControlImage = nil) Then Exit;

 Bitmap  := TBitmap.Create;
 Bitmap.Assign(AControlImage);

 Canvas  := TControlCanvas.Create;
 Try
   With AControl Do Begin
    Func.BlendOp             := AC_SRC_OVER;
    Func.BlendFlags          := 0;
    Func.AlphaFormat         := 0;

    Canvas.Control         := Parent;
    Parent.DoubleBuffered  := True;

    Opacity := 0;
    While Opacity < 230 Do Begin
      R := ClientRect;
      OffsetRect(R, Left, Top);
      InvalidateRect(Parent.Handle, @R, False);
      Parent.Update;

      Func.SourceConstantAlpha := Opacity;
      AlphaBlend(Canvas.Handle, Left, Top, Width, Height,
                 Bitmap.Canvas.Handle, 0, 0, Width, Height,
                 Func);

      Sleep(50);
      Inc(Opacity, 20);
    End;

    Show;
   End;

 finally
   Bitmap.Free;
   Canvas.Free;
 End;
End;



procedure TForm1.Button1Click(Sender: TObject);
begin
 ControlImage.Free;
 ControlImage := TBitmap.Create;
 FadeOutControl(Panel1, ControlImage);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 FadeInControl(Panel1, ControlImage);
end;

end.
ASKER CERTIFIED SOLUTION
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This is a superb method of fading TGroupBoxes both in and out, flickerlessly, smoothly and cleanly.
One last question. With this code, I want to fade the TGroupBox out, set a couple of properties (i.e. Left, Top, Width and Height) and then fade it in again. I can do the first two parts, but when I try to fade it in again, I get the error message:
"Exception EAccessViolation in module TWINDY.EXE at 0023A68
 Access violation at address 00423A68 in module 'TWINDY.EXE' Read of address FFFFFFFF"
I have figured out that this means that you can not fade out and then in in the same function, or in another function. It must be done by two seperate button clicks. How do I solve this problem:-/
Ok sorted that out, just now I want to get it to fade in an update TBitmap of the TGroupBox in its new position and with its new dimensions. How do I do that?
Ok sorted that out, just now I want to get it to fade in an update TBitmap of the TGroupBox in its new position and with its new dimensions. How do I do that?