窗体的动画效果的疑问(300分)

  • 主题发起人 主题发起人 Town
  • 开始时间 开始时间
T

Town

Unregistered / Unconfirmed
GUEST, unregistred user!
使用AnimateWindow可以实现几种窗体的动画效果,如:
procedure TForm1.FormShow(Sender: TObject);
var
i:integer;
begin
AnimateWindow(HandLe,80,AW_CENTER);
for i:=0 to ControlCount-1 do
Controls.Refresh;
Form1.BringToFront;
end;

但是, 系统提供的动画效果有限, 而且对操作系统有限制, 如Win95上就不能用。
因此, 我想还是使用自己编写的更好一些。 下面是一位富翁写的代码:
ID=606885
procedure TForm1.Button1Click(Sender: TObject);
var
Rgn,hInRgn,hOutRgn:hrgn;
i:integer;
Rc:Trect;
begin
i:=0;
GetWindowRect(handle,Rc);
hOutRgn:=CreateRectRgn(0,0,Rc.Right-Rc.Left+1,Rc.Bottom-Rc.Top+1);
try
while (i<width div 2) do begin
inc(i);
hInRgn:=CreateRectRgn(Width div 2-i,height div 2 -i,Width div 2+i,height div 2 +i);
try
CombineRgn(hInRgn,hInRgn,hOutRgn,Rgn_And);
SetWindowRgn(Handle,hInRgn,True);
finally
DeleteObject(hInRgn);
end;
end;
finally
DeleteObject(hOutRgn);
end;
end;

我有几个问题:
1、 为什么AnimateWindow可以在OnShow中调用, 而这段代码在OnShow中调用却无效果?
2、 怎样做才行呢?
3、 有没有更好的实现窗体动画的方法?


 
这是程云大侠以前写的一个窗体动画效果的例子.不要意思,借来一用.你看看,若要源文件,
请发信给我.kan@freetrend.com.vn
unit UnFM;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
OleCtrls, SHDocVw, ExtCtrls, StdCtrls, MPlayer;//, Animate, GIFCtrl;

type
TWelcome = class(TForm)
Timer: TTimer;
Image: TImage;
MediaPlayer: TMediaPlayer;
// RxGIF: TRxGIFAnimator;
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure TimerTimer(Sender: TObject);
procedure ImageClick(Sender: TObject);
procedure MediaPlayerNotify(Sender: TObject);
private
{ Private declarations }
procedure showpic(PlayMode:integer;RCode:Integer);
procedure PicOne;
public
{ Public declarations }
procedure MCIPlay(Code:Integer);
end;

var
welcome: TWelcome;
MCIStop:Integer=0;
MessFlag:Integer=0;
PicNum:Integer=1;
ForBmp:Integer=1;
RanCode:Integer=80;
CartCode:Integer=0;
FormH:integer=81;

implementation

uses Unit2;

//uses UnFM;

//uses UnWebBrowser;


{$R *.DFM}

procedure TWelcome.MCIPlay(Code:Integer);
begin
if MCIStop=0 then
begin
MCIStop:=1;
MediaPlayer.Close;
end;

case Code of

0:if FileExists(ExtractFilePath(Application.Exename)+'RunLib/T01.mid') then
begin
MediaPlayer.FileName:=(ExtractFilePath(Application.Exename)+'RunLib/T01.mid');
MediaPlayer.Open;
MediaPlayer.Notify:=true;
MediaPlayer.Play;
end;

1:if FileExists(ExtractFilePath(Application.Exename)+'RunLib/T02.mid') then
begin
MediaPlayer.FileName:=(ExtractFilePath(Application.Exename)+'RunLib/T02.mid');
MediaPlayer.Open;
MediaPlayer.Notify:=true;
MediaPlayer.Play;
end;

2:if FileExists(ExtractFilePath(Application.Exename)+'RunLib/T03.mid') then
begin
MediaPlayer.FileName:=(ExtractFilePath(Application.Exename)+'RunLib/T03.mid');
MediaPlayer.Open;
MediaPlayer.Notify:=true;
MediaPlayer.Play;
end;
end;

MCIStop:=0;
end;

procedure TWelcome.PicOne;
var
newbmp,BmpTemp:TBitmap;
i,j,bmpheight,bmpwidth:integer;
begin
BmpTemp:=TBitmap.Create;
BmpTemp.Width:=image.Width;
BmpTemp.Height:=image.Height;

