如何直接将图象写入显存?(200分)

amo:
我想将一副位图在窗体上快速的移动,怎样能消除才闪烁??
 
消除闪烁? 太简单了.
procedure form1.fastmove(bmp: TBitmap; beginX, BeginX: Integer;
Stepx, Stepy: Integer; interval: Integer);
var
dc: HDC;
formRct: TRect;
rg: HRGN;
rctnew, rctold: Integer;
mask: TBitmap;
begin
mask := tbitmap.create;
mask.assign(bmp);
mask.mask(bmp.transparentcolor); // mask.mask(bmp.canvas.pixel[0, bmp.height-1])
dc := createdc('DISPLAY', nil, nil);
formrct.TopLeft := ClientToScreen(pointer(0, 0));
formrct.right := formrct.left+width;
formrct.bottom := formrct.top + height;
rg := createRectRgnIndirect(formrct);
selectcliprgn(dc, rg);
rctnew.topleft := clienttoscreen(point(beginx, beginy));
rctnew.right := rctnew.left+bmp.width;
rctnew.bottom := rctnew.top + bmp.height;
rctold := rctnew;
for i := 0 to 1000 do
begin
redrawwindow(getdesktopwindow, @rctold, 0, RDW_ERASE or
RDW_ERASENOW or
RDW_ALLCHILDREN); // 恢复底色
transparentstretchblt(dc, rctnew.left, rctnew.top, bmp.width, bmp.height,
bmp.canvas.handle, 0, 0, bmp.width, bmp.height,
mask.canvas.handle, 0, 0); // 画图
sleep(interval);
rctold := rctnew;
offsetrect(rctnew, stepx, stepy);
end;
selectcliprgn(dc, 0);
deleteobject(rg);
deletedc(dc);
mask.free;
end;
 
Another_eYes:
大虾!还是不行啊!
是不是要截获WM_Paint消息,屏蔽之?
 
impossible.
是不是你form上放了很复杂的背景?
 
Another_eYes:
不是啊!
我就把你给我的代码贴在一个空窗体上,加了个按钮:
procedure TForm1.Button1Click(Sender: TObject);
var
bmp:Tbitmap;
begin
bmp:=Tbitmap.Create;
bmp.LoadFromFile('c:/1.bmp');
fastMove(bmp,0,0,1,1,10);
end;

如此而已,位图大小100*100左右。

另,图象移动后,留下的轨迹,背景没有被重画。
 

Eyes的代码应该与下面的代码功能差不多:

b:=tbitmap.Create;
b.LoadFromFile('h.bmp');

b.Transparent:=true;
b.TransparentMode:=tmauto;//tmfixed;

for i:=0 to 200 do
begin
Canvas.Draw(i, i, b);
sleep(20);
end;
b.free;

这样的缺点就是b会自动用b的左上角的颜色作为透明色,
这样就会留尾巴,
于是我就改了改,
试试这样:
var
b,c,d:tbitmap;
i,j:integer;

PaintDC: HDC;
MaskRect: TRect;
SavedRgn: HRgn;
SavedBox: TRect;
begin
b:=tbitmap.Create;
b.LoadFromFile('h.bmp');

c:=tbitmap.Create;
c.Width:=2;
c.Height:=b.Height;

d:=tbitmap.create;
d.width:=b.width;
d.height:=2;


b.Transparent:=true;

b.TransparentMode:=tmauto;//tmfixed;

for i:=0 to 200 do
begin
c.Canvas.CopyRect(rect(i,i,2,b.height),form1.canvas,rect(i,i,i+2,i+b.height));
d.Canvas.copyrect(rect(i,i,b.width,1),form1.canvas,rect(i,i,i+b.width,i+2));

Canvas.Draw(i, i, b);
sleep(20);

form1.Canvas.CopyRect(rect(i,i,i+c.width,i+c.height),c.canvas,rect(0,0,c.width,c.height));
form1.Canvas.CopyRect(rect(i,i,i+d.width,i+d.height),d.canvas,rect(0,0,d.width,d.height));
end;
b.free;
c.free;
d.free;
end;

不知Eyes还有什么好办法。
 
闪烁是因为form老是接受到invalidaterect(windows会自动将该区域清成白
色), WM_ERASEBKGND造成的.
所以应该避免触发form的invalidaterect与WM_ERASEBKGND.
所以我用createdc直接忘screen上画.出现轨迹是redrawwindow参数不对头,
试试redrawwindow(getdesktopwindow, nil, 0, RDW_ERASE or RDW_INTERNALPAINT or RDW_ERASENOW or RDW_ALLCHILDREN);
这其实是个偷懒的办法, 好点的办法是另开一个bitmap专门保存背景, 恢复
背景时也用bitblt直接画在screen上(我做过一个在屏幕上移动的动画控件,
就是先保存背景然后再画的, 没有闪烁问题).
 
Another_eYes:
<我做过一个在屏幕上移动的动画控件,
<就是先保存背景然后再画的, 没有闪烁问题).

能不能把源代码给我瞧瞧?如果方便的话。
superwgr@netease.com
 
大虾们:
有没有关于“双缓存”的例子,发一个给我。
 
Another_eYes:
大虾,给我也发个例子吧!
beetjf@yahoo.com
 
大家再来看看吧!
 
双缓存的例子我到是有一个,不过我在学校教育网上网,没带那本书,本人也是刚学到那一节,不过他需要directx控件支持5。0版本的。如你有控件,我可在以后用邮件发给你,或你去买那本书也可以,delphi4。0深入编程内幕,要110元呢
 
我的email meng_1226@freemail.online.tj.cn
 
利用图形的异或操作你有没有试过呢?在copy图形的时候,用异或可以的啊。具体么,你去自己实现,做个实验么。
 
各位有没有用过DIBUltra呢?它采用ASM和Delphi混合编程,速度极快,
功能强大。需要的话请通知我。
(有完整源代码和例子!可惜源代码中的大量注解是--法语!)
 
ZRY大虾
DIBUltra我也想看看,方便的话来一个吧!

E-mail:
c9651127@turing.wuhee.edu.cn
 
To SnowWolf:
  已经发过去了,请查收。
 
DIBUltra不错, 但功能不算强. 要说功能, 我觉得fastlib最好. 常用图象算法
都有了.
 
多人接受答案了。
 

Similar threads

回复
0
查看
710
不得闲
回复
0
查看
662
不得闲
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
顶部