第十一章C++ Builder 的多媒體世界

Download Report

Transcript 第十一章C++ Builder 的多媒體世界

基础综合 C++ Builder 的多媒体世界
在这个新的世代,图片、动画充斥在我们的身边,BCB
当然也不能在多媒体这块区域缺席。在第9章我们将介
绍各种多媒体组件的使用,也讨论有关绘图部分的设计,
更深入探讨影像绘图处理上的速度,由于完整的组件支
持,对于花俏功能的多媒体程序开发,对读者们来说已
经不再是高深的程序。
大纲
•
•
•
•
•
•
9-1 Image组件的建立
9-2 ImageList组件的建立
9-3 Animate动画组件
9-4 MediaPlayer组件
9-5 绘图功能
本章习题
9-1 Image组件的建立
• 图形档案的表现是本章所要介绍最基本的功能,BCB提供图形
加载的组件,可以方便的让我们操作图形显示和处理的动作,
也就是本节所要介绍的Image组件。
• Image组件不但可以让我们把图文件的内容显示在Image组件
的显示范围之内,我们也可以针对开启的图文件存在组件属
性里的数据作处理,也就是利用Image组件作为接口,让我们
来编辑图形档案的内容。
Image图形组件的主要属性
属性(Properties)
型态原型
说明
AutoSize
bool
是否让图形显示自动调整
Canvas
TCanvas
描绘图像
Center
bool
调整图像在显示范围的中间
Picture
TPicture
加载图像
Height
int
显示方块的长度
Width
int
显示方块的宽度
Transparent
bool
背景是否透明
Strecth
bool
是否缩放图像
图档的加载方式
• 我们可以用两种方法加载档案:
– 第一种最简单的就是用对象编辑器(Object Inspector)来手动放入档
案:
• 我们在程序开发模式下在我们所建立的Image组件上面按两下鼠标
左键,这时就会出现加载图文件的对话窗口,这时我们按下Load
键就可以开启档案浏览的对话盒来指定要加载的档案。目前支持
的图档格式有jpg,bmp,ico,emt,wmf等一般常见的档案格式。
– 另一种方式我们可以利用Picture属性里的LoadFromFile的函式
• 在程序执行时把图文件信息喂进去,除了在程序里面把档案的路
径和名称写死,这样子在编译时期就决定了要载入的档案;我们
还可以动态的指定档案,譬如说让使用者输入,或是可以藉由
OpenDialog组件或是OpenPictureDialog组件让我们随意的开启所
需要显示的图文件。
9-2 ImageList组件的建立
• 如果我们要设计的应用程序需要使用很多的图档,或是要大
量的作图档的存取动作,将每个Image组件的加载动作都做设
定是一件很费力的事情。这个时候我们也许会需要一个可以
管理这些图形的方法。而TImageList组件顾名思义就是集中
各个Image图像成为一个图像的列表,用意在可以让我们便于
管理图像的存取,但是有一个非常重要的限制,就是列表中
的图像大小要完全一样。
ImageList组件的重要属性
属性(Properties)
型态原型
说明
AllocBy
Int
预设的List空间
BkColor
TColor
影像绘出时的背景颜色
BlendColor
TColor
影像绘出时的前景混合色
Count
Int
目前所存入List的图像数目
Height
Int
指定List里每个影像的高度
Width
Int
指定List里每个影像的宽度
ImageType
TimageType
影像绘出时是否加入mask影像
Masked
Bool
指定影像绘出时是否可以加入
mask
使用开发工具编辑ImageList
• 我们从右图里可以看到几个主要
的部分,下面的Images里所显示
的是目前List里所有的Image,当
点选了之后可以在Selected
Image格里看到预览画面,而每个
图像的下面所显示的数字就是该
图像在这个List里面的Index编号,
这是很重要的信息,我们在存取
时所要指定图像就得要知道该图
像在列表里的编号。
使用程序代码编辑ImageList
• 除了用编辑画面加入图像,我们也可以在程序代码里利用内建的函式将图
像加入列表里,如Add(),AddImage()等等。使用方式如:
– Add( Graphics::TBitmap* Image , Graphics::TBitmap * mask);
– 就是指定Bitmap格式的图像加入List里。另外显示图像的方式我们可以利用
Draw()函式,方法如下:
• Draw(Graphics::TCanvas *, int x,int y,int Index);
• 就是给予绘图的组件,绘图的起始坐标x和y,以及要绘出图像在
ImageList里的Index编号。
• 另外我们也可以利用Delete()和Clear()两个函式把ImageList既有的图像
删除,Delete函式是指定单一图像一一删除,所以我们必须在使用
Delete( )时要指定所要删除图像的Index编号,而Clear()函式则是将所
有在列表里的图像全部删除,用法如下:
– Delete(int Index);
– Clear( );
9-3 Animate动画组件
• 使用Animate动画组件可将动画控制功能加到Form里,动画组
件是一种可以显示影音动画AVI档案。AVI档案是一系列连续
的Bitmap图形所结合排列成的大量影像,连续拨放就像动画
一样,而每一个显示画面的单位一般都称为frame。BCB所提
供的这个动画表现的组件功能并不太完整,并不能拨放压缩
过的AVI档案,只能拨放标准的AVI格式的档案,而这样的格
式已经慢慢的被淘汰了。我们来介绍这个组件的运作方式,
其实Animate动画组件的使用方式和下一节所要介绍的
MediaPlayer的方式差不多,不过功能稍嫌阳春了些??耈
Animate动画组件的应用 I
• 首先在开启AVI档案方面,组件的FileName属性可以让我们设
定成所要开启的档案,所以我们可以利用这个属性作接口,
把档案指定给Animate组件,当我们开启了档案之后就可以有
以下的处理动作:Play,Seek,Reset,和Stop等等,这些动
作都已经写成函式了。
Animate动画组件的应用 II
• 当我们把Animate组件加入Form时,所设定的组件大小就会是AVI格式拨放
显示的大小。首先当使用者开启档案后,如要拨放则如下:
– Animate1->Play(0,Animate1->FrameCount,1);
• Play函式要求三个参数,分别为拨放的起始Frame,拨放的结尾Frame,以
及拨放的次数,所以本例里是从0开始拨放,拨放完整个AVI来源,而拨放
次数是1次。而我们按下停止功能键要求拨放停止时,程序就执行:
– Animate1->Stop();
• 最后我们要求程序在拨放结束时能够回到拨放前的起始Frame,所以在
Animate组件在Stop事件发生时给予Reset的动作:
– Animate1->Reset();
9-4 MediaPlayer组件
• Windows操作系统的一大魅力,就是在多媒体的表现上面一直有很突出
的效果。现在我们在Windows环境下,只要有操作系统内建的
MediaPlayer软件,几乎就可以拨放所有的多媒体档案。在窗口环境下
拨放软件透过MCI(Media Control Interface)函式接口与多媒体设备
沟通,所谓的MCI就是一种介于拨放接口和媒体资源的接口,对于拨放
多媒体数据,已经有MCI完成一些处理动作,让程序设计师可以利用这
个接口轻易的作多媒体数据的处理。在BCB的环境下我们可以利用
MediaPlayer组件来达到拨放???
MediaPlayer按键和功能说明
图示
按钮名称
设定值
说明
Play
btPlay
开始执行拨放动作
Pause
btPause
暂时停止拨放的动作
Stop
btStop
停止目前拨放的动作
Next
btNext
跳到下一个Track
Prev
btPrev
条回上一个Track
Step
btStep
跳到下一个Frame
Back
btBack
跳回上一个Frame
StartRecord btStartRecord
开始执行录音动作
Eject
弹出光驱
btEject
MediaPlayer重要属性说明 I
• 1.FileName属性:
– FileName的型态为一Ansi字符串,内容为目前组件正在拨放的档案路
径以及名称。透过FileName属性我们可以利用OpenDialog组件来处理
开启档案的接口,如:
• MediaPlayer1->FileName = OpenDialog1->FileName;
• 2.Mode属性:
– Mode属性为纪录目前所开启媒体设备的模式,其模式共有7种,分别
为:Not Ready , Stopped , Playing , Recording , Seeking ,
Paused , Open。当我们制作拨放程序接口时可以将Mode显示在窗口某
个地方,让使用者知道目前程序所执行的动作为何。
MediaPlayer重要属性说明 II
• 3.Notify属性:
– Notify属性为控制OnNotify事件是否发生,型态为Bool。如值为true则在目
前MCI命令完成时将会启动OnNotify事件,若为False则否。举例来说,如果
我们希望拨放媒体完成时可以产生一个讯息告知我们档案已经拨放完毕,那
我们就可以在Notify属性里设定成true,并在OnNotify事件里加进显示讯息
的程序代码,Notify更改如:
• MediaPlayer1->Notify = true;MediaPlayer1->Play();
– OnNotify事件程序代码加入如下:
• application -> MessageBox(‘档案拨放完毕!’,NULL,MB_OK);end;
• 4.Position属性,StartPos属性,EndPos属性;
– 纪录档案拨放的位置是控制档案拨放的方式,StartPos属性可以让我们设定
拨放档案的时候要从哪个位置开始拨放,EndPos属性则是让我们设定要拨放
到哪个位置,Position属性则是纪录目前拨放的位置。预设的StartPos和
EndPos分别为档案开始和结尾的地方,如果我们希望在拨放接口里加入
ScrollBar那我们就可以利用ScrollBar里的Position属性和MediaPlayer的
Position去做对应。
MediaPlayer范例说明 I
• 拨放界面如右图
• 范例我们可以看到的组件有
MediaPlayer组件,Panel组件,
MainMenu组件,ScrollBar组件以
及三个Label组件。另外为了功能
而加的有OpenDialog组件和Timer
组件。
MediaPlayer范例说明 II
• 首先我们先在新的项目里建立以
下对象:OpenDialog1,Panel1,
MediaPlayer1,ScrollBar1,
Label1,Label2,Label3,
Timer1,以及MainManu1等组件。
在MainMenu1里我们加入两个选
项;Open和Exit,并且MainMenu1
的Caption更改成File
MediaPlayer范例说明 III
• 我们设计按下File的Open时,就会开启档案开启对话框,让我们选择
要拨放的档案,而按下Exit时就关闭窗口。 所以要加入以下程序代
码
void __fastcall TForm1::Open1Click(TObject *Sender)
{
if(OpenDialog1->Execute())
{
MediaPlayer1->FileName = OpenDialog1->FileName;
MediaPlayer1->Open();
Label3->Caption = MediaPlayer1->TrackLength[1];
ScrollBar1-> Max = MediaPlayer1->TrackLength[1];
}
}
MediaPlayer范例说明 IV
• 首先我们希望开启的档案由MedaiPlayer1来拨放;
– MediaPlayer1->FileName = OpenDialog1->FileName;
• 接着我们开始开启MediaPlayer
– MediaPlayer1->Open();
• 关于ScrollBar的总长度我们希望和档案大小相关,所以我们以下设
定:
– ScrollBar1-> Max = MediaPlayer1->TrackLength[1];
• 然后我们设定按下Exit时的动作,在Exit1被Click的事件如下:
void __fastcall TForm1::Exit1Click(TObject *Sender)
{
Form1->Close();
}
MediaPlayer范例说明 V
• 以上的动作就把开启档案和关闭窗口的动作完成了,现在我们来注
意MediaPlayer1该作的动作,以下为程序代码:
void __fastcall TForm1::MediaPlayer1Click(TObject *Sender,
TMPBtnType Button, bool &DoDefault)
{
MediaPlayer1->Display = Panel1;
}
MediaPlayer范例说明 VI
•
完成了以上的动作基本上媒体拨放的功能就已经齐全了,不过我们还希望能够
有ScrollBar来显示拨放进度,以及我们可以利用ScrollBar来调整拨放的内容。
– 要考虑ScrollBar的动作有两个地方,第一就是ScrollBar要随着档案拨放自己跑动,
第二就是当我们拉动ScrollBar时,档案拨放的位置也要跟着我们ScrollBar拉的位
置去改变目前拨放的位置。要完成第一个动作我们需要用Timer来协助我们产生变动
的事件:
void __fastcall TForm1::ScrollBar1Scroll(TObject *Sender,
TScrollCode ScrollCode, int &ScrollPos){
MediaPlayer1->Position = ScrollBar1->Position;
MediaPlayer1-> Play();
}
void __fastcall TForm1::Timer1Timer(TObject *Sender){
if(MediaPlayer1->FileName!="") {
Label1->Caption = MediaPlayer1->Position;
ScrollBar1->Position = MediaPlayer1->Position;
}
}
9-5 绘图功能
• 我们可以重很多有关图形的组件里看到他们同样拥有的类别
Canvas,这类的组件有TForm,TImage,TbitButton….等等。
而Canvas类别就是处理Windows绘图的接口,这个类别将会跟
Windows的装置驱动程序作沟通,Windows会透过装置驱动程
序把做好转换的数据结构显示在装置显示器上面。也就是说
Canvas类别我们可以看成是一套帮我们管理Windows内的绘图
动作的API的类别。因此有了Canvas后,我们在开发绘图程序
时就会十分便利,只需要知道如何利用Canvas就可以将我们
要的绘图???
9-5 绘图功能
• 我们可以利用两种Canvas下的类别,Pen(画笔)和Brush(画
刷)。首先我们先看画笔的属性,我们可以设定画笔的三个重
要属性,分别为画笔的宽度,画笔画出来的颜色,以及画笔
本身的形式,如实线虚线等等。在颜色方面我们可以设定成
VCL所提供的颜色类别。写法如下:
– Tcolor DrawColor = Tcolor(RGB(100,100,100));
– 其中RGB(x,y,z)里面的x代表的是红色的比重,y代表的是绿色的比重,
z代表的是蓝色的比重。每个颜色的比重值可以是0到255,所以我们可
以自行调配出255*255*255种颜色出来。
Canvas所提供的重要属性和函式 I
• Pixels:
– 我们可以把任何的图像当看作是大量的像素所组成的,当然我们也可以直接
对于像素作处理,每个pixel所在图像的位置就好像是坐标一样,只要指定好
要对那个坐标的像素处理即可,简例如下:
• Image1->Pixels[10][20] = clBlack;
• PenPos:
– 即Pen Position的意思,原型为TPoint,纪录目前画笔在图像上的坐标位置。
• MoveTo(int X,int Y);
– 这是指定画笔到某个坐标的函式,我们可以利用此函式指定画笔到图像上某
个位置,就技术方面来看我们也可以直接指定PenPos到指定的位置,其作用
是一样的。
• LineTo(int X,int Y);
– 除了把目前画笔的位置移到指定的坐标以外,移动的最短线将会由画笔划下
直线,也就是说从画笔目前位置到坐标(X,Y)位置画下一条直线。
Canvas所提供的重要属性和函式 II
• Draw(int X,int Y,TGraphic* Graphic);
– 把一型态为Graphic的图像画到Canvas上面的(X,Y)坐标位置上面。
• Ellipse(int X1,int Y1,int X2,int Y2);
– 给予椭圆形的两个坐标,(X1,Y1)为左上角的坐标,(X2,Y2)为右下角
的坐标,绘出一椭圆形。
• FillRect(TRect &Rect);
– 指定一矩形区域,将该区域套用Brush的属性把其颜色图满。
• FloodFill(int X,int Y,TColor Color,TFillStyle
FillStyle);
– 由坐标(X,Y)作为起始坐标,把一封闭区域图满颜色,图满的方式有两
种,其一为fsSurface:把封闭的区域图满,遇到其它颜色的图像才停
止。另一种为fsBorder:以设定值Color作为边界,而边界内的部份就
用Brush的设定值来图满区域。
Canvas所提供的重要属性和函式 III
• Polygon(const Point *points,const int Size);
– 把传入的所有点数组以直线连接起来,形成一个没有缺口的多边形,Size为
数组的大小。当多边形完成后内部将会被图满颜色,颜色的设定值是套用
Brush的设定值。
• Polyline(const Point *points,const int Size);
– 把传入的所有点数组以直线连接起来,形成一个没有缺口的多边形,Size为
数组的大小。但和Polygon不同的是Polyline不会把内部填满颜色。
• Rectangle(int X1,int Y1,int X2,int Y2);
– 画出一个矩形,矩形的左上角坐标为(X1,Y1),右下角坐标为(X2,Y2)。
• TextOut(int X,int Y,AnsiString Text);
– 将文字Text用绘图的方式显示在Canvas上,文字将套用Font属性的设定,起
始位置为坐标(X,Y)。
范例-涂鸦广告牌
• 这个范例所需要用到的组件,除了要显示涂鸦的一个Image组件外,
菜单上我们用了一个panel和5个SpeedButton,而画笔颜色的选择
笔者则是套用了一个ColorDialog组件,最后为了加入储存功能我
们还需要一个SavePictureDialog组件。
范例说明 I
• 在Unit1.h里我们加入了一些公用参数
– int mode;
– TColor DrawColor;
– bool
MDown;
– TPoint EraseP[4];
• mode表示目前的绘图模式,有画笔(0)和画刷(1)两种。DrawColor表示画
笔和画刷设定的颜色,MDown是表示鼠标是否有按下,最后EraseP[4]是一
个点的数组,我们会用来作清除时范围的设定。
• 首先在建立这个Form的时候,我们需要先设定一些初始值,包括鼠标目前
是否有被按下,目前画笔的颜色,以及预设的模式为画笔。
– Image1->Canvas->Pen->Color = clBlack;
– mode = 0;
– MDown = false;
范例说明 II
• 接着来看鼠标在Image1上面使用时的处理,对于绘图的动作主要可以分三
种事件来讨论:鼠标移动,鼠标左键按着,鼠标左键按下后放开。当鼠标
按下的时候,布尔变量MDown要被设定成true,并且画笔目前的坐标要马
上移到鼠标点下的地方。以上说明程序代码如下:
– MDown = true;
– Image1->Canvas->MoveTo(X,Y);
• 当鼠标按下后再放开,MDown就要被设成false。最后最重要的就是判断鼠
标移动时的状况,对于鼠标移动的事件,我们需要先作判断鼠标左键是否
是被按下的,如果是被按下的才需要作动作,如果不是就不予理会。接着
我们需要知道目前的使用状态是画笔还是画刷,画笔的话就利用LineTo函
式画在画面上,如果是画刷的话就建立一个矩形的移动方块,凡是被方块
经过的就被清成空白 。
范例说明 III
• 画刷的相关程序代码
if(MDown) {
if(mode == 0) {
Image1->Canvas->Pen->Color = DrawColor;
Image1->Canvas->Pen->Mode = pmCopy;
Image1->Canvas->LineTo(X,Y);
}
if(mode == 1){
EraseP[0] = Point(X,Y);
EraseP[1] = Point(X+10,Y);
EraseP[2] = Point(X+10,Y+10);
EraseP[3] = Point(X,Y+10);
Image1->Canvas->Pen->Color = clWhite;
Image1->Canvas->Polygon(EraseP,3);
}
}
范例说明 IV
• 绘图的部分大概就完成了,接着来看看功能键的部分,功能
键有五个分别是画笔,画刷,选择颜色,清除画面,以及存
档。
• 画笔
– 当选择画笔时,状态mode要设定成0成为画笔模式。
• 画刷
– 当选择画刷时,状态mode要设定成1成为画刷模式。
• 选择颜色
– 点选此键,会呼叫ColorDialog组件,并且把画笔的Color属性设定成
为被选定的颜色。
范例说明 V
•
清除画面
– 做法类似清洁画刷,做法是开启一个涵盖全Image组件画面的矩形,把矩形内部和边
框都清空。程序代码如下:
EraseP[0] = Point(0,0);
EraseP[1] = Point(856,0);
EraseP[2] = Point(856,513);
EraseP[3] = Point(0,513);
Image1->Canvas->Pen->Color = clWhite;
Image1->Canvas->Polygon(EraseP,3);
Image1->Canvas->Pen->Color = DrawColor;
– 笔者在范例里所开启的Image大小为856*513
•
存档
– 开启SavePictureDialog组件,利用Picture属性作接口,将Image的内容存成档案。
本章习题
•
•
利用MediaPlayer组件,自形设计一个CD拨放程序。
将本章的范例涂鸦画板加入文字编辑插入的功能。