newbmp:= TBitmap.Create;
newbmp.Width:=image.Width;
newbmp.Height:=image.Height;
bmpheight:=image.Height;
bmpwidth:=image.Width;
BmpTemp.Canvas.StretchDraw(Rect(0,0,bmpwidth,bmpheight),image.Picture.Graphic);
i:=0;
while i<=bmpheight do
begin
j:=i;
while(j >0)do
begin
newbmp.Canvas.CopyRect(Rect(0,j-1,bmpwidth,j),BmpTemp.Canvas,Rect(0,bmpheight-i+j-1,bmpwidth,bmpheight-i+j));
newbmp.Canvas.CopyRect(Rect(0,bmpheight-j,bmpwidth,bmpheight-j+1),BmpTemp.Canvas,Rect(0,i-j,bmpwidth,i-j+1));
j:=j-2;
end;
welcome.Canvas.Draw(0,FormH+0,newbmp);
Sleep(RanCode);
i:=i+2;
end;
newbmp.free;
BmpTemp.Free;
CartCode:=1;
end;

procedure TWelcome.showpic(PlayMode:integer;RCode:Integer);
var
newbmp:TBitmap;
x,y,i,j,k,x1,x2,y1,y2,ynum,xnum,ScrH,ScrW:integer;
begin
newbmp:=TBitmap.Create;
newbmp.Width := Image.Width;
newbmp.Height := Image.Height;
ScrH:=Image.Height;
ScrW:=Image.Width;
newbmp.Canvas.StretchDraw(Rect(0,0,ScrW,ScrH),Image.Picture.Graphic);

