Related
i used 30 png pictures on a transplanted from to make a simple animation, a Timer make an event every 33 Millisecond to change the visibility of the TImage Components which have the png images, i tried all the method suggested in other posts to stop flickering but could not solve the problem.
unit Animation;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, AdvShaper, pngimage, ExtCtrls, StdCtrls;
type
TAnimation_Form = class(TForm)
Image1: TImage;
Timer: TTimer;
Image2: TImage;
Image3: TImage;
Image4: TImage;
Image5: TImage;
Image6: TImage;
Image7: TImage;
Image8: TImage;
Image9: TImage;
Image10: TImage;
Image11: TImage;
Image12: TImage;
Image13: TImage;
Image14: TImage;
Image15: TImage;
Image16: TImage;
Image17: TImage;
Image18: TImage;
Image19: TImage;
Image20: TImage;
Image21: TImage;
Image22: TImage;
Image23: TImage;
Image24: TImage;
Image25: TImage;
Image26: TImage;
Image27: TImage;
Image28: TImage;
Image29: TImage;
Image30: TImage;
Exit: TButton;
procedure TimerTimer(Sender: TObject);
procedure ExitClick(Sender: TObject);
private
{ Private declarations }
Image_Counter:Integer;
procedure ChooseImage(I:Integer);
procedure Init();
public
{ Public declarations }
end;
procedure Run_Animation_Form();
procedure Finish_Animation_Form();
implementation
var
Animation_Form: TAnimation_Form;
{$R *.dfm}
procedure Finish_Animation_Form();
Begin
Animation_Form.Close;
End;
procedure Run_Animation_Form();
Begin
Animation_Form := TAnimation_Form.Create(nil);
Try
Animation_Form.Init();
Animation_Form.ShowModal();
Finally
Animation_Form.Free;
End;
End;
{ TAnimation_Form }
procedure TAnimation_Form.ChooseImage(I: Integer);
begin
TwinControl(FindComponent(Format('Image%d',[I]))).Visible := False;
TwinControl(FindComponent(Format('Image%d',[I+1]))).Visible := True;
end;
procedure TAnimation_Form.ExitClick(Sender: TObject);
begin
Close;
end;
procedure TAnimation_Form.Init;
begin
TransparentColor := True;
TransparentColorValue := Color;
Image1.Visible := True;
Image_Counter:=1;
ControlStyle:=ControlStyle - [csOpaque];
BorderWidth := 10;
Anchors := [akLeft, akTop, akBottom, akRight];
end;
procedure TAnimation_Form.TimerTimer(Sender: TObject);
begin
if Image_Counter >= 30 then
Begin
Image30.Visible := False;
Image1.Visible := True;
Image_Counter:=1;
End
else
Begin
ChooseImage(Image_Counter);
Inc(Image_Counter);
End;
end;
end.
Thanks for your help and sorry for my bad English
Rather than using multiple overlapping TImage objects and swapping their Visible property, I would suggest you create an array of 30 TPNGImage objects and then either:
use a single TImage that is always visible and assign the desired PNG to its TImage.Picture property whenever the TTimer elapses:
unit Animation;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, AdvShaper, pngimage, ExtCtrls, StdCtrls;
type
TAnimation_Form = class(TForm)
Image1: TImage;
Timer: TTimer;
Exit: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure TimerTimer(Sender: TObject);
procedure ExitClick(Sender: TObject);
private
{ Private declarations }
Image_Counter: Integer;
Images: array[0..29] of TPNGImage;
public
{ Public declarations }
end;
procedure Run_Animation_Form();
procedure Finish_Animation_Form();
implementation
var
Animation_Form: TAnimation_Form = nil;
{$R *.dfm}
procedure Finish_Animation_Form();
Begin
if Animation_Form <> nil then
Animation_Form.Close;
End;
procedure Run_Animation_Form();
Begin
Animation_Form := TAnimation_Form.Create(nil);
Try
Animation_Form.ShowModal();
Finally
FreeAndNil(Animation_Form);
End;
End;
{ TAnimation_Form }
procedure TAnimation_Form.FormCreate(Sender: TObject);
var
I: Integer;
begin
for I := Low(Images) to High(Images) do
begin
Images[I] := TPNGImage.Create;
// load PNG image into Images[I] as needed...
end;
// FYI, these properties can be set at design time...
TransparentColor := True;
TransparentColorValue := Color;
Image1.Visible := True;
BorderWidth := 10;
Anchors := [akLeft, akTop, akBottom, akRight];
Image_Counter := 0;
Image1.Picture := Images[0];
ControlStyle := ControlStyle - [csOpaque];
end;
procedure TAnimation_Form.FormDestroy(Sender: TObject);
var
I: Integer;
begin
for I := Low(Images) to High(Images) do
Images[I].Free;
end;
procedure TAnimation_Form.ExitClick(Sender: TObject);
begin
Close;
end;
procedure TAnimation_Form.TimerTimer(Sender: TObject);
begin
Inc(Image_Counter);
if Image_Counter > High(Images) then
Image_Counter := 0;
Image1.Picture := Images[Image_Counter];
end;
end.
use a single TPaintBox and assign an OnPaint event handler to it that draws the current PNG onto the TPaintBox.Canvas, and then have the TTimer simply update the current PNG and call TPaintBox.Invalidate() to trigger a repaint:
unit Animation;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, AdvShaper, pngimage, ExtCtrls, StdCtrls;
type
TAnimation_Form = class(TForm)
PaintBox1: TPaintBox;
Timer: TTimer;
Exit: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure TimerTimer(Sender: TObject);
procedure ExitClick(Sender: TObject);
procedure PaintBox1Paint(Sender: TObject);
private
{ Private declarations }
Image_Counter: Integer;
Images: array[0..29] of TPNGImage;
public
{ Public declarations }
end;
procedure Run_Animation_Form();
procedure Finish_Animation_Form();
implementation
var
Animation_Form: TAnimation_Form = nil;
{$R *.dfm}
procedure Finish_Animation_Form();
Begin
if Animation_Form <> nil then
Animation_Form.Close;
End;
procedure Run_Animation_Form();
Begin
Animation_Form := TAnimation_Form.Create(nil);
Try
Animation_Form.ShowModal();
Finally
FreeAndNil(Animation_Form);
End;
End;
{ TAnimation_Form }
procedure TAnimation_Form.FormCreate(Sender: TObject);
var
I: Integer;
begin
for I := Low(Images) to High(Images) do
begin
Images[I] := TPNGImage.Create;
// load PNG image into Images[I] as needed...
end;
// FYI, these properties can be set at design time...
TransparentColor := True;
TransparentColorValue := Color;
Image1.Visible := True;
BorderWidth := 10;
Anchors := [akLeft, akTop, akBottom, akRight];
Image_Counter := 0;
ControlStyle := ControlStyle - [csOpaque];
end;
procedure TAnimation_Form.FormDestroy(Sender: TObject);
var
I: Integer;
begin
for I := Low(Images) to High(Images) do
Images[I].Free;
end;
procedure TAnimation_Form.ExitClick(Sender: TObject);
begin
Close;
end;
procedure TAnimation_Form.TimerTimer(Sender: TObject);
begin
Inc(Image_Counter);
if Image_Counter > High(Images) then
Image_Counter := 0;
PaintBox1.Invalidate;
end;
procedure TAnimation_Form.PaintBox1Paint(Sender: TObject);
begin
PaintBox1.Canvas.Draw(0, 0, Images[Image_Counter]);
// or:
// PaintBox1.Canvas.StretchDraw(Rect(0, 0, PaintBox1.Width, PaintBox1.Height), Images[Image_Counter]);
end;
end.
I have two scenarios. One works, one does not. The first (the one that works) invloves a scrollbox sitting directly on a form that when a button is pushed it executes this code:
procedure TForm1.Button2Click(Sender: TObject);
begin
DrawPanel;
end;
procedure TForm1.DrawPanel;
begin
BuildPanel; //Resides on a seperate unit code pasted below
TestPanel.Height := 40;
TestPanel.Width := 100;
TestPanel.Left := Trunc(ScrollBox1.Width / 2) - Trunc(TestPanel.Width / 2);
TestPanel.Top := Trunc(ScrollBox1.Height / 2) - Trunc(TestPanel.Height / 2);
TestPanel.Visible := True;
TestPanel.Parent := ScrollBox1;
end;
unit Unit3;
interface
uses ExtCtrls;
Var
TestPanel : Tpanel;
Procedure BuildPanel;
implementation
procedure BuildPanel;
begin
TestPanel := TPanel.Create(Nil);
end;
end.
The code is identical except for a small difference in the second scenario. The scrollbox sits on a frame that is added to the Templates palette and then dropped down on the form. The button click calls:
procedure TForm1.Button1Click(Sender: TObject);
begin
TestFrame.DrawPanel;
end;
procedure TTestFrame.DrawPanel;
begin
BuildPanel; //Still points to the unit3 code above
TestPanel.Height := 40;
TestPanel.Width := 100;
TestPanel.Left := Trunc(ScrollBox1.Width / 2) - Trunc(TestPanel.Width / 2);
TestPanel.Top := Trunc(ScrollBox1.Height / 2) - Trunc(TestPanel.Height / 2);
TestPanel.Visible := True;
TestPanel.Parent := ScrollBox1;
end;
However the panel will not display in the scrollbox that sits on the frame, when triggered at runtime. I'm not really sure why, can anybody help out? I hope I was specific enough in my question, let me know if anything is unclear. Thanks in advance.
Here's all the code in order.....Hopefully it make it more clear:
//This is the form
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, Unit2, Unit3;
type
TForm1 = class(TForm)
Button1: TButton;
TTestFrame1: TTestFrame;
ScrollBox1: TScrollBox;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
TestFrame: TTestFrame;
Procedure DrawPanel;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
TestFrame.DrawPanel;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
DrawPanel;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
TestFrame.Free;
end;
procedure TForm1.FormShow(Sender: TObject);
begin
TestFrame := TTestFrame.Create(Form1);
end;
procedure TForm1.DrawPanel;
begin
BuildPanel;
TestPanel.Height := 40;
TestPanel.Width := 100;
TestPanel.Left := Trunc(ScrollBox1.Width / 2) - Trunc(TestPanel.Width / 2);
TestPanel.Top := Trunc(ScrollBox1.Height / 2) - Trunc(TestPanel.Height / 2);
TestPanel.Visible := True;
TestPanel.Parent := ScrollBox1;
end;
end.
//This is the frame
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Unit3;
type
TTestFrame = class(TFrame)
ScrollBox1: TScrollBox;
private
{ Private declarations }
public
{ Public declarations }
Procedure DrawPanel;
end;
implementation
{$R *.dfm}
{ TTestFrame }
procedure TTestFrame.DrawPanel;
begin
BuildPanel;
TestPanel.Height := 40;
TestPanel.Width := 100;
TestPanel.Left := Trunc(ScrollBox1.Width / 2) - Trunc(TestPanel.Width / 2);
TestPanel.Top := Trunc(ScrollBox1.Height / 2) - Trunc(TestPanel.Height / 2);
TestPanel.Visible := True;
TestPanel.Parent := ScrollBox1;
end;
end.
//This is the unit that mocks my data structure
//In reality it creates an Array of Tpanel that is part of a class.
unit Unit3;
interface
uses ExtCtrls;
Var
TestPanel : Tpanel;
Procedure BuildPanel;
implementation
procedure BuildPanel;
begin
TestPanel := TPanel.Create(Nil);
end;
end.
You just forgot to assign a parent to your dynamic created TestFrame.
My program stays running if I click the X in the top right hand corner of the form. This also happens within Delphi 4 and I am then forced to do a Program Reset as it will not recomplie if i don't.
Main form code:
unit Unit3;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
type
TMainForm = class(TForm)
NewButton: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
Button6: TButton;
ExitButton: TButton;
LockButton: TButton;
SettingsButton: TButton;
Label1: TLabel;
TimeLabel: TLabel;
Timer1: TTimer;
procedure ExitButtonClick(Sender: TObject);
procedure LockButtonClick(Sender: TObject);
procedure SettingsButtonClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure NewButtonClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
uses Unit2, Unit1, Unit4;
{$R *.DFM}
procedure TMainForm.ExitButtonClick(Sender: TObject);
begin
if MessageBox(0, 'Are you sure you want to quit?', 'Exit Program?', +mb_YesNo +mb_ICONWARNING) = 6 then
Application.Terminate
else
end;
procedure TMainForm.LockButtonClick(Sender: TObject);
begin
MainForm.Hide;
Login.Show;
Login.LockLabel.Visible := true;
end;
procedure TMainForm.SettingsButtonClick(Sender: TObject);
begin
MainForm.Hide;
Settings.Show;
end;
procedure TMainForm.Timer1Timer(Sender: TObject);
begin
TimeLabel.Caption := TimeToStr(time);
end;
procedure TMainForm.NewButtonClick(Sender: TObject);
begin
TransForm.Show;
MainForm.Hide;
end;
end.
Login Form code:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Mask, inifiles, Unit1;
type
TLogin = class(TForm)
PassEdit: TMaskEdit;
LoginButton: TButton;
PassLabel: TLabel;
InvisiButton: TButton;
LockLabel: TLabel;
procedure PassEditClick(Sender: TObject);
procedure LoginButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Login: TLogin;
IniFile : TIniFile;
appINI : TIniFile;
Password : string;
implementation
uses Unit3;
{$R *.DFM}
procedure TLogin.PassEditClick(Sender: TObject);
begin
PassEdit.Text := '';
end;
procedure TLogin.LoginButtonClick(Sender: TObject);
begin
if Password = PassEdit.Text then begin
Login.Hide;
MainForm.Show;
LockLabel.Visible := false;
end
else
showmessage('Incorrect Password!')
end;
procedure TLogin.FormCreate(Sender: TObject);
begin
appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
Password := appINI.ReadString('Login','Password','');
appINI.Free;
end;
end.
Setting Form Code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, inifiles;
type
TSettings = class(TForm)
SaveButton: TButton;
AEditA: TEdit;
AEditB: TEdit;
SEditB: TEdit;
PEditB: TEdit;
PLabelA: TLabel;
SLabelA: TLabel;
ALabelA: TLabel;
PEditA: TEdit;
SEditA: TEdit;
BackButton: TButton;
SettingsLabel: TLabel;
ALabelB: TLabel;
SLabelB: TLabel;
PLabelB: TLabel;
AReserveLabel: TLabel;
BReserveLabel: TLabel;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
Label8: TLabel;
Label7: TLabel;
procedure SaveButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure BackButtonClick(Sender: TObject);
procedure AEditAKeyPress(Sender: TObject; var Key: Char);
procedure AEditBKeyPress(Sender: TObject; var Key: Char);
procedure SEditAKeyPress(Sender: TObject; var Key: Char);
procedure SEditBKeyPress(Sender: TObject; var Key: Char);
procedure PEditAKeyPress(Sender: TObject; var Key: Char);
procedure PEditBKeyPress(Sender: TObject; var Key: Char);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Settings: TSettings;
IniFile : TIniFile;
appINI : TIniFile;
APriceA : String;
SPriceA : String;
PPriceA : String;
APriceB : String;
SPriceB : String;
PPriceB : String;
change : boolean;
implementation
uses Unit3, Unit2;
{$R *.DFM}
procedure TSettings.SaveButtonClick(Sender: TObject);
//Save Button
begin
appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
APriceA := (AEditA.Text);
SPriceA := (SEditA.Text);
PPriceA := (PEditA.Text);
APriceB := (AEditB.Text);
SPriceB := (SEditB.Text);
PPriceB := (PEditB.Text);
appINI.WriteString('PricesA','Adult',APriceA);
appINI.WriteString('PricesA','Student',SPriceA);
appINI.WriteString('PricesA','Pensioner',PPriceA);
appINI.WriteString('PricesB','Adult',APriceB);
appINI.WriteString('PricesB','Student',SPriceB);
appINI.WriteString('PricesB','Pensioner',PPriceB);
appINI.Free;
ShowMessage('Settings Saved Successfully!');
change := false;
end;
procedure TSettings.FormCreate(Sender: TObject);
//Displays values as the form is created
begin
appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
APriceA := appINI.ReadString('PricesA','Adult','');
SPriceA := appINI.ReadString('PricesA','Student','');
PPriceA := appINI.ReadString('PricesA','Pensioner','');
APriceB := appINI.ReadString('PricesB','Adult','');
SPriceB := appINI.ReadString('PricesB','Student','');
PPriceB := appINI.ReadString('PricesB','Pensioner','');
appINI.Free;
AEditA.Text := (APriceA);
SEditA.Text := (SPriceA);
PEditA.Text := (PPriceA);
AEditB.Text := (APriceB);
SEditB.Text := (SPriceB);
PEditB.Text := (PPriceB);
end;
procedure TSettings.BackButtonClick(Sender: TObject);
//Exit Button
begin
if MessageBox(0, 'Are you sure you want to quit?', 'Exit Program?', +mb_YesNo +mb_ICONWARNING) = 6 then begin
if Change = (true) then
begin
if MessageBox(0, 'Save Changes?', 'Save Changes?', +mb_YesNo +mb_ICONWARNING) = 6 then
begin
appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
APriceA := (AEditA.Text);
SPriceA := (SEditA.Text);
PPriceA := (PEditA.Text);
APriceB := (AEditB.Text);
SPriceB := (SEditB.Text);
PPriceB := (PEditB.Text);
appINI.WriteString('PricesA','Adult',APriceA);
appINI.WriteString('PricesA','Student',SPriceA);
appINI.WriteString('PricesA','Pensioner',PPriceA);
appINI.WriteString('PricesB','Adult',APriceB);
appINI.WriteString('PricesB','Student',SPriceB);
appINI.WriteString('PricesB','Pensioner',PPriceB);
appINI.Free;
ShowMessage('Settings Saved Successfully!');
Settings.Hide;
MainForm.Show;
change := false;
end
else
change := false;
MainForm.Show;
Settings.Hide;
end
else
MainForm.Show;
Settings.Hide;
end
else
end;
procedure TSettings.AEditAKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
change := true;
s := ('1234567890.'#8); //Add chars you want to allow
if pos(key,s) =0 then begin
Key:=#0;
showmessage('Only Numbers are allowed. Include cents!');
end;
end;
procedure TSettings.AEditBKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
change := true;
s := ('1234567890.'#8); //Add chars you want to allow
if pos(key,s) =0 then begin
Key:=#0;
showmessage('Only Numbers are allowed. Include cents!');
end;
end;
procedure TSettings.SEditAKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
change := true;
s := ('1234567890.'#8); //Add chars you want to allow
if pos(key,s) =0 then begin
Key:=#0;
showmessage('Only Numbers are allowed. Include cents!');
end;
end;
procedure TSettings.SEditBKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
change := true;
s := ('1234567890.'#8); //Add chars you want to allow
if pos(key,s) =0 then begin
Key:=#0;
showmessage('Only Numbers are allowed. Include cents!');
end;
end;
procedure TSettings.PEditAKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
change := true;
s := ('1234567890.'#8); //Add chars you want to allow
if pos(key,s) =0 then begin
Key:=#0;
showmessage('Only Numbers are allowed. Include cents!');
end;
end;
procedure TSettings.PEditBKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
change := true;
s := ('1234567890.'#8); //Add chars you want to allow
if pos(key,s) =0 then begin
Key:=#0;
showmessage('Only Numbers are allowed. Include cents!');
end;
end;
//End of Settings
procedure TSettings.Button1Click(Sender: TObject);
begin
Settings.hide;
end;
end.
Project Data:
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Settings},
Unit2 in 'Unit2.pas' {Login},
Unit3 in 'Unit3.pas' {MainForm},
Unit4 in '..\Write to ini\Unit4.pas' {TransForm};
{$R *.RES}
begin
Application.Initialize;
Application.CreateForm(TLogin, Login);
Application.CreateForm(TMainForm, MainForm);
Application.CreateForm(TSettings, Settings);
Application.Run;
end.
When i close the application it stays running, can you help me fix this?
As David said, your TLogin form is being set as Application.MainForm because it is the first form create by Application.CreateForm(). You are simply hiding the TLogin form, not closing it, which is why your app does not fully exit. When you close the TMainForm form, the TLogin form is still running.
Given the code you have shown, your TMainForm form should be the only one created with Application.CreateForm(). All of your other forms should be created on an as-needed basis instead.
You have also coded Unit1, Unit2, and Unit3 (what is Unit4?) to be inter-dependant on each other when they do not need to be, so you should remove that dependancy as well. The TLogin and TSettings units should be standalone units.
Try something more like this instead:
Main form:
unit Unit3;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
type
TMainForm = class(TForm)
NewButton: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
Button6: TButton;
ExitButton: TButton;
LockButton: TButton;
SettingsButton: TButton;
Label1: TLabel;
TimeLabel: TLabel;
Timer1: TTimer;
procedure FormCreate(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure ExitButtonClick(Sender: TObject);
procedure LockButtonClick(Sender: TObject);
procedure SettingsButtonClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure NewButtonClick(Sender: TObject);
protected
procedure WndProc(var Message: TMessage); override;
private
{ Private declarations }
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
uses
Unit2, Unit1, Unit4;
{$R *.DFM}
const
WM_LOCK = WM_USER + 100;
procedure TMainForm.FormCreate(Sender: TObject);
begin
PostMessage(Handle, WM_LOCK, 0, 0);
end;
procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
if Application.MessageBox('Are you sure you want to quit?', 'Exit Program?', MB_YESNO or MB_ICONWARNING) <> IDYES then
CanClose := False;
end;
procedure TMainForm.WndProc(var Message: TMessage);
begin
if Message.Msg = WM_LOCK then
LockButtonClick(nil)
else
inherited;
end;
procedure TMainForm.ExitButtonClick(Sender: TObject);
begin
Close;
end;
procedure TMainForm.LockButtonClick(Sender: TObject);
var
Login: TLogin;
begin
Login := TLogin.Create(nil);
try
Hide;
Login.LockLabel.Visible := True;
if Login.ShowModal = mrOk then
Show
else
Application.Terminate;
finally
Login.Free;
end;
end;
procedure TMainForm.SettingsButtonClick(Sender: TObject);
var
Settings: TSettings;
begin
Settings := TSettings.Create(nil);
try
Settings.ShowModal;
finally
Settings.Free;
end;
end;
procedure TMainForm.Timer1Timer(Sender: TObject);
begin
TimeLabel.Caption := TimeToStr(time);
end;
procedure TMainForm.NewButtonClick(Sender: TObject);
begin
TransForm.Show;
Hide;
end;
end.
Login form:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Mask;
type
TLogin = class(TForm)
PassEdit: TMaskEdit;
LoginButton: TButton;
PassLabel: TLabel;
InvisiButton: TButton;
LockLabel: TLabel;
procedure PassEditClick(Sender: TObject);
procedure LoginButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
implementation
uses
inifiles;
var
Password : string;
{$R *.DFM}
procedure TLogin.FormCreate(Sender: TObject);
var
appINI : TIniFile;
begin
appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
try
Password := appINI.ReadString('Login','Password','');
finally
appINI.Free;
end;
end;
procedure TLogin.PassEditClick(Sender: TObject);
begin
PassEdit.Text := '';
end;
procedure TLogin.LoginButtonClick(Sender: TObject);
begin
if Password <> PassEdit.Text then
begin
ShowMessage('Incorrect Password!')
Exit;
end;
LockLabel.Visible := False;
ModalResult = mrOk;
end;
end.
Settings Form:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TSettings = class(TForm)
SaveButton: TButton;
AEditA: TEdit;
AEditB: TEdit;
SEditB: TEdit;
PEditB: TEdit;
PLabelA: TLabel;
SLabelA: TLabel;
ALabelA: TLabel;
PEditA: TEdit;
SEditA: TEdit;
BackButton: TButton;
SettingsLabel: TLabel;
ALabelB: TLabel;
SLabelB: TLabel;
PLabelB: TLabel;
AReserveLabel: TLabel;
BReserveLabel: TLabel;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
Label8: TLabel;
Label7: TLabel;
procedure SaveButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure BackButtonClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
function Changed: Boolean;
function SaveSettings: Boolean;
public
{ Public declarations }
end;
var
APriceA : String;
SPriceA : String;
PPriceA : String;
APriceB : String;
SPriceB : String;
PPriceB : String;
implementation
uses
inifiles;
{$R *.DFM}
procedure LoadSettings;
var
appINI: TIniFile;
begin
appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
try
APriceA := appINI.ReadString('PricesA','Adult','');
SPriceA := appINI.ReadString('PricesA','Student','');
PPriceA := appINI.ReadString('PricesA','Pensioner','');
APriceB := appINI.ReadString('PricesB','Adult','');
SPriceB := appINI.ReadString('PricesB','Student','');
PPriceB := appINI.ReadString('PricesB','Pensioner','');
finally
appINI.Free;
end;
end;
procedure TSettings.FormCreate(Sender: TObject);
begin
AEditA.Text := APriceA;
AEditA.Modified := False;
SEditA.Text := SPriceA;
SEditA.Modified := False;
PEditA.Text := PPriceA;
PEditA.Modified := False;
AEditB.Text := APriceB;
AEditB.Modified := False;
SEditB.Text := SPriceB;
SEditB.Modified := False;
PEditB.Text := PPriceB;
PEditB.Modified := False;
end;
function TSettings.Changed: Boolean;
begin
Result := AEditA.Modified or
SEditA.Modified or
PEditA.Modified or
AEditB.Modified or
SEditB.Modified or
PEditB.Modified;
end;
function TSettings.SaveSettings: Boolean;
var
dbl: Double;
begin
Result := TryStrToFloat(AEditA.Text, dbl) and
TryStrToFloat(SEditA.Text, dbl) and
TryStrToFloat(PEditA.Text, dbl) and
TryStrToFloat(AEditB.Text, dbl) and
TryStrToFloat(SEditB.Text, dbl) and
TryStrToFloat(PEditB.Text, dbl);
if not Result then
begin
ShowMessage('Only Numbers are allowed. Include cents!');
Exit;
end;
APriceA := AEditA.Text;
SPriceA := SEditA.Text;
PPriceA := PEditA.Text;
APriceB := AEditB.Text;
SPriceB := SEditB.Text;
PPriceB := PEditB.Text;
appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
try
appINI.WriteString('PricesA','Adult',APriceA);
appINI.WriteString('PricesA','Student',SPriceA);
appINI.WriteString('PricesA','Pensioner',PPriceA);
appINI.WriteString('PricesB','Adult',APriceB);
appINI.WriteString('PricesB','Student',SPriceB);
appINI.WriteString('PricesB','Pensioner',PPriceB);
finally
appINI.Free;
end;
AEditA.Modified := False;
SEditA.Modified := False;
PEditA.Modified := False;
AEditB.Modified := False;
SEditB.Modified := False;
PEditB.Modified := False;
ShowMessage('Settings Saved Successfully!');
Result := True;
end;
procedure TSettings.SaveButtonClick(Sender: TObject);
begin
SaveSettings;
end;
procedure TSettings.BackButtonClick(Sender: TObject);
begin
if Changed then
begin
if Application.MessageBox('Save Changes?', 'Save Changes?', MB_YESNO or MB_ICONWARNING) = IDYES then
begin
if not SaveSettings then
Exit;
end;
end;
ModalResult = mrOk;
end;
procedure TSettings.Button1Click(Sender: TObject);
begin
Close;
end;
initialization
LoadSettings;
end.
Project:
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Settings},
Unit2 in 'Unit2.pas' {Login},
Unit3 in 'Unit3.pas' {MainForm},
Unit4 in '..\Write to ini\Unit4.pas' {TransForm};
{$R *.RES}
begin
Application.Initialize;
Application.CreateForm(TMainForm, MainForm);
Application.ShowMainForm := False;
Application.Run;
end.
The easiest way to to this would be to be in a close button with just one line of code:
BtnClose.click
Begin
Application.terminate;
End;
Hope that helps
Using DSPack, Delphi XE I need to take a snapshot from a webcam and allow a preview before which the user is allowed to save to JPEG file. How can this be done (code)?
Maybe this will work, but I have not tested it. You should give it a try.
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DSPack, DSUtil, DirectShow9;
type
TMainForm = class(TForm)
CaptureGraph: TFilterGraph;
VideoWindow: TVideoWindow;
ListBox1: TListBox;
VideoSourceFilter: TFilter;
StartButton: TButton;
StopButton: TButton;
Label1: TLabel;
ListBox2: TListBox;
Label3: TLabel;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
procedure StartButtonClick(Sender: TObject);
procedure StopButtonClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
MainForm: TMainForm;
VideoDevice: TSysDevEnum;
VideoMediaTypes: TEnumMediaType;
implementation
{$R *.dfm}
{ TMainForm }
procedure TMainForm.FormCreate(Sender: TObject);
var i: integer;
begin
VideoDevice := TSysDevEnum.Create(CLSID_VideoInputDeviceCategory);
for i := 0 to VideoDevice.CountFilters - 1 do
ListBox1.Items.Add(VideoDevice.Filters[i].FriendlyName);
VideoMediaTypes := TEnumMediaType.Create;
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
VideoDevice.Free;
VideoMediaTypes.Free;
end;
// Selecting of the video source
procedure TMainForm.ListBox1Click(Sender: TObject);
var
PinList: TPinList;
i: integer;
begin
VideoDevice.SelectGUIDCategory(CLSID_VideoInputDeviceCategory);
if ListBox1.ItemIndex <> -1 then
begin
// Set the device which we work with
VideoSourceFilter.BaseFilter.Moniker := VideoDevice.GetMoniker(ListBox1.ItemIndex);
VideoSourceFilter.FilterGraph := CaptureGraph;
CaptureGraph.Active := true;
PinList := TPinList.Create(VideoSourceFilter as IBaseFilter);
ListBox2.Clear;
VideoMediaTypes.Assign(PinList.First);
// Adding permission to ListBox2, which supports device
for i := 0 to VideoMediaTypes.Count - 1 do
ListBox2.Items.Add(VideoMediaTypes.MediaDescription[i]);
CaptureGraph.Active := false;
PinList.Free;
StartButton.Enabled := true;
end;
end;
procedure TMainForm.StartButtonClick(Sender: TObject);
var
PinList: TPinList;
begin
// Activating graph filter, at this stage the source filter is added to the graph
CaptureGraph.Active := true;
// The configuration of the output device
if VideoSourceFilter.FilterGraph <> nil then
begin
PinList := TPinList.Create(VideoSourceFilter as IBaseFilter);
if ListBox2.ItemIndex <> -1 then
with (PinList.First as IAMStreamConfig) do
SetFormat(VideoMediaTypes.Items[ListBox2.ItemIndex].AMMediaType^);
PinList.Free;
end;
// now render streams
with CaptureGraph as IcaptureGraphBuilder2 do
begin
// Hooking up a preview video (VideoWindow)
if VideoSourceFilter.BaseFilter.DataLength > 0 then
RenderStream(#PIN_CATEGORY_PREVIEW, nil, VideoSourceFilter as IBaseFilter,
nil , VideoWindow as IBaseFilter);
end;
// Launch video
CaptureGraph.Play;
StopButton.Enabled := true;
StartButton.Enabled := false;
ListBox2.Enabled := false;
ListBox1.Enabled := false;
end;
// Stop video
procedure TMainForm.StopButtonClick(Sender: TObject);
begin
StopButton.Enabled := false;
StartButton.Enabled := true;
CaptureGraph.Stop;
CaptureGraph.Active := False;
ListBox2.Enabled := true;
ListBox1.Enabled := true;
end;
end.
This question springs from an earlier one. Most of the code is from suggested answers that probably worked in later versions of Delphi. In D2006 I don't get the full range of opacity, and the transparent part of the image shows as white.
Image is from http://upload.wikimedia.org/wikipedia/commons/6/61/Icon_attention_s.png.
It is loaded from the PNGImageCollection into the TImage at run-time because I have found you have to do this as the image doesn't remain intact after the DFM is saved. For the purposes of demonstrating the behaviour you probably don't need the PNGImageCollection and can just load the PNG image into the TImage at design time and then run it from the IDE.
There are four buttons on the form - each one sets a different value of opacity. Opacity=0 works fine (paintbox image is not visible, opacity=16 looks OK except for the white background, opacity=64, 255 are similar - the opacity seems to saturate at around 10%.
Any ideas as to what's up?
unit Unit18;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, pngimage, StdCtrls, Spin, PngImageList;
type
TAlphaBlendForm = class(TForm)
PaintBox1: TPaintBox;
Image1: TImage;
PngImageCollection1: TPngImageCollection;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
procedure PaintBox1Paint(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
private
FOpacity : Integer ;
FBitmap : TBitmap ;
{ Private declarations }
public
{ Public declarations }
end;
var
AlphaBlendForm: TAlphaBlendForm;
implementation
{$R *.dfm}
procedure TAlphaBlendForm.Button1Click(Sender: TObject);
begin
FOpacity:= 0 ;
PaintBox1.Invalidate;
end;
procedure TAlphaBlendForm.Button2Click(Sender: TObject);
begin
FOpacity:= 16 ;
PaintBox1.Invalidate;
end;
procedure TAlphaBlendForm.Button3Click(Sender: TObject);
begin
FOpacity:= 64 ;
PaintBox1.Invalidate;
end;
procedure TAlphaBlendForm.Button4Click(Sender: TObject);
begin
FOpacity:= 255 ;
PaintBox1.Invalidate;
end;
procedure TAlphaBlendForm.FormCreate(Sender: TObject);
begin
Image1.Picture.Assign (PngImageCollection1.Items [0].PNGImage) ;
FBitmap := TBitmap.Create;
FBitmap.Assign(Image1.Picture.Graphic);//Image1 contains a transparent PNG
FBitmap.PixelFormat := pf32bit ;
PaintBox1.Width := FBitmap.Width;
PaintBox1.Height := FBitmap.Height;
end;
procedure TAlphaBlendForm.PaintBox1Paint(Sender: TObject);
var
fn: TBlendFunction;
begin
fn.BlendOp := AC_SRC_OVER;
fn.BlendFlags := 0;
fn.SourceConstantAlpha := FOpacity;
fn.AlphaFormat := AC_SRC_ALPHA;
Windows.AlphaBlend(
PaintBox1.Canvas.Handle,
0,
0,
PaintBox1.Width,
PaintBox1.Height,
FBitmap.Canvas.Handle,
0,
0,
FBitmap.Width,
FBitmap.Height,
fn
);
end;
end.
** This code (using graphics32 TImage32) almost works **
unit Unit18;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, pngimage, StdCtrls, Spin, PngImageList, GR32_Image;
type
TAlphaBlendForm = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Image321: TImage32;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
AlphaBlendForm: TAlphaBlendForm;
implementation
{$R *.dfm}
procedure TAlphaBlendForm.Button1Click(Sender: TObject);
begin
Image321.Bitmap.MasterAlpha := 0 ;
end;
procedure TAlphaBlendForm.Button2Click(Sender: TObject);
begin
Image321.Bitmap.MasterAlpha := 16 ;
end;
procedure TAlphaBlendForm.Button3Click(Sender: TObject);
begin
Image321.Bitmap.MasterAlpha := 64 ;
end;
procedure TAlphaBlendForm.Button4Click(Sender: TObject);
begin
Image321.Bitmap.MasterAlpha := 255 ;
end;
end.
** (UPDATE) This code (using graphics32 TImage32) DOES work **
The following code is successful in assigning a PNG image to the Graphics32.TImage32 at run-time. The PNG image with alpha channel is loaded into a TPNGImageCollection (really useful component as it allows mixtures of images of arbitrary size) at design time. On form creation it is written to a stream, then read from the stream into the Image32 using LoadPNGintoBitmap32. Once this is done I can control the opacity by assigning to TImage32.Bitmap.MasterAlpha. No bothering with OnPaint handlers.
procedure TAlphaBlendForm.FormCreate(Sender: TObject);
var
FStream : TMemoryStream ;
AlphaChannelUsed : boolean ;
begin
FStream := TMemoryStream.Create ;
try
PngImageCollection1.Items [0].PngImage.SaveToStream (FStream) ;
FStream.Position := 0 ;
LoadPNGintoBitmap32 (Image321.Bitmap, FStream, AlphaChannelUsed) ;
finally
FStream.Free ;
end;
end ;
As David commented to the question, the alpha channel information is lost when you assign the graphic to the bitmap. As such there's no point in setting the pixel format to pf32bit after the assignment, apart from preventing AlphaBlend call to fail, there's no per-pixel alpha in the bitmap anyway.
But the png object knows how to draw on a canvas taking into consideration the transparency information. So the solution would involve drawing on the bitmap canvas instead of assigning the graphic, and then, since there's no Alpha channel, remove the AC_SRC_ALPHA flag from the BLENDFUNCTION.
Below is working code here on D2007:
procedure TAlphaBlendForm.FormCreate(Sender: TObject);
begin
Image1.Picture.LoadFromFile(
ExtractFilePath(Application.ExeName) + 'Icon_attention_s.png');
FBitmap := TBitmap.Create;
FBitmap.Width := Image1.Picture.Graphic.Width;
FBitmap.Height := Image1.Picture.Graphic.Height;
FBitmap.Canvas.Brush.Color := Color; // background color for the image
FBitmap.Canvas.FillRect(FBitmap.Canvas.ClipRect);
FBitmap.Canvas.Draw(0, 0, Image1.Picture.Graphic);
PaintBox1.Width := FBitmap.Width;
PaintBox1.Height := FBitmap.Height;
end;
procedure TAlphaBlendForm.PaintBox1Paint(Sender: TObject);
var
fn: TBlendFunction;
begin
fn.BlendOp := AC_SRC_OVER;
fn.BlendFlags := 0;
fn.SourceConstantAlpha := FOpacity;
fn.AlphaFormat := 0;
Windows.AlphaBlend(
PaintBox1.Canvas.Handle,
0,
0,
PaintBox1.Width,
PaintBox1.Height,
FBitmap.Canvas.Handle,
0,
0,
FBitmap.Width,
FBitmap.Height,
fn
);
end;
or without using a intermediate TImage:
procedure TAlphaBlendForm.FormCreate(Sender: TObject);
var
PNG: TPNGObject;
begin
PNG := TPNGObject.Create;
try
PNG.LoadFromFile(ExtractFilePath(Application.ExeName) + 'Icon_attention_s.png');
FBitmap := TBitmap.Create;
FBitmap.Width := PNG.Width;
FBitmap.Height := PNG.Height;
FBitmap.Canvas.Brush.Color := Color;
FBitmap.Canvas.FillRect(FBitmap.Canvas.ClipRect);
PNG.Draw(FBitmap.Canvas, FBitmap.Canvas.ClipRect);
PaintBox1.Width := FBitmap.Width;
PaintBox1.Height := FBitmap.Height;
finally
PNG.Free;
end;
end;