我的手机开发(八)——GIF动画播放

      在windows中DC就是相当于画布,当我们利用CreateCompatibleDC时,就创建了一块画布,在这块画布上,有一套缺省的工具(画笔,画刷,字体,位图等,每一个画布都得到框架的这一待遇),
如果不喜欢,你可以造了一个新的画笔,再入选这套工具集,并把原来的画笔给代替掉了,画完图后你觉得不安,想还原一下,于是就把oldPen再select进去.
      我们常用的DC包括设备DC和内存DC,内存DC,是一个虚拟的内存设备上下文,我们对它进行绘图等操作,不会显示在屏幕或打印机上,而我们可以在它完成之后,拷贝到屏幕上或打印机上来输出,这样我们可以避免因为操作而给屏幕带来的闪烁,如果你有很多个内存DC,想把这些东西都显示出来,那你应该先把这多个内存DC的内容同时拷到另外一个内存DC上,再把这个内存DC的内容拷到屏幕DC上。这就好比我们在做拼图,最后的这一块内存DC起到了缓存的作用。
位图是按块存储的,所以所有的位图都是方方正正的,不可能出现不规则形状的位图。
画笔和画刷比较简单,这里有一个简单的例子,是改变画笔的

ContractedBlock.gif ExpandedBlockStart.gif Code
 1 LRESULT DoPaintMain (HWND hWnd, UINT wMsg, WPARAM wParam,
 2       LPARAM lParam) {
 3        /* DWORD dwColorTable[] = {0x00EA0000, 0x009F35FF, 
 4        0x00000079, 0x00006000};*/
 5     
 6             LOGPEN lp;
 7             HPEN hPen,hOldPen;
 8        HDC hdc;
 9       
10        hdc = GetDC(hWnd);
11 
12        lp.lopnStyle = PS_SOLID;//设置画笔样式(4个像素宽的红色实心画笔)
13        lp.lopnWidth.x = 4;
14        lp.lopnWidth.y = 4;
15        lp.lopnColor = RGB (0xff00);
16 
17        for(int i=0;i<50;i++){
18         hPen = CreatePenIndirect (&lp);//创建画笔
19         hOldPen = (HPEN)SelectObject(hdc,hPen);//将画笔选入设备环境
20         MoveToEx(hdc,6*i,10,NULL);
21         LineTo(hdc,6*i,20);
22         SelectObject(hdc,hOldPen);
23         DeleteObject(hPen);
24 

运行效果:

为了规范,我们可以先将画笔选入到内存DC中,在内存DC中绘制完成后,在拷贝到窗口DC中去,代码如下:

ContractedBlock.gif ExpandedBlockStart.gif Code
 1 LRESULT DoPaintMain (HWND hWnd, UINT wMsg, WPARAM wParam,
 2       LPARAM lParam) {
 3 
 4        HDC hDC,hPauseDC;
 5        HBITMAP hbitmap,hOldBitmap;
 6        int i;
 7        HPEN hpen,holdpen;
 8        PAINTSTRUCT ps;
 9        RECT rect;
10 
11        hDC = BeginPaint(hWnd,&ps);
12        GetClientRect(hWnd,&rect);
13        hPauseDC=CreateCompatibleDC(hDC);
14 
15        hbitmap = CreateCompatibleBitmap(hDC,100,100);
16        hOldBitmap = (HBITMAP)SelectObject(hPauseDC,hbitmap);//创建一张位图初始化内存DC
17       
18        for(i=0;i<100;i++){
19         hpen = CreatePen(PS_SOLID,1,RGB(0,0,i*2+55));
20         holdpen = (HPEN)SelectObject(hPauseDC,hpen);
21         MoveToEx(hPauseDC,0,i,NULL);
22         LineTo(hPauseDC,100,i);
23         SelectObject(hPauseDC,holdpen);
24         DeleteObject(hpen);
25        }
26        BitBlt(hDC,0,0,100,100,hPauseDC,0,0,SRCAND); 
27        SelectObject(hPauseDC,hOldBitmap);//释放资源
28 
29        DeleteObject(hbitmap);
30        DeleteDC(hPauseDC);
31 
32 

效果图:

这里好的编程习惯是一块DC对应一张位图,然后将处理好的各块DC,拼接好放入到一个主的内存DC中,最后在BitBlt到窗口DC中。

 

    绘图最重要的就是DC的处理。之前在学习的时候,很不理解什么是DC。后来老师跟我说DC就是画布,要想在窗口上画画,就要先创建一个DC。好,明白了,作画前,就先创建DC。按照这种想法,我参照网上的代码完成了去除图像背景的编程。
    这儿阵子,我又把我之前做的GIF文件播放整理了一下,将解码,和图片显示分离开来,并且在指定区域显示指定大小的图片的功能。类都已经封装好了,本来以为改起来会很方便,没想到这一改,又花了我将近一个星期的时间。这次修改发现自己还有很多模糊的地方。

首先我们看下DC三部曲:
1、创建内存DC和相应的位图
hPauseDC = CreateCompatibleDC(hDC);
hbitmap = CreateCompatibleBitmap(hDC,100,100);
OldBitmap = (HBITMAP)SelectObject(hPauseDC,hbitmap);

2、将内存DC中的内容显示到窗口DC中
BitBlt(hDC,0,0,100,100,hPauseDC,0,0);
3、清理内存

SelectObject(hPauseDC,OldBitmap);//清理前先要将DC复原,即将初始状态再次选入
DeleteObject(hb
itmap);//一定要先释放位图,在释放DC
DeleteDC(hPauseDC);

创建一块兼容DC和一张设备兼容位图,这个就不多说了。
     看一下什么是将位图选入DC?将位图选入DC其实就是规定了DC的大小,相当给DC赋值初值(此时DC的大小就是位图的大小、颜色全黑)。
再看一个十分重要的函数:::BitBlt(hDC,x,y,width,height,hPauseDC,x1,y1,SRCCOPY);
     这个函数是进行DC间的拷贝,此时若hDC是窗口DC,则此句表示将hPauseDC中的从x1,y1开始的区域会显示到窗口从x,y开始的区域。若两块都是内存DC,则实现的是DC间的拷贝,相当于赋值函数,即将hPauseDC中的内容赋值给hDC。
在这里有一个很重要的概念,窗口DC内存DC
     所谓的窗口DC就是我们的主DC,将内存DC中的内容BitBlt到窗口DC中,就完成了图像的显示。
     而内存DC呢,就是通过CreateCompatibleDC创建的DC,这个DC是个临时DC
     临时DC这个也很重要,相当于我们的临时变量。
     这里有个问题困扰了我很久,当时就是太执著于窗口DC和临时DC了。搞得自己晕头转向。
其实在图像显示的最好做法是,先预留一个内存DC,然后将其他处理好的内存DC中的内容统一拷贝到这个内存DC中,形成一个完整的图像。然后在将这个主内存DC中的内容拷贝到窗口DC中显示图像,这样可以防止图像来回叠加造成的混淆
      这种办法,在处理图像缩放上很管用,当我们把hDC中的图像StrecthBitBlt到窗口DC中时,这时若在从窗口DC中取位图,就是已经放缩了的位图了。而内存DC中还是原大小的位图。这样,只要我们操作内存DC就可以很灵活的处理好图像,然后,在放缩到窗口上。
     还有就是DC和位图一定 要注意

清楚了这些在看GIF的源码,自然就一目了然了。

转载于:https://www.cnblogs.com/rubywang/archive/2009/02/12/1388796.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值