case PlayMode of
0:begin //?左向右移?(?x初值?Screen.Width)
x:=ScrW;
while x>0 do
begin
x:=x-10;
welcome.Canvas.CopyRect(Rect(x,FormH+0,x+10,FormH+ScrH),newbmp.Canvas,Rect(x,0,x+10,ScrH));
Sleep(RCode);
end;
end;
1:begin //?右向左拉(?x初值?0)
x:=0;
while x<ScrW do
begin
x:=x+10;
welcome.Canvas.CopyRect(Rect(x,FormH+0,x-10,FormH+ScrH),newbmp.Canvas,Rect(x,0,x-10,ScrH));
Sleep(RCode);
end;
end;
2:begin //?下向上拉(?y初值?ScrH)
y:=ScrH;
while y>0 do
begin
y:=y-10;
welcome.Canvas.CopyRect(Rect(0,FormH+y,ScrW,FormH+y+10),newbmp.Canvas,Rect(0,y,ScrW,y+10));
Sleep(RCode);
end;
end;
3:begin //?上向下拉(?y初值?0)
y:=0;
while y<ScrH do
begin
y:=y+10;
welcome.Canvas.CopyRect(Rect(0,FormH+y,ScrW,FormH+y-10),newbmp.Canvas,Rect(0,y,ScrW,y-10));
Sleep(RCode);
end;
end;
4:begin //?中?往??拉
x:=ScrW div 2;
x1:=x;
x2:=x;
while x1>0 do
begin
x1:=x1-10;
x2:=x2+10;
welcome.Canvas.CopyRect(Rect(x1,FormH+0,x1+10,FormH+ScrH),newbmp.Canvas,Rect(x1,0,x1+10,ScrH));
welcome.Canvas.CopyRect(Rect(x2,FormH+0,x2-10,FormH+ScrH),newbmp.Canvas,Rect(x2,0,x2-10,ScrH));
Sleep(RCode);
end;
end;
5:begin //???往中?拉
x:=ScrW;
x1:=0;
while x>(x div 2)do
begin
x:=x-10;
x1:=x1+10;
welcome.Canvas.CopyRect(Rect(x,FormH+0,x+10,FormH+ScrH),newbmp.Canvas,Rect(x,0,x+10,ScrH));
welcome.Canvas.CopyRect(Rect(x1,FormH+0,x1-10,FormH+ScrH),newbmp.Canvas,Rect(x1,0,x1-10,ScrH));
Sleep(RCode);
end;
end;
6:begin //????隔拉
x:=ScrW;
x1:=0;
while x>0do
begin
x:=x-10;
x1:=x1+10;
ynum:=ScrH div 20;
for j:=0 to ynum do
begin
welcome.Canvas.CopyRect(Rect(x,FormH+j*20,x+10,FormH+j*20+10),newbmp.Canvas,Rect(x,j*20,x+10,j*20+10));
welcome.Canvas.CopyRect(Rect(x1,FormH+j*20+10,x1-10,FormH+j*20+20),newbmp.Canvas,Rect(x1,j*20+10,x1-10,j*20+20));
end;
Sleep(RCode);
end;
end;
7:begin //?上下?隔拉
y:=ScrH;
y1:=0;
while y>0do
begin
y:=y-10;
y1:=y1+10;
xnum:=ScrW div 20;
for j:=0 to xnum do
begin
welcome.Canvas.CopyRect(Rect(j*20,FormH+y,j*20+10,FormH+y+10),newbmp.Canvas,Rect(j*20,y,j*20+10,y+10));
welcome.Canvas.CopyRect(Rect(j*20+10,FormH+y1,j*20+20,FormH+y1-10),newbmp.Canvas,Rect(j*20+10,y1,j*20+20,y1-10));
end;
Sleep(RCode);
end;
end;
8:begin //?中?往四?拉
x:=ScrW div 2;
y:=ScrH div 2;
y1:=y; y2:=y-2; x1:=x; x2:=x;
while (x1>0) or (y1>0) do
begin
x1:=x1-2; x2:=x2+2;
y1:=y1-2; y2:=y2+2;
welcome.Canvas.CopyRect(Rect(x1,FormH+0,x1+2,FormH+ScrH),newbmp.Canvas,Rect(x1,0,x1+2,ScrH));
welcome.Canvas.CopyRect(Rect(0,FormH+y1,ScrW,FormH+y1+2),newbmp.Canvas,Rect(0,y1,ScrW,y1+2));
welcome.Canvas.CopyRect(Rect(x2,FormH+0,x2-2,FormH+ScrH),newbmp.Canvas,Rect(x2,0,x2-2,ScrH));
welcome.Canvas.CopyRect(Rect(0,FormH+y2,ScrW,FormH+y2+2),newbmp.Canvas,Rect(0,y2,ScrW,y2+2));
Sleep(RCode);
end;
end;
9:begin //?四?往中?拉
x:=ScrW;
y:=ScrH;
x1:=0;y1:=0;
while (x>(x div 2)) or (y>(y div 2))do
begin
x:=x-2; x1:=x1+2;
y:=y-2; y1:=y1+2;
welcome.Canvas.CopyRect(Rect(x,FormH+0,x+2,FormH+ScrH),newbmp.Canvas,Rect(x,0,x+2,ScrH));
welcome.Canvas.CopyRect(Rect(0,FormH+y,ScrW,FormH+y+2),newbmp.Canvas,Rect(0,y,ScrW,y+2));
welcome.Canvas.CopyRect(Rect(x1,FormH+0,x1-2,FormH+ScrH),newbmp.Canvas,Rect(x1,0,x1-2,ScrH));
welcome.Canvas.CopyRect(Rect(0,FormH+y1,ScrW,FormH+y1-2),newbmp.Canvas,Rect(0,y1,ScrW,y1-2));
Sleep(RCode);
end;
end;
10:begin //??克
for i:=0 to ScrW*ScrH div 10 do
begin
j := Random(ScrW div 4)*4;
k := Random(ScrH div 4)*4;
welcome.Canvas.CopyRect(Rect(j,FormH+k,j+4,FormH+k+4),newbmp.Canvas,Rect(j,k,j+4,k+4));
end;
welcome.Canvas.CopyRect(Rect(0,FormH+0,ScrW,FormH+ScrH),newbmp.Canvas,Rect(0,0,ScrW,ScrH));
end;
11:begin //左右?次刷新
x:=0;
while x<(ScrW+6) do
begin
x:=x+6;
welcome.Canvas.CopyRect(Rect(x-3,FormH+0,x-6,FormH+ScrH),newbmp.Canvas,Rect(x-3,0,x-6,ScrH));
Sleep(10);
end;
while (x+6)>0 do
begin
x:=x-6;
welcome.Canvas.CopyRect(Rect(x+3,FormH+0,x+6,FormH+ScrH),newbmp.Canvas,Rect(x+3,0,x+6,ScrH));
Sleep(10);
end;
end;
12:begin //左右?次刷新
x:=ScrW;
while (x+6)>0 do
begin
x:=x-6;
welcome.Canvas.CopyRect(Rect(x+3,FormH+0,x+6,FormH+ScrH),newbmp.Canvas,Rect(x+3,0,x+6,ScrH));
Sleep(10);
end;
while x<(ScrW+6) do
begin
x:=x+6;
welcome.Canvas.CopyRect(Rect(x-3,FormH+0,x-6,FormH+ScrH),newbmp.Canvas,Rect(x-3,0,x-6,ScrH));
Sleep(10);
end;
end;
end;
newbmp.Free;
end;


