窗体动画怎样实现???(200分)

  • 主题发起人 主题发起人 xFairy
  • 开始时间 开始时间
X

xFairy

Unregistered / Unconfirmed
GUEST, unregistred user!
我刚学编程不久,但却爱探索高难度问题(只对我而言是高难度),当然难不到各位Delphi前辈.
我想实现像Office助手那样的程序,窗体不但是不规则的,而且还会有动画效果,但是不能用透明窗体的方法实现,而是真正的不规则窗体,不知道应该怎样实现?
我已经尽了最大的努力来实现,但是窗体动画时,太闪耀了,且拖动窗体时窗体上会看不到图像,我真的不知道该怎样做.
以下是我实现的方法:
图像与图像的Mask都放在资源文件ResImages.res中,ID分别从1到15.
Timer1的Interval = 200.
var
Form1: TForm1;
bmp: TBitmap;
MaskFile: TResourceStream;
RgnSize: integer;
RgnData: pRgndata;
Region: hrgn;
i: integer;

implementation

{$R ResImages.res}

procedure TForm1.Timer1Timer(Sender: TObject);
begin
i := (i + 1);
//循环ID值实现动画
bmp := TBitmap.Create;
bmp.LoadFromResourceID(hInstance,i);
//从资源文件读取图像
Image1.Picture.Graphic := bmp;
//Image1显示图像
MaskFile := TResourceStream.CreateFromID(HInstance,i,'Mask');
//从资源文件读取图像Mask
MaskFile.read (RgnSize,4);
Getmem(RgnData,RgnSize);
MaskFile.read(rgnData^,RgnSize);
Region := ExtCreateRegion(nil,RgnSize,RgnData^);
SetWindowRgn(Form1.handle,Region,true);
//实现不规则窗体
bmp.Free;
MaskFile.Free;
If i = 15 then i := 0;
end;
 
用GDI做,一定程度的闪烁是难以避免的
要获得较好的效果,可以用DirectX的重叠表面,
DirectX SDK上有例子
如需要,我可以mail给你
 
<<像Office助手那样的
用MSAgent不就得了
 
xWolf:
用MSAgent控件应当怎样做呢??
 
我做过. 用SetWindowRgn就能做到. 几乎没什么闪烁, 其实我认为office的
小助手也是通过SetWindowRgn达到不规则动画窗口的(偶然之中发觉的,
如果你和我一样, 用win2000+28M内存+较慢的CPU, 你也会发觉它的小助手
在动画之间外型变化上不那么流畅, 很容易发觉上一画面的外框与当前画面
相交的现象)
你要做的只是保存图象各个连续画面的region而不是mask, 然后在动画播放
中用SetWindowRgn改变窗口的外型再bitblt将当前画面画上去就成了(不必
考虑transparent)
不过需要注意的是, 如果您的动画需要重复播放, SetWindowRgn时不能将
外型region直接作为参数传递, 而要复制一个region, 将复制品传递给SetWindowRgn
一旦一个region传递给SetWindowRgn之后您不能对这个region handle再进
行任何操作. 这个region handle已经由系统接管了, 你可以认为一个region传
递给SetWindowRgn只有等于已经释放了.
 
SetWindowRgn是可以,但若涉及Bitmap操作,则要好好考虑一下(现在我的机
没有装Delphi,找机会在把Demo贴上来。
 
他闪烁的原因是用了Image, 如果直接在form.canvas上画就不会闪了(再截取
掉form的WM_ERASEBKGND效果更佳)
 
终于进入论坛了,太难访问了.
我真是笨,用form.canvas直接写屏的方法也忘了,多谢Another_eYes提点,闪烁这下明显没有了.我截取掉了form的WM_ERASEBKGND,不知是不是这样:
procedure TForm1.WMEraseBkgnd (var Msg : TWMEraseBkgnd );
begin
Msg.Result := 0;
end;
但是这样做后,每次SetWindowRgn后都会调用WMEraseBkgnd,然后才调用我定义的图形,快速拖动窗体时,图形应为更新不及时,窗体上会看到用WMEraseBkgnd截取的背景图.如:
我把窗体快速从白色的区域拖到黑色区域,会明显看到窗体上的白色部分.
 
应该为 Msg.Result := 1;

=0表示你的程序未处理WM_ERASEBKGND, 系统将调用DefaultWndProc
的WM_ERASEBKGND处理过程(也就是全部清成白色).
 
to xFairy: 这可不是直接写屏。
 
我是说快速拖动窗体时,窗体因为更新不及时,会把部分背景也带走.
Msg.Result := 1时也是这样.
把窗体快速从黑色的区域拖到白色区域,会明显看到窗体上的黑色部分.
 
接受答案了.
 

Similar threads

后退
顶部