第九篇,看来世界上十全十美的事还真是很少。所以,从今天开始,回归基础,继续加油。工欲善其事,必先利其器。不抛弃,不放弃,加油,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组件
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 }
第二步:取得图片信息
2 LARGE_INTEGER dlibMove = { 0 , 0 };
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相应的位图)
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, 0 , 0 , ii.Width, ii.Height, gif -> GetBkDC(), 0 , 0 , SRCCOPY);
28
29 image -> Draw(tempDC, & rect, NULL);
30 ::BitBlt(hdc, 0 , 0 , ii.Width, ii.Height, tempDC, 0 , 0 , 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