procedure TWelcome.FormCreate(Sender: TObject);
begin
// RxGIF.Image.LoadFromFile(ExtractFilePath(Application.Exename)+'RunLib/Tit01.GIF');
end;

procedure TWelcome.FormPaint(Sender: TObject);
begin
if MessFlag<>0 then Exit;
if FileExists(ExtractFilePath(Application.Exename)+'RunLib/T01_'+IntToStr(ForBmp)+'.bmp') then
Image.Picture.LoadFromFile(ExtractFilePath(Application.Exename)+'RunLib/T01_'+IntToStr(ForBmp)+'.bmp');
RanCOde:=30+Random(70);
Screen.Cursor:=crHourGlass;
PicOne;
if FileExists(ExtractFilePath(Application.Exename)+'RunLib/T01.mid') then
begin
MediaPlayer.FileName:=ExtractFilePath(Application.Exename)+'RunLib/T01.mid';
MediaPlayer.Open;
MediaPlayer.Play;
end
else
if FileExists(ExtractFilePath(Application.Exename)+'RunLib/T01.wav') then
begin
MediaPlayer.FileName:=ExtractFilePath(Application.Exename)+'RunLib/T01.wav';
MediaPlayer.Open;
MediaPlayer.Play;
end;
MCIPlay(0);
Screen.Cursor:=crHandPoint;
Timer.Enabled:=True;
Image.Visible:=True;
MessFlag:=1;
end;

procedure TWelcome.TimerTimer(Sender: TObject);
begin
Timer.Enabled:=False;
ForBmp:=ForBmp+1;
if FileExists(ExtractFilePath(Application.Exename)+'RunLib/T01_'+IntToStr(ForBmp)+'.bmp') then
begin
Image.Picture.LoadFromFile(ExtractFilePath(Application.Exename)+'RunLib/T01_'+IntToStr(ForBmp)+'.bmp');
end
else
begin
ForBmp:=1;
Image.Picture.LoadFromFile(ExtractFilePath(Application.Exename)+'RunLib/T01_'+IntToStr(ForBmp)+'.bmp');
end;
RanCode:=Random(50);
PicNum:=Random(13);
Screen.Cursor:=crHourGlass;
showpic(PicNum,RanCode);
Screen.Cursor:=crHandPoint;
Timer.Enabled:=True;
end;

procedure TWelcome.ImageClick(Sender: TObject);
begin
if MessFlag=0 then Exit;
MCIStop:=1;
MediaPlayer.Stop;
Timer.Enabled:=False;
welcome.Hide;
Form2.ShowModal;
Close;
end;

procedure TWelcome.MediaPlayerNotify(Sender: TObject);
begin
if MCIStop=1 then Exit;
if MediaPlayer.Mode=mpStopped then
begin
MediaPlayer.Rewind;
MediaPlayer.Play;
end;
MediaPlayer.Notify:=true;
end;
end.
 
AnimateWindow作为WINDOWS提供的API函数是最简便的窗体动画实现方法。
如果想功能更强大,可以用第三方控件。如:http://www.appcontrols.com/demos.html有一个AnimationEffect的DEMO。
使用该函数时要注意避免几点:窗口使用了窗口边界;窗口已经可见仍要显示窗口;窗口已经隐藏仍要隐藏窗口。
如果是以上三种情况之一,该函数就会失效。
当然自己写动画窗体也可以,利用窗体重绘属性即可。
 
您发给我吧, 谢谢啦! town@263.net 我学习学习。

在OnPaint中, 使用MessFlag来控制,只是第一次OnPaint来显示, 这可能是我
第二个问题的答案,呵呵。 我试试看。
 
介绍读煤体的书上都有啊。
 
