第九篇,看来世界上十全十美的事还真是很少。所以,从今天开始,回归基础,继续加油。工欲善其事,必先利其器。不抛弃,不放弃,加油,fighting,go on!

   COM组件,一个很有意思的东西,原来没有接触过,但是很感兴趣。精益求精,所以为了优化任务,就又用COM组件把项目从新修改了一遍,再次谢谢老师,感谢老师不厌其烦的指教,谢谢谢谢,很感谢。

   首先我们看一下什么是COM,网上资料很多,很详细。列举如下。

Question

什么是COM组件?

Answer:

COM组件是以WIN32动态链接库(DLL)或可执行文件(EXE)形式发布的可执行代码组成。

COM组件是遵循COM规范编写的

COM组件是一些小的二进制可执行文件

COM组件可以给应用程序、操作系统以及其他组件提供服务

自定义的COM组件可以在运行时刻同其他组件连接起来构成某个应用程序

COM组件可以动态的插入或卸出应用

COM组件必须是动态链接的

COM组件必须隐藏(封装)其内部实现细节

COM组件必须将其实现的语言隐藏

COM组件必须以二进制的形式发布

COM组件必须可以在不妨碍已有用户的情况下被升级

COM组件可以透明的在网络上被重新分配位置

COM组件按照一种标准的方式来宣布它们的存在

Question

  组件不是……?

Answer:

COM组件不是一种计算机语言

COM组件不是DLL,只是利用DLL来给组件提供动态链接的能力

COM组件不是一个API函数集。

COM组件不是类

怎么样,COM很神奇吧。但是不用怕,其实COM用起来,就像是我们平常经常用的库函数,我们不必关心它是怎么实现的,只要按照使用说明去用就行了,当然要是想研究COM,设计COM,那就要好好思考了,COM这种优秀的编程思想。小弟才疏学浅,就不卖弄了。我只能先站在使用者的角度,讲讲COM怎么用。

   起先由于没有接触过COM,用起来很不顺手,总是跟COM较劲儿:这个解码信息在哪?位图呢?它怎么没有。。。?它怎么不是。。。?它怎么不用。。。?等等等等,心里老是想按照自己的想法去做,但是COM就是COM它不会因你而改变。你只能按照它的套路出牌。

   记得老师总是说让我看文档,看文档,其实我看了,但是总是按照自己的想法去解读COM,结果总是出错。下面我们看看IImage组件是怎么实现GIF循环播放的吧

第一步:创建文件流,注册COM组件

 1  
 2 IStream*  stream = CreateStreamByFileName(fileName);
 3 
 4   if (!stream)                         
 5   {
 6    return false;
 7   }
 8 
 9 
10   hr = factory->CreateImageDecoder(stream, DecoderInitFlagBuiltIn1st, &decoder);
11   if (FAILED(hr))
12 
13  
14 
15 
16   {
17    return false;
18   }

第二步:取得图片信息

 

 1 hr = decoder->TerminateDecoder();//初始化decoder
 2   LARGE_INTEGER dlibMove = { 00 };
 3   hr = stream->Seek( dlibMove, STREAM_SEEK_SET, NULL );
 4   hr = decoder->InitDecoder(stream, DecoderInitFlagBuiltIn1st);
 5 
 6   decoder->GetPropertyItemSize(PropertyTagFrameDelay, &size);//取得GIF中的延时间
 7   decoder->GetPropertyItem(PropertyTagFrameDelay, size, &pi);
 8   
 9   hr = decoder->GetImageInfo(&ii);//取得帧数信息
10   decoder->GetFrameDimensionsCount(&count1);
11   decoder->GetFrameDimensionsList(&guid, count1);
12   decoder->GetFrameCount(&guid, &count);

第三步:循环播放(Draw相应的位图)

 

 1 hr = decoder->SelectActiveFrame(&guid, i);
 2      if (FAILED(hr))
 3      {
 4       return false;
 5      }
 6 
 7      hr = factory->CreateNewBitmap(ii.Width, ii.Height, PixelFormatDontCare, &bmpimg);
 8      if (FAILED(hr))
 9      {
10       return false;
11      }
12      bmpimg->QueryInterface(IID_IImageSink, (void**)&sink);
13 
14      hr = decoder->BeginDecode(sink, NULL);
15      if (FAILED(hr))
16      {
17       return false;
18      }
19 
20      hr = decoder->Decode();
21      if (FAILED(hr))
22      {
23       return false;
24      }
25      bmpimg->QueryInterface(IID_IImage, (void**)&image);
26 
27      ::BitBlt(tempDC, 00, ii.Width, ii.Height, gif->GetBkDC(), 00, SRCCOPY);
28 
29      image->Draw(tempDC, &rect, NULL);
30      ::BitBlt(hdc, 00, ii.Width, ii.Height, tempDC, 00, SRCCOPY);
31 
32      decoder->EndDecode(hr);
33      //设置延时 
34      Sleep(( (long*)pi.value )[i]*10);
35      image->Release();
36      sink->Release();
37      bmpimg->Release();
38      image = NULL;
39      sink = NULL;
40      bmpimg = NULL;

第四步:释放资源(位图、内存、组件)

OK大功告成,利用组件很简单吧,只要按照说明,一步步地把各个职位(COM接口)安排好,这个COM公司就会帮我们运做,生产出我们想要的产品。

COM会用了。但是学无止境,老师说我直接开线程的方式写GIF播放还是很幼稚,老师让我好好思考一下Windows编程。

windows编程其核心就是消息机制。进而我们可以用消息来控制线程的运行。这样的话。。。。

还有windows中窗口的刷新都涉位图的绘制,所以在窗口刷新前,要将各种材料(需要显示的位图)准备好,然后再在指定的区域重绘。

这样windows开发在头脑中又清晰了许多。keep running.....bless everyone 

posted on 2009-03-14 22:59  Ruby_Wang  阅读(1146)  评论(2)    收藏  举报