/******************************************************************************/
// module: FAbout.cpp version 1.2b //
// //
// About-dialog with a few lines of text and an animated icon playing //
// pinball with the dialogs frame. //
// //
// copyright (c) 2000-2003 by lars haendel //
// home: http://www.newty.de //
// //
// This program is free software and can be used under the terms of the //
// GNU licence. See header-file for further information and disclaimer. //
// //
/******************************************************************************/
#include <vcl.h>
#pragma hdrstop
#include <math> // due to: cos()/sin()
#include <stdio> // sprintf()
#include <process> // _beginthread()
#pragma package(smart_init)
#pragma resource "*.dfm"
//----------------------------------------------------------------------------------------------------------------------
#include "FAbout.h"
#define SZ_PURPOSE "A Gui for the cluster algorithm PNC2"
#define SZ_AUTHOR "Lars Haendel"
#define SZ_URL "http:\/\/www.newty.de\/pnc2/index.html"
#define SZ_EMAIL "mailto:lars.nospam@gmx.de?subject=Contact PNC2"
TFAbout *FAbout;
//----------------------------------------------------------------------------------------------------------------------
// constructor
__fastcall TFAbout::TFAbout(TComponent* Owner, const char* name, const AnsiString szDir) : TForm(Owner)
{
// ToDo: move code to OnShow() ??
// compose and set dialog's caption
char text1[256];
sprintf(text1, "About the program %s", name);
Caption = AnsiString(text1);
// ask for the size of an icon - usually 32x32
cxIcon = GetSystemMetrics(SM_CXICON);
cyIcon = GetSystemMetrics(SM_CYICON);
// create and load the two icons
icon1 = new TPicture;
icon2 = new TPicture;
icon1->LoadFromFile(szDir + "smiley1.ico");
icon2->LoadFromFile(szDir + "smiley2.ico");
// icon start position
randomize();
xIcon = random(Width); // initialize icon position and ...
yIcon = random(Height);
directionPhi = 1; // ... moving direction
// set the icon to be shown in the image, set its size and show it
Image->Picture = icon1;
// create panel
panel = new TPanel(this);
panel->Parent = this;
panel->HandleNeeded(); // this creates the window
panel->BorderStyle = bsNone;
panel->BevelInner = bvNone;
panel->BevelOuter = bvNone;
panel->FullRepaint = false;
// set the panel position to be the same as the Image's one
panel->Left = xIcon;
panel->Top = yIcon;
panel->Width = cxIcon;
panel->Height = cyIcon;
Image->Parent = panel; // make the panel to be the image's parent ...
Image->Left = 0; // ... and position it inside the panel
Image->Top = 0;
// exchange the panel's WindowProc() function
OldWindowProc = panel->WindowProc; // remember old one
panel->WindowProc = NewWindowProc; // set new one
Timer->Enabled=true; // enable timer
// wrap handle in the wrapper (needed to pass it by pointer to a thread function
wrapper.hwnd = Handle;
}
//----------------------------------------------------------------------------------------------------------------------
// initialize purpose and author texts
void __fastcall TFAbout::FormShow(TObject *Sender)
{
LaPurpose ->Caption = AnsiString("// ") + SZ_PURPOSE;
LaWrittenBy->Caption = AnsiString("// Written by ") + SZ_AUTHOR;
}
//----------------------------------------------------------------------------------------------------------------------
// disable timer and restore the panel's old WindowProc() function
void __fastcall TFAbout::OnClose(TObject *Sender, TCloseAction &Action)
{
panel->WindowProc = OldWindowProc; // restore
Timer->Enabled = false; // disable timer
Action = caFree; // emulates 'wfDeleteOnClose' behaviour
}
//----------------------------------------------------------------------------------------------------------------------
// eliminate the panel's WM_ERASEBKGND message and forward all other
void __fastcall TFAbout::NewWindowProc(TMessage& msg)
{
if(msg.Msg == WM_ERASEBKGND)
msg.Result=false;
else
OldWindowProc(msg);
}
//----------------------------------------------------------------------------------------------------------------------
// close dialog if user hits escape
void __fastcall TFAbout::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
{
if(Key==VK_ESCAPE)
Close();
}
//----------------------------------------------------------------------------------------------------------------------
// evaluate timer event: move the panel with the icon and check for contact with the dialog's frame
void __fastcall TFAbout::OnTimer(TObject *Sender)
{
// eventually restore display to the standard-icon
if(nSmile == 0)
Image->Picture = icon1;
nSmile--; // decrease counter
// calculate new position
xIcon += 2.5*cos(directionPhi);
yIcon += -2.5*sin(directionPhi);
// check calculated position against the dialog's border and "reflect" if the icon hits it
if(xIcon < 0) // left border
{
xIcon = 0;
directionPhi = -directionPhi + M_PI;
nSmile = 5;
Image->Picture = icon2;
}
if(yIcon < 0) // top border
{
yIcon = 0;
directionPhi = -directionPhi;
nSmile = 5;
Image->Picture = icon2;
}
if(xIcon > ClientWidth-cxIcon) // right border
{
xIcon = ClientWidth-cxIcon;
directionPhi = -directionPhi + M_PI;
nSmile = 5;
Image->Picture = icon2;
}
if(yIcon > ClientHeight-cyIcon) // bottom border
{
yIcon = ClientHeight-cyIcon;
directionPhi = -directionPhi;
nSmile = 5;
Image->Picture = icon2;
}
panel->Left = xIcon; // move panel with the icon inside
panel->Top = yIcon;
}
//-------------------------------------------------------------------------------------------------------------------
// functions which start browser and mail client
//
//----------------------------------------------------------------------------------------------------------------------
// function executes the shell command in an additional thread - see below
void OpenURL(void* _tmp)
{
TFAbout::THandleWrap* tmp = (TFAbout::THandleWrap*) _tmp;
ShellExecute(tmp->hwnd, "open", SZ_URL, 0, 0, SW_NORMAL);
}
//----------------------------------------------------------------------------------------------------------------------
// function executes the shell command in an additional thread - see below
void OpenMail(void* _tmp)
{
TFAbout::THandleWrap* tmp = (TFAbout::THandleWrap*) _tmp;
ShellExecute(tmp->hwnd, "open", SZ_EMAIL, 0, 0, SW_NORMAL);
}
//----------------------------------------------------------------------------------------------------------------------
// functions open homepage URL in browser or mail client. both call a thread function which executes
// the necessary shell command. done this way cause some browsers need a long time to open ... ;-)
void __fastcall TFAbout::UrlClick(TObject *Sender)
{
_beginthread(OpenURL, 4096, (void*) &wrapper);
Image->Picture = icon2;
}
void __fastcall TFAbout::MailClick(TObject *Sender)
{
_beginthread(OpenMail, 4096, (void*) &wrapper);
Image->Picture = icon2;
}