HarmFade Component, by Harm
Copyright © 1998 Technoid Brain Trust
All Rights Reserved
harmans@uswest.net
Version 2.3 - 1/99
Added three new Events: OnMouseEnter, OnMouseLeave, and OnClick. Added two new methods:
UnBlend and UnDissolve. These excellent suggestions came from Douglas@rexburg.com. This makes HarmFade a
little more useful - it can be used as a quasi-button. The other change is this
document, an attempted improvement over *.txt. I'm assuming that anyone who
downloads this component also has some sort of browser.
Usage Notes - Miscellaneous info
Description - A description of this component and its
limitations
System Requirements - What you need to use this
component successfully
License Agreement - What's required for you to use this
component
Credits - People who have helped improve this component
Installation - How to install this component
Properties - a description of the component properties
Methods - a description of the component methods
Events - a description of the component events
Examples - code snippets and suggestions to get you going
Usage Notes
For D3 users, your projects may need to have jpeg added to the uses clause in order for
them to work correctly with HarmFade. D4 seems to include it automatically.
If you have a GIFImage component installed, such as the excellent freeware version by
Anders Melander, you can use gif with harmfade also. Be aware that transparency may cause
odd behavior with gifs, since they are not specifically addressed within Harmfade. Gif
support is not a native Delphi TPicture format, so I did not include code to deal with
that.
Description
HarmFade is a Delphi Component that will transition between two TPictures. It's a
descendant of TGraphicControl. It currently has two transitions: Blend and
Dissolve. Blend is a gradual change of the pixels from the first TPicture to the
second TPicture. It's basically a series of merge operations on the two images,
changing the percentage from 100% of the first picture to 100% of the second picture
gradually. Dissolve is a pixel swap operation, so that individual pixels are changed
from the first picture to the second picture. It can be used in about boxes for
interesting effects, or as a quasi-button. See the Examples section for details on
how to use HarmFade effectively.
System Requirements
HarmFade will only work with Delphi 3 or higher. It uses the
TBitmap.Scanline property introduced in D3, and will not compile in D1 or D2. It
also uses 24bit bitmaps. It will look OK on 16bit (High) color and above, but looks
like crap on 16 or 256 color monitors. I developed this for my own purposes, and
that's how my system is set up. Sorry about that, but I'm not out to make any money
on this, so what you see is what you get. HarmFade is fairly fast, and should be
fine on any Pentium processor, but may be a bit on the slow side on anything less.
License Agreement
This code is freeware. As such, you get what you pay for. No warranties, express
or implied, are provided. The author is not responsible for any problems caused by
this component. Use it at your own risk. The author provides no support
whatsoever, and is not obligated to any person or corporation for anything related to this
software. The author reserves all rights concerning this code. You are free to
use it as you see fit, but if you make modifications or improvements that may benefit the
Delphi programming community, I would appreciate hearing from you. This code cannot
be sold for any purposes, or included in a commercial collection, without the express
written consent of the author. By installing these files on your computer, you agree
to all above conditions.
Credits
Many improvements have been made to the original version of this component.
I would like to thank those who have helped make this better, I am always
interested in learning how to improve the code/usability.
Sebastion LEON - Provided the assembler code to speed things up dramatically. A
major improvement. Thanks, Seb.
Cristian Brolin, Dean Crawford, and Douglas ? @Rexburg.com for great suggestions on
improvements.
Delphi programmers who have shared their code with the world so we can all learn from it.
Team B and others who have taken the time to give advice and patient explanations on the
Borland newsgroups.
Unzip the files
Copy HarmFade.pas and HarmFade.dcr to the component folder of your choice.
From D3 or D4, select the Component menu item, then Install (component). Browse to the foler where you copied the files. Select HarmFade.pas and click OK until it's installed.
By default, HarmFade will be placed on the Samples tab of the Component palette. To change this, edit the source code and find the register procedure. Change the 'Samples' to whatever tab you wish, then re-install the component. Or, use the Configure Palette menu option to move it to the tab you want.
Property | Type |
AutoReverse | Boolean |
BlendRate | Integer |
ColorFrom, ColorTo | TColor |
DisolvRate | Integer |
Finish | Boolean |
Height | Integer |
Hint | String |
Left | Integer |
Name | String |
ParentShowHint | Boolean |
PicFrom, PicTo | TPicture |
PopupMenu | TMenu |
ProcessMsgs | Boolean |
ShowHint | Boolean |
StretchToFit | Boolean |
SwapDelay | Integer |
SwapOnReverse | Boolean |
Tag | Integer |
Top | Integer |
Visible | Boolean |
Width | Integer |
AutoReverse - When this is set to true, the blend or dissolve will reverse itself and do an UnBlend or UnDissolve, depending on the SwapOnReverse setting. The delay before reversal is set with the SwapDelay property.
BlendRate - a value from 1 - 255. This determines the speed of the blend transition. Low values are faster. The smoothest blend rate is 32, but it's pretty fast for smaller images. The speed of blend is dependent on the Image size. It takes some experimentation with this value to determine the optimum.
ColorFrom, ColorTo - If a PicFrom or PicTo is not assigned, these colors are used in their stead. You could blend from solid black color to a Picture by setting PicFrom to nil and setting ColorFrom to clBlack. If a PicFrom or PicTo is assigned, these settings are ignored.
DisolvRate - a value from 1 - (the HarmFade W x H). This is similar to the BlendRate, lower numbers are faster. The speed of dissolve is also dependent on the image size, and will take some experimentation to get set the way you want.
Finish - This property is not published, but is available in your application at run-time. Setting this property to TRUE will force immediate completion of the transition. You must set ProcessMsgs to true for this to work properly.
Height, Hint, Left, Name, ParentShowHint - These are normal Delphi VCL properties, common to all Controls. See delphi help for a description of these.
PicFrom, PicTo - These are the images that harmfade blends or dissolves. All of the normal TPicture formats are supported: bmp, jpg, wmf, emf, and ico. They can be assigned at design time via the object inspector, or loaded or assigned at runtime with the normal TPicture methods. See Examples for more information.
PopupMenu - Normal Delphi PopupMenu, see Delphi help for information on usage.
ProcessMsgs - When set to true, this will allow the blend or dissolve transition to be 'interrupted'. Normally, HarmFade uses tight loops for drawing and won't allow other processing to take place during the transition. This must be set to true for the Finish property to take effect.
ShowHint - Normal Delphi ShowHint property, see Delphi help for information on usage.
StretchToFit - When set to true, this will stretchdraw the images to fit into the current HarmFade dimensions. When set to false, HarmFade will resize itself to fit the PicFrom image, unless: if PicFrom is not assigned, HarmFade will resize itself to the PicTo dimensions. If neither is assigned, this property is ignored.
SwapDelay - the amount of time between transition and un-transition, in seconds. This property is ignored if AutoReverse is false.
SwapOnReverse - changes the transition when doing an UnBlend or UnDissolve. Ignored if AutoReverse is false. If true, this will UnDissolve after a Blend, or UnBlend after a Dissolve.
Tag, Top, Visible, Width - These are normal Delphi VCL properties, common to all Controls. See delphi help for a description of these.
Method | Description |
Blend | This starts the transition using the Blend effect. It blends from either PicFrom or ColorFrom to PicTo or ColorTo, depending on propery settings. |
Dissolve | This starts the transition using the Dissolve effect. It dissolves from either PicFrom or ColorFrom to PicTo or ColorTo, depending on property settings. |
Reset | Recalculate sizes, re-draw starting picture (or color). |
UnBlend | This starts the transition using the Blend effect, but goes in reverse order. It blends from either PicTo or ColorTo to PicFrom or ColorFrom, depending on property settings. |
UnDissolve | This starts the transition using the Dissolve effect, but goes in reverse order. It dissolves from either PicTo or ColorTo to PicFrom or ColorFrom, depending on property settings. |
Event | Description |
OnBegin | Fires when transition starts, by either a Blend or Disslove method. |
OnClick | Fires when user clicks on HarmFade. Use like a button click. |
OnEnd | Fires when transition is complete. |
OnMouseEnter | Fires when mouse enters HarmFade. |
OnMouseLeave | Fires when mouse leaves HarmFade. |
OnReset | Fires when a Reset is done. |
Examples
When a THarmFade is dropped on a form (or panel, etc), it will just be a small
black box. It will function without loading any pictures, but is much more effective
if PicFrom and/or PicTo is assigned. Just double-click one of those properties in
the Object Inspector to load an image, much like a TImage. To start the transition,
you must use the Blend or Disslove method in your application code:
procedure TForm1.Button1Click(Sender: TObject);
begin
HarmFade1.Dissolve;
{or}
HarmFade1.Blend;
end;
If neither the From or To Picture has been assigned, it will transition from a 'ColorFrom'
square to a 'ColorTo' square.
After completing the transition, the PicTo (or ColorTo) will remain visible unless
AutoReverse is True, or until either:
1) the effect is started again with .Dissolve or .Blend, or
2) the THarmFade.Reset method is used. This will reset the pictures back to their
'original' state, prior to transition. Changing any of the following properties will also
cause the Reset method to be called:
PicFrom, PicTo, ColorFrom, ColorTo, or StretchToFit.
If only one of PicFrom or PicTo is assigned, the transition will use a solid color for the
other picture. For example, if PicFrom is
assigned, and PicTo is not, then the ColorTo color will be used instead of PicTo.
If PicFrom or PicTo is a MetaFile or Icon, they support transparency. The background color
will be the ColorFrom or ColorTo, respectively.
StretchToFit by default is True. When a picture is assigned, it will StretchDraw it to fit
into the current size of HarmFade. If StretchToFit is False, then the HarmFade is
sized to match the PicFrom picture (if assigned) and the PicTo is stretched to match that
size. If PicFrom is empty, the HarmFade will be sized based on PicTo. In order for
the fading effect to work, the From and To pictures must be made the same size. I didn't
want to force people to size the pictures prior to using this control, so I made up these
rules. Again, some experimentation with the pictures and this setting will give you a
better feel for how it all works.
ProcessMessages is FALSE by default. The HarmFade uses tight loops for doing the
animation, which means your application is locked until it's complete . You can't use
buttons, scrollbars, etc in your application until the .Blend or .Dissolve method has
completed. Setting the ProcessMessages property to TRUE allows the animation to be
interrupted. It allows the tight loop to be paused for handling other tasks. The animation
stops while messages are processed, then continues when it can.
While this all may sound complicated, it's really quite easy to use HarmFade: Drop a
THarmFade on a form. Double Click the PicFrom property, and use the Dialog to select a
graphic supported by tpicture. Double Click the PicTo property and select a different
picture. (Or leave one of these properties unassigned). Add a TButton to your form,
and add the following line to the OnClick:
HarmFade1.Dissolve;
Run the program, then click the button. Watch the dissolve, and adjust the DisolvRate
property as desired for maximum effect. To unassign one of the bitmap properties, double
click the property and use the Clear button in the dialog. To achieve the same effect in
code, use this:
HarmFade1.PicTo := nil;
You can use HarmFade as a crude button, but with interesting effects. Use your favorite Paint program to design a picture that looks like a button, with very dark colors, or just solid black with gray text (for the 'caption'). Save it, then flood fill the text with a bright color (like red or lime) and save it as a different filename. Use these as the PicFrom and PicTo, respectively. Then, in your application, add the following code:
procedure
TForm1.HarmFade1MouseEnter(Sender: TObject);
begin
HarmFade1.Blend;
end;
procedure TForm1.HarmFade1MouseLeave(Sender: TObject);
begin
HarmFade1.UnBlend;
end;
procedure TForm1.HarmFade1Click(Sender:
TObject);
begin
ShowMessage('You clicked on HarmFade');
end;
When the mouse moves over the HarmFade, it will start the blend transition. When the
mouse leaves the HarmFade, it will UnBlend back to the original image.
You may want to have this Transition effect take place whenever a Form is
first shown. This can be achieved by placing the .Dissolve or .Blend method in the form's
OnShow event. However, it seems that the transition starts up before the form is
completely painted. Thanks to Anders Melander and Joachim Meyer for advice on how to
surmount this problem:
*** Add a user message constant (MY_MSG)
*** Add a procedure to handle message (MY_MSG)
*** In Form's OnShow event, Post the new message
*** In the new message handler, do the animation
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, HarmFade;
const
MY_MSG = WM_USER + 1; {<=== Add this}
type
TForm1 = class(TForm)
Label1: TLabel;
HarmFade1 : THarmFade;
procedure FormShow(Sender: TObject); {<== Add code to OnShow}
....
private
procedure WeArePainted(var Msg : TMessage); message MY_MSG;
.... {== Add the above procedure ==}
implementation
procedure TForm1.FormShow(Sender: TObject);
begin
PostMessage(Handle, MY_MSG, 0, 0); {<== Post our new message}
end;
{== The following procedure now gets control once form is painted}
procedure TForm1.WeArePainted(var Msg : TMessage);
begin
Application.ProcessMessages;
HarmFade1.Dissolve;
end;
How to make a Splash Screen with a THarmFade component
Here's an example of using a splash screen, with a THarmFade transition method thrown in:
First, design your splash screen form. I modify the form's border property to bsNone to
get rid of the title bar. I also make the form's ClientWidth and ClientHeight match the
HarmFade1.Width and Height. I would then change the Position to poScreenCenter to make
sure it centers in the screen at run-time. Of course, this is all arbitrary.
Assuming you gave the form a name of fSplash....
In the project source code (from the menu, select Project, View Source), make the
following modifications:
***Add Windows to the uses clause.
***Add a variable before the begin statement, for your splash form.
***Create your form and show it before creating the other form(s).
***Add the Harmfade.Blend prior to creating other forms.
Here's an example:
program Project1;
uses
Windows, Forms, <== Add 'Windows' for Sleep()
Unit1 in 'Unit1.pas' {Form1},
Splash in 'Splash.pas' {fSplash};
{$R *.RES}
var
Splasher : TfSplash; <== Add var for splash form
begin
try
Splasher := TfSplash.Create(Application); <== Create form
Splasher.FormStyle := fsStayOnTop; <== Stay on Top
Splasher.Show; <== Show form
Sleep(1000); <== Delay 1 second
Splasher.HarmFade1.Dissolve; <== Do dissolve
Sleep(5000); <== Delay 5 secs
Application.Initialize;
Application.CreateForm(TForm1, Form1);
//Application.CreateForm(TfSplash, fSplash); <==Remove
Splasher.Close; <== Close splash
finally
Splasher.Free; <== Free resources
end;
Application.Run;
end.
See the accompanying Demo for more coding examples.
** To make a Harmfade blend from it's underlying form/controls:
Similar to the splash example. Place a Harmfade on your form and set the Visible property
to FALSE. Set the PicTo picture to whatever.
* Note - if underlying controls are windowed controls (memo, button, etc) there is a bit
of flicker when harmfade effect starts.
The following example uses a couple of buttons to start and stop the effect:
procedure TForm1.Button1Click(Sender: TObject);
var
ADC : HDC;
sx, sy : integer;
bm : TBitmap;
begin
ADC := GetDC(0);
bm := TBitmap.Create; //Need a temporary bitmap.
bm.Width := HarmFade1.Width;
bm.Height := Harmfade1.Height;
sx := HarmFade1.ClientOrigin.x;
sy := HarmFade1.ClientOrigin.y;
Bitblt(bm.Canvas.Handle, 0, 0, //BitBlt to our temp bmp
bm.Width, bm.Height,
ADC, sx, sy, SRCCOPY);
HarmFade1.PicFrom.Assign(bm); //Assign it to harmfade
//IF harmfade covers other controls, it's best to make them
// invisible here, like Image1.Visible := FALSE;
HarmFade1.Visible := TRUE; // Sneak us into position
HarmFade1.Blend; // Show the PicTo
bm.Free; // Free the temp bmp
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
HarmFade1.Visible := FALSE;
//If other controls were made invisible, reverse it
// here Image1.Visible := TRUE;
end;