我在OnPaint中使用, 效果不好。 它先是把Form全部显示出来,
然后再消失, 然后才出现动画效果。 :(
 
同意 YB_unique的观点,使用AnimateWindow受到很多限制的,它只能实现一些普通的动画
建议使用第三方控件
 
To YB_unique:

我觉得, Animation Effect并不是真正的动画窗口。 它好像只是使用了窗口
的Width和Height, 然后, 额外进行一些动画操作, 然后才显示Form; 反之,是
先把Form隐藏之后, 进行动画, 然后关闭程序。
 
由于AnimateWindow在不同的操作系统中效果不一样,所以尽量不要用。
我给你一段代码,拿来就可以用,起作用的就是一个过程,你可以建立一个公用的单元文件,
然后想让哪个窗口实现动画效果,就在哪个单元调用一下,非常不错的!


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
TForm1 = class(TForm)
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

procedure AnimateForm(Form: TForm);
var
Form1: TForm1;

implementation

{$R *.DFM}


procedure AnimateForm(Form: TForm);
var
FDesktopCanvas: TCanvas;
FDesktopHandle: Hwnd;
FDesktopBitmap: TPicture;
SRect: TRect;
aPos1,aPos2,
N,FLeft,FTop: Integer;
KLeft,KTop,KRight,KBottom,
FStep: Double;
begin
FDesktopHandle := 0;
FDesktopBitmap := TPicture.Create;
FDesktopCanvas := TCanvas.Create;
FDesktopBitmap.Bitmap.Width := Screen.Width;
FDesktopBitmap.Bitmap.Height := Screen.Height;

FLeft := Form.Left;
FTop := Form.Top;
if Form.Position = poScreenCenter then
begin
if Form.FormStyle = fsMDIChild then
begin
FLeft := (Application.MainForm.ClientWidth - Form.Width) div 2;
FTop := (Application.MainForm.ClientHeight - Form.Height) div 2;
end else
begin
FLeft := (Screen.Width - Form.Width) div 2;
FTop := (Screen.Height - Form.Height) div 2;
end;
if FLeft < 0 then FLeft := 0;
if FTop < 0 then FTop := 0;
end
else if Form.Position = poDesktopCenter then
begin
if Form.FormStyle = fsMDIChild then
begin
FLeft := (Application.MainForm.ClientWidth - Form.Width) div 2;
FTop := (Application.MainForm.ClientHeight - Form.Height) div 2;
end else
begin
FLeft := (Screen.DesktopWidth - Form.Width) div 2;
FTop := (Screen.DesktopHeight - Form.Height) div 2;
end;
if FLeft < 0 then FLeft := 0;
if FTop < 0 then FTop := 0;
end;

FDesktopCanvas.Handle := GetWindowDC(FDesktopHandle);
SendMessage(FDesktopHandle, WM_PAINT, FDesktopCanvas.Handle, 0);
SRect := Rect(0, 0, Screen.Width, Screen.Height);
FDesktopBitmap.Bitmap.Canvas.CopyRect(SRect,FDesktopCanvas,SRect);

FDesktopCanvas.Brush.Color := clBtnFace;
FDesktopCanvas.Brush.Style := bsClear;
FDesktopCanvas.Pen.Color := clBlack;
FDesktopCanvas.Pen.Width := 1;
//FDesktopCanvas.Pen.Style := psDot;

N := Form.Width div 32;
if N<=0 then
N := 4;

aPos1 := (Form.Width div 2)+FLeft;
aPos2 := (Form.Height div 2)+FTop;
KTop := aPos2; KLeft := aPos1;
KRight := aPos1; KBottom := aPos2;

FStep := Form.Height / Form.Width;
while KLeft>FLeft do
begin
KLeft := KLeft - N;
KTop := KTop - FStep*N;
KRight := KRight + N;
KBottom := KBottom + FStep*N;
if (KLeft<FLeft) or (KTop<FTop+1) then Break;
Sleep(2);
FDesktopCanvas.Rectangle(Trunc(KLeft),Trunc(KTop),Trunc(KRight),Trunc(KBottom));
BitBlt(FDesktopCanvas.Handle,Trunc(KLeft)+2,Trunc(KTop)+2,
Trunc(KRight-KLeft)-4,Trunc(KBottom-KTop)-4,
FDesktopBitmap.Bitmap.Canvas.Handle,Trunc(KLeft)+2,Trunc(KTop)+2,SRCCOPY);

end;
{BitBlt(FDesktopCanvas.Handle,FLeft,FTop,Width,Height,
FDesktopBitmap.Canvas.Handle,FLeft,FTop,SRCCOPY);}
ReleaseDC(0, FDesktopCanvas.Handle);
FDesktopBitmap.Free;
FDesktopCanvas.Free;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
AnimateForm(Self);
end;

end.
 
确实不错, 我先学习学习,呵呵。

能否帮我回答第一个问题呢? 然后就给大家发奖金了,呵呵 :)
 
因为formshow的事件中窗体还没有显示出来,所以设边界不行.
 
收到! 发奖金咯!
 
后退
顶部