摄像头编程
ACDCounts属性(音频捕捉设备的数量) ACompCounts属性(音频压缩引擎的数量) AddToRot属性(是否加入到系统运行对象表) ARDCounts属性(音频发布设备的数量) CaptureAudio属性(是否捕捉音频)
CaptureFile属性(捕捉文件名)
CaptureVideo属性(是否捕捉视频)
CurACD属性(当前的音频捕捉设备)
CurAComp属性(当前的音频压缩引擎) CurARD属性(当前的音频发布设备)
CurVCD属性(当前的视频捕捉设备)
CurVCDInput属性(当前视频输入通道) CurVComp属性(当前的视频压缩引擎) DefaultMenuItems属性(缺省菜单项) EnableDefaultMenu属性(是否使用缺省菜单) Picture属性(背景图片)
PlayState属性(控件运行状态)
PreviewAudio属性(控件运行时是否预览音频) PreviewVideo属性(控件运行时是否预览视频) TitleGenerator属性(视频字幕)
VCDCounts属性(视频捕捉设备的数量) VCDInputCounts属性(视频捕捉设备输入通道的数量) VCompCounts属性(视频压缩引擎的数量) VideoHeight属性(视频的高度)
VideoSampleMachining属性(视频样本处理器) VideoWidth属性(视频的宽度)
?返回目录
ACDCounts属性
当前系统中可供使用的音频捕捉设备的数量 读/写:只读
类型:long
VB语法:
[longVar] = Object.ACDCounts
VC语法:
[longVar] = Object.GetACDCounts();
参见:
CurACD属性、GetACDName方法
?返回目录
ACompCounts属性
当前系统中可供使用的音频压缩引擎的数量
读/写:只读
类型:long
VB语法:
longVar = Object.ACompCounts VC语法:
longVar = Object.GetACompCounts();
参见:
CurAComp属性、GetACompName方法
?返回目录
AddToRot属性
是否将当前过滤器图加入到系统运行对象表中
读/写:读写
类型:bool
VB语法:
Object.AddToRot = boolVar boolVar = Object.AddToRot VC语法:
Object.SetAddToRot(boolVar); boolVar = Object.GetAddToRot(); 说明:
如果将当前过滤器图加入到系统运行对象表中,就可以利用DX8SDK提供的工具程序
GraphEdit查看当前过滤器图结构,但只有在Win2k/WinXP该功能才被支持。
?返回目录
ARDCounts属性
当前系统中可供使用的音频发布(播放)设备的数量
读/写:只读
类型:long
VB语法:
longVar = Object.ARDCounts VC语法:
longVar = Object.GetARDCounts(); 参见:
CurARD属性、GetARDName方法
?返回目录
CaptureAudio属性
控件运行时是否捕捉音频流
读/写:读写
类型:bool
VB语法:
Object.CaptureAudio = boolVar boolVar = Object.CaptureAudio VC语法:
Object.SetCaptureAudio(boolVar); boolVar = Object.GetCaptureAudio(); ?返回目录
CaptureFile属性
保存音/视频流数据的捕捉文件的完整文件名
读/写:读写
类型:string
VB语法:
Object.CaptureFile = stringVar stringVar = Object.CaptureFile VC语法:
Object.SetCaptureFile(stringVar); stringVar = Object.GetCaptureFile(); ?返回目录
CaptureVideo属性
控件运行时是否捕捉视频流
读/写:读写
类型:bool
VB语法:
Object.CaptureVideo = boolVar boolVar = Object.CaptureVideo VC语法:
Object.SetCaptureVideo(boolVar); boolVar = Object.GetCaptureVideo(); ?返回目录
CurACD属性
当前的音频捕捉设备
读/写:读写
类型:long
VB语法:
Object.CurACD = longVar
longVar = Object.CurACD
VC语法:
Object.SetCurACD(longVar); longVar = Object.GetCurACD(); 说明:
该属性决定控件使用当前系统可用音频捕捉设备中的哪一个设备进行音频捕捉,缺省为?0′
即第一个音频捕捉设备。
参见:
ACDCounts属性、GetACDName方法
?返回目录
CurAComp属性
当前的音频压缩引擎
读/写:读写
类型:long
VB语法:
Object.CurAComp = longVar longVar = Object.CurAComp VC语法:
Object.SetCurAComp(longVar); longVar = Object.GetCurAComp(); 说明:
该属性决定控件使用当前系统可用音频压缩引擎中的哪一个进行音频压缩,缺省为?-1′即不
进行音频压缩。
参见:
ACompCounts属性、GetACompName方法
?返回目录
CurARD属性
当前的音频发布(播放)设备
读/写:读写
类型:long
VB语法:
Object.CurARD = longVar longVar = Object.CurARD VC语法:
Object.SetCurARD(longVar); longVar = Object.GetCurARD(); 说明:
该属性决定控件使用当前系统可用音频发布设备中的哪一个设备进行音频发布,缺省为?0′
即第一个音频发布设备。
参见:
ARDCounts属性、GetARDName方法
?返回目录
CurVCD属性
当前的视频捕捉设备
读/写:读写
类型:long
VB语法:
Object.CurVCD = longVar longVar = Object.CurVCD VC语法:
Object.SetCurVCD(longVar); longVar = Object.GetCurVCD(); 说明:
该属性决定控件使用当前系统可用视频捕捉设备中的哪一个设备进行视频捕捉,缺省为?0′
即第一个视频捕捉设备。
参见:
VCDCounts属性、GetVCDName方法
?返回目录
CurVCDInput属性
被选中视频捕捉设备的当前输入通道
读/写:读写
类型:long
VB语法:
Object.CurVCDInput = longVar longVar = Object.CurVCDInput VC语法:
Object.SetCurVCDInput(longVar); longVar = Object.GetCurVCDInput();
说明:
该属性决定被选中视频捕捉设备使用哪一个输入通道获取视频源,缺省为?0′即使用第一个
通道。该属性是一个持续属性~
参见:
VCDInputCounts属性、GetVCDInputName方法 ?返回目录
CurVComp属性
当前的视频压缩引擎
读/写:读写
类型:long
VB语法:
Object.CurVComp = longVar longVar = Object.CurVComp VC语法:
Object.SetCurVComp(longVar); longVar = Object.GetCurVComp(); 说明:
该属性决定控件使用当前系统可用视频压缩引擎中的哪一个进行视频压缩,缺省为?-1′即不
进行视频压缩。
参见:
VCompCounts属性、GetVCompName方法
?返回目录
DefaultMenuItems属性
缺省菜单项掩码
读/写:读写
类型:long
VB语法:
Object.DefaultMenuItems = lVar lVar = Object.DefaultMenuItems VC语法:
Object.SetDefaultMenuItems(lVar); lVar = Object.GetDefaultMenuItems(); 说明:
通过该属性可以利用一个控件定义的枚举值组合来决定缺省菜单中显示哪些菜单项。
菜单项枚举类型定义(IDL):
typedef enum {
PlayItem = 0×0001, //播放
PauseItem = 0×0002, //暂停
StopItem = 0×0004, //停止
CopyToClipboardItem = 0×0008, //抓图
TakePictureItem = 0×0010, //照相
PreviewItem = 0×0020, //预览
CaptureToFileItem = 0×0040, //录制到文件
VCDSelectItem = 0×0080, //视频采集设备
VCQSelectItem = 0×0100, //视频采集质量
VCISelectItem = 0×0200, //视频输入选择
VCompSelectItem = 0×0400, //视频压缩
ACDSelectItem = 0×0800, //音频采集设备
ACompSelectItem = 0×1000, //音频压缩
AllItem = 0x1FFF //所有项
}EMenuItem ;
参见:
DefaultMenuCommand事件
?返回目录
EnableDefaultMenu属性
是否使用控件提供的缺省弹出式菜单
读/写:读写
类型:bool
VB语法:
Object.EnableDefaultMenu = boolVar boolVar = Object.EnableDefaultMenu VC语法:
Object.SetEnableDefaultMenu(boolVar); boolVar = Object.GetEnableDefaultMenu();
说明:
缺省菜单提供了对常用操作的支持,该属性缺省为?true?即允许使用控件提供的缺省弹出式
菜单。
?返回目录
Picture属性
控件待机状态时的背景图片
读/写:读写
类型:OLEobject
VB语法:
Object.Picture = pictureVar pictureVar = Object.Picture VC语法:
Object.SetPicture(pictureVar); pictureVar = Object.GetPicture(); 说明:
该属性是一个标准的OLE对象,其具体使用方法参见相关MSDN文档。 ?返回目录
PlayState属性
控件运行状态
读/写:读写
类型:EPlayState(控件定义的long枚举类型)
类型定义(IDL):
typedef enum {
Stopped, // 停止
Plaing, //运行
Paused //暂停
} EPlayState;
VB语法:
Object.PlayState = enumVar enumVar = Object.PlayState VC语法:
Object.SetPlayState(enumVar); enumVar = Object.GetPlayState(); 说明:
该属性可以控制和掌握控件的运行状态,。
?返回目录
PreviewAudio属性
控件运行时是否预览音频
读/写:读写
类型:bool
VB语法:
Object.PreviewAudio = boolVar boolVar = Object.PreviewAudio VC语法:
Object.SetPreviewAudio(boolVar); boolVar = Object.GetPreviewAudio(); ?返回目录
PreviewVideo属性
控件运行时是否预览视频
读/写:读写
类型:bool
VB语法:
Object.PreviewVideo = boolVar boolVar = Object.PreviewVideo VC语法:
Object.SetPreviewVideo(boolVar); boolVar = Object.GetPreviewVideo(); ?返回目录
TitleGenerator属性
视频字幕
读/写:只读
类型:COMobject(控件定义的COM对象)
对象方法:无
对象属性:
TitleGenerator.Text //字幕文本,string类型。
TitleGenerator.Style //字幕风格,控件定义的枚举类型。
//typedef enum {TGSNormal(普通), TGSClear(清晰,即带边框)} ETGStyle; TitleGenerator.Font //OLE 字幕字体,字体对象类型。
TitleGenerator.TextColor //32RGB 字幕文本颜色,位颜色编码类型。TitleGenerator.PosX //X(0,0) 字幕向位置,视频左上角为,度量为屏幕像素。TitleGenerator.PosY //X(0,0) 字幕向位置,视频左上角为,度量为屏幕像素。TitleGenerator.FrameColor //32RGB 字幕文本的边框颜色,位颜色编码类型。对象事件:无
VB语法:
Object.TitleGenerator.Text = stringVar stringVar = Object.TitleGenerator.Text Object.TitleGenerator.Style = enumVar enumVar = Object.TitleGenerator.Style VC语法:
CTitleGenerator & rTG = Object.GetTitleGenerator();
rTG.SetText(stringVar);
stringVar = rTG.GetText();
rTG.SetStyle(enumVar);
enumVar = rTG.GetStyle();
说明:
该属性是一个控件定义的COM对象,通过修改该COM对象的属性可以控制字幕的字体、尺寸、颜色、风格等特性。[字幕需要8.0或更高版本DirectX的支持] ?返回目录
VCDCounts属性
当前系统中可供使用的视频捕捉设备的数量
读/写:只读
类型:long
VB语法:
[longVar] = Object.VCDCounts
VC语法:
[longVar] = Object.GetVCDCounts(); 参见:
CurVCD属性、GetVCDName方法
?返回目录
VCDInputCounts属性
被选中视频捕捉设备输入通道的数量
读/写:只读
类型:long
VB语法:
[longVar] = Object.VCDInputCounts
VC语法:
[longVar] = Object.GetVCDInputCounts();
参见:
CurVCDInput属性、GetVCDInputName方法 ?返回目录
VCompCounts属性
当前系统中可供使用的视频压缩引擎的数量 读/写:只读
类型:long
VB语法:
longVar = Object.VCompCounts
VC语法:
longVar = Object.GetVCompCounts();
参见:
CurVComp属性、GetVCompName方法 ?返回目录
VideoHeight属性
当前捕捉视频的高度(单位为:像素)
读/写:只读
类型:long
VB语法:
longVar = Object.VideoHeight
VC语法:
longVar = Object.GetVideoHeight();
参见:
VideoWidth属性
?返回目录
VideoSampleMachining属性
视频样本处理器
读/写:只读
类型:COMobject(控件定义的COM对象)
对象方法:无
对象属性:
VideoSampleMachining.Inversion //视频是否翻转,bool类型。 VideoSampleMachining.MirrorImage //视频是否镜像,bool类型。 对象事件:无
VB语法:
Object.VideoSampleMachining.Inversion = boolVar boolVar= Object.VideoSampleMachining.Inversion
Object.VideoSampleMachining.MirrorImage = boolVar boolVar = Object.VideoSampleMachining.MirrorImage VC语法:
CVideoSampleMachining & rVSM = Object.GetVideoSampleMachining(); rVSM.SetInversion(boolVar);
boolVar= rVSM.GetInversion();
rVSM.SetMirrorImage(boolVar);
boolVar= rVSM.GetMirrorImage();
说明:
该属性是一个控件定义的COM对象,通过修改该COM对象的属性可以控制视频是否翻转和镜
像。[视频翻转和视频镜像需要8.0或更高版本DirectX的支持 ]?返回目录
VideoWidth属性
当前捕捉视频的宽度(单位为:像素)
读/写:只读
类型:long
VB语法:
longVar = Object.VideoWidth VC语法:
longVar = Object.GetVideoWidth(); 参见:
VideoHeight属性
关键字: AVCapture
AVCapture使用说明-方法
admin 发表于 2010-12-04 05:25 | 来源: | 阅读 205 views
Coarseness方法(降低视频捕捉分辨率)
Fine方法(提高视频捕捉分辨率)
GetACDName方法(获取音频捕捉设备的名称)
GetACompName方法(获取音频压缩引擎的名称)
GetARDName方法(获取音频发布设备的名称)
GetCurrentImage方法(抓图)
GetVCDInputName方法(获取视频输入通道的名称)
GetVCDName方法(获取视频捕捉设备的名称)
GetVCompName方法(获取视频捕捉设备的名称)
ShowConfigureDialog方法(启动过滤器提供的配置对话框) TakePictureToFile方法(照相)
Coarseness方法
降低视频捕捉分辨率
参数:
无。
返回值:
无。
VB语法:
Object.Coarseness
VC语法:
Object.Coarseness();
说明:
该方法将当前视频捕捉设备的捕捉分辨率调整为一个更低但肯定被支持的分辨率。例如典型
的PAL制式数字视频捕捉设备支持720×576、360×288、180×144、88×72四个分辨率,
如果当前的分辨率为360×288,调用Coarseness后,分辨率将降为180×144。 ?返回目录
Fine方法
提高视频捕捉分辨率
参数:
无。
返回值:
无。
VB语法:
Object.Fine
VC语法:
Object.Fine();
说明:
该方法将当前视频捕捉设备的捕捉分辨率调整为一个更高但肯定被支持的分辨率。例如典型
的PAL制式数字视频捕捉设备支持720×576、360×288、180×144、88×72四个分辨率,
如果当前的分辨率为360×288,调用Fine后,分辨率将提高到720×576。 ?返回目录
GetACDName方法
获取音频捕捉设备的名称
参数:
lIndex — 指定音频捕捉设备的索引,索引值的合法范围为[ 0 ? lIndex ? Object.ACDCounts
- 1 ]。
返回值:
如果成功则返回一个音频捕捉设备名称字符串,否则返回一个空字符串。 VB语法:
Dim strName as String
strName = Object.GetACDName(Index) VC语法:
CString strName;
strName = Object.GetACDName(Index); 说明:
该方法用于获取由索引指定的音频捕捉设备的设备名称。
?返回目录
GetACompName方法
获取音频压缩引擎名称
参数:
lIndex — 指定音频压缩引擎的索引,索引值的合法范围为[ 0 ? lIndex ? Object.ACompCounts - 1 ]。
返回值:
如果成功则返回一个音频压缩引擎名称字符串,否则返回一个空字符串。 VB语法:
Dim strName as String
strName = Object.GetACompName(Index) VC语法:
CString strName;
strName = Object.GetACompName(Index); 说明:
该方法用于获取由索引指定的音频压缩引擎的名称。
?返回目录
GetARDName方法
获取音频发布(播放)设备名称
参数:
lIndex — 指定音频发布设备的索引,索引值的合法范围为[ 0 ? lIndex ? Object.ARDCounts
- 1 ]。
返回值:
如果成功则返回一个音频发布设备名称字符串,否则返回一个空字符串。 VB语法:
Dim strName as String
strName = Object.GetARDName(Index) VC语法:
CString strName;
strName = Object.GetARDName(Index); 说明:
该方法用于获取由索引指定的音频发布设备的名称。音频发布设备是指用来播放音频流的输出设备,如:DirectSound、WaveOut等。
?返回目录
GetCurrentImage方法
从当前视频流中抓取一帧图象到一个Picture对象中
参数:
无。
返回值:
如果成功返回一个Picture对象,该Picture对象中包含本方法调用所抓取的图象。 VB语法:
Dim Pic as StdPicture
Set Pic = Object.GetCurrentImage VC语法:
CPicture oPic;
oPic = Object.GetCurrentImage(); 说明:
该方法在当前视频流中以DIB位图
抓取被调用瞬间的一帧图象,并以此位图创建和返回一个标准Picture对象。[为了保证该方法的成功调用,建议安装DirectX 8.x] ?返回目录
GetVCDInputName方法
获取指定视频输入通道的名称
参数:
lIndex — 指定视频输入通道的索引,索引值的合法范围为[ 0 ? lIndex ? Object.VCDInputCounts - 1 ]。
返回值:
如果成功则返回一个音频发布设备名称字符串,否则返回一个空字符串。 VB语法:
Dim strName as String
strName = Object.GetVCDInputName(Index) VC语法:
CString strName;
strName = Object.GetVCDInputName(Index); 说明:
该方法并不总是适用,对于大部分数字视频捕捉设备而言,视频流仅仅来源于单一通道,不存在输入通道选择的问题,因此也不许要定义输入通道名称,甚至不需要输入通道这个概念。但许多模拟视频捕捉卡(例如FlyVideo)有3个甚至更多视频输入通道可供选择,通常每一个输入通道都有其独有的名称。
?返回目录
GetVCDName方法
获取视频捕捉设备的名称
参数:
lIndex — 指定视频捕捉设备的索引,索引值的合法范围为[ 0 ? lIndex ? Object.VCDCounts
- 1 ]。
返回值:
如果成功则返回一个视频捕捉设备名称字符串,否则返回一个空字符串。 VB语法:
Dim strName as String
strName = Object.GetVCDName(Index) VC语法:
CString strName;
strName = Object.GetVCDName(Index); 说明:
该方法用于获取由索引指定的视频捕捉设备的设备名称。
?返回目录
GetVCompName方法
获取视频压缩引擎名称
参数:
lIndex — 指定视频压缩引擎的索引,索引值的合法范围为[ 0 ? lIndex ? Object.VCompCounts - 1 ]。
返回值:
如果成功则返回一个视频压缩引擎名称字符串,否则返回一个空字符串。 VB语法:
Dim strName as String
strName = Object.GetVCompName(Index) VC语法:
CString strName;
strName = Object.GetVCompName(Index); 说明:
该方法用于获取由索引指定的视频压缩引擎的名称。
?返回目录
ShowConfigureDialog方法
启动过滤器提供的配置对话框
参数:
eDlg — 指定希望启动的对话框,该变量是一个枚举量其取值及含义如下: AudioCaptureDeviceConfigure — 音频捕捉设备配置对话框
VideoCaptureDeviceConfigure — 视频捕捉设备配置对话框
VideoCaptureFormatConfigure — 视频捕捉格式配置对话框
AVIMuxConfigure — AVI混合器配置对话框
OtherConfigure — 其他配置对话框
返回值:
无。
VB语法:
Object.ShowConfigureDialog (VideoCaptureDeviceConfigure) „启动视频配置对话框设置视频捕捉设备
VC语法:
Object.ShowConfigureDialog(VideoCaptureDeviceConfigure); //启动视频配置对话框设置视频捕捉设备
说明:
该方法用于启动一些音/视频捕捉相关的关键过滤器的配置对话框,对这些过滤器进行一些被支持的参数设置,这些对话框均有过滤器开发商实现,其使用的语言和布局由系统中所安装DirectX组件版本决定。
?返回目录
TakePictureToFile方法
从当前视频流中抓取一帧图象到一个文件中或系统剪贴板中
参数:
bstrFileName — 指定保存图象的文件名。
返回值:
无。
VB语法:
Object.TakePictureToFile (“C:\test.bmp”) „抓取一帧图象并保存到文件
中。 Object.TakePictureToFile (“”) „抓取一帧图象并放到系统剪贴板中。 VC语法:
Object.TakePictureToFile(“C:\\test.bmp”); //抓取一帧图象并保存到文件中。 Object.TakePictureToFile(“”); //抓取一帧图象并放到系统剪贴板中。 说明:
该方法在当前视频流中以DIB位图格式抓取被调用瞬间的一帧图象,并将此位图保存到指定的文件中或系统剪贴板中。[DirectX 8.x] 为了保证该方法的成功调用,建议安装
?返回目录
易语言教程-Win32编程(一)
admin 发表于 2010-08-06 18:40 | 来源: | 阅读 352 views 在易语言中 我们的窗口是随随便便就“画”出来的,以至于我们对系统深入的细节不了解。 下面我将带领大家领略Windows的神奇,当然,媒介就是有些朋友恐慌的Win32API函数了。
不过不必担心,我会尽量详细介绍用到的API函数,还请大家多多关注 不驹E阁 论坛,最好能推荐朋友来一起学习领略Windows的编程细节。
本节内容是初识Windows窗口,如果我现在说,不用易语言的窗口,怎么写一个窗口程序呢,
可能这会难倒一些朋友了,那现在我们来看一段代码。
首先,需要修改一下设置,规定一下程序的入口。
工具-系统配置-Windows窗口启动方式-通过名称为“_启动子程序”的子程序启动 , .版本 2
, .程序集 程序集1
, .程序集变量 集_实例句柄, 整数型
, .程序集变量 集_窗口句柄, 整数型
, .子程序 _启动子程序, 整数型, , 本子程序在程序启动后最先执行
, .局部变量 msg, MSG
, 注册窗口类 ()
, 集_窗口句柄 , API_CreateWindowEx (0, “www.xxbc8.cn”, “[able教你Win32编程]
初识窗口”, 位或 (#WS_VISIBLE, #WS_MAXIMIZEBOX, #WS_MINIMIZEBOX,
#WS_SYSMENU), 0, 0, 400, 300, 0, 0, 集_实例句柄, 0)
, API_ShowWindow (集_窗口句柄, #SW_SHOW) ? 显示窗口
, API_UpdateWindow (集_窗口句柄) ? 更新窗口,重画
, „ ———————————————-
, „ >>>>>>>>>>>>> 进入消息循环 <<<<<<<<<<<<<<<<< , „ ———————————————-
, .判断循环首 (API_GetMessage (msg, 0, 0, 0) ? 0) ? 从消息队列中提取消息并删除,如果
返回0代表WM_QUIT
, API_TranslateMessage (msg) ? 转换虚拟关键字消息 , API_DispatchMessage (msg) ? 向窗口发送消息
, .判断循环尾 ()
, 返回 (0) ? 可以根据您的需要返回任意数值
, .子程序 注册窗口类
, .局部变量 wc, WNDCLASSEX
, 集_实例句柄 , API_GetModuleHandle_int (0) , wc.cbSize , 48 ? 结构大小
, wc.style , 位或 (#CS_HREDRAW, #CS_VREDRAW, #CS_DBLCLKS) ? 类风格 , wc.hCursor , API_LoadCursor (0, #IDC_ARROW) ? 鼠标指针 , wc.hIcon , API_LoadIcon (集_实例句柄, 129) ? 易语言图标 , wc.hbrBackground , #COLOR_WINDOW ? 背景颜色 WINDOWS预定的颜色,且规定
必须+1
, wc.lpszClassName , “www.xxbc8.cn” ? 有些朋友熟悉的窗口类名 , wc.hInstance , 集_实例句柄 ? 程序实例句柄
, wc.lpfnWndProc , 到整数 (&WndProc) ? 窗口过程函数地址 , API_RegisterClassEx (wc) ? 注册窗口类
, .子程序 WndProc, 整数型, , 窗口过程函数
, .参数 hWnd, 整数型, , 窗口句柄
, .参数 uMsg, 整数型, , 消息标志
, .参数 wParam, 整数型, , 自定义参数1
, .参数 lParam, 整数型, , 自定义参数2
, .判断开始 (uMsg , #WM_LBUTTONDBLCLK) ? 鼠标左键双击消息 , 信息框 (“双击了窗口”, 0, )
, 返回 (0)
, .判断 (uMsg , #WM_CLOSE) ? 窗口关闭消息
, 信息框 (“窗口即将关闭”, 0, )
, API_DestroyWindow (hWnd) ? 摧毁窗口
, API_PostQuitMessage (0) ? 结束消息循环
, 返回 (0)
, .默认
, .判断结束
, 返回 (API_DefWindowProc (hWnd, uMsg, wParam, lParam)) ? 默认处理消息 复制代码
作用是创建如下窗口:
下载 (12.46 KB)
2010-7-17 05:52
接下来是对代码的解说了,本想通过视频教程来介绍,不过内容多,没那么多口水,且麦出了问题。
注册窗口类
首先我们看注册窗口类这个子程序,大家熟悉的窗口一般会有窗口标题和窗口类名。 其实这个窗口类名就是注册窗口类(WndClass)的时候定义的,每个窗口必须要有一个窗口类(WndClass),我们的窗口需要自己注册一个窗口类(WndClass)。Ps:接下来窗口类都用WndClass 注册窗口类可以用RegisterClassEx这个函数(Register:注册;Class:类;Ex:拓展),参数只有一个,是一个WNDCLASSEX结构。
WND是Window(窗口)的缩写,CLASS和EX前面说了。
我们来看WNDCLASSEX结构的定义:
下载 (45.12 KB)
2010-7-17 06:18
既然是第一课,那就不得不多扯一些了,我们所说的句柄(handle)一般对应一个对象,比如一个窗口句柄对应一个窗口,一个线程句柄对应一个线程,一个实例句柄对应一个模块……。
对我们来说,句柄只是一个数值,但是对于系统来说句柄是一个资源的标识,像编号一样,用句柄就可以找到对应的东西,有句柄就可以做很多XE的事了。
API的参数中h开头的参数就代表参数要提供一个句柄(handle)。这个就是匈牙利命名法了,类似的还有:
lpsz(文本型:0结尾的字符串指针)Long 长 Pointer 指针 String字符串 Zero 零 lpfn(整数型:函数(子程序)指针)lp同上,Function 函数
详细可以看
继续介绍WNDCLASSEX结构,
?
hIcon——图标句柄,指定显示在窗口标题栏左上角的图标。Windows已经预定义了一些图标,同样,程序也可以使用在资源文件中定义的图标,这些图标的句柄可以用LoadIcon函数获得。例子程序没有用到图标,所以Windows给窗口显示了一个默认的图标。
?
hCursor——光标句柄,指定了鼠标在窗口中的光标形状。同样,Windows也预定义了一些光标,可以用LoadCursor获取它们的句柄,IDC_ARROW是
Windows预定义的箭头光标,如果想使用自定义的光标,也可以自己在资源文件中定义。
?
lpszMenuName——指定窗口上显示的默认菜单,它指向一个字符串,描述资源文件中菜单的名称,如果资源文件中菜单是用数值定义的,那么这里使用菜单资源的数值。窗口中的菜单也可以在建立窗口函数CreateWindowEx的参数中指定。如果在两个地方都没有指定,那么建立的窗口上就没有菜单。 ?
hInstance——指定要注册的窗口类属于哪个模块,模块句柄在程序开始的地方已经用GetModuleHandle函数获得。
?
cbSize——指定WNDCLASSEX结构的长度,用sizeof伪操作来获取。很多Win32 API参数中的结构都有cbSize字段,它主要是用来区分结构的版本,当以后新增了一个字段时,cbSize就相应增大,如果调用的时候cbSize还是老的长度,表示运行的是基于旧结构的程序,这样可以防止使用无效的字段。 ?
style——窗口风格。CS_HREDRAW和CS_VREDRAW表示窗口的宽度或高度改变时是否重画窗口。比较重要的是CS_DBLCLKS风格,指定了它,Windows才会把在窗口中快速两次单击鼠标的行为翻译成双击消息WM_LBUTTONDBLCLK发给窗口过程。笔者就曾经忘了指定它,结果怎么也搞不出双击消息来。
?
hbrBackground——窗口客户区的背景色。前面的hbr表示它是一个刷子(Brush)的句柄,“刷子”一词形象地表示了填充一个区域的着色模式。Windows预定义了一些刷子,如BLACK_BRUSH和WHITE_BRUSH等,可以用下列语句来得到它们的句柄:
wc.hbrBackground =
GetObjectStock (#WHITE_BRUSH)
但在这里也可以使用颜色值,Windows已经预定义了一些颜色值,分别对应窗口各部分的颜色,如COLOR_BACKGROUND,COLOR_HIGHLIGHT,COLOR_MENU和COLOR_WINDOW等,使用颜色值的时候,Windows规定必须在颜色值上加1,所以程序中的指令是:
wc.hbrBackground = #COLOR_WINDOW + 1
?
lpszClassName——指定程序员要建立的类命名,以便以后用这个名称来引用它。这个字段是一个字符串指针,在程序里,它指向“MyClass”字符串。 ?
cbWndExtra和cbClsExtra——分别是在Windows内部保存的窗口结构和类
结构中给程序员预留的空间大小,用来存放自定义数据,它们的单位是字节。不使用自定义数据的话,这两个字段就是0。
?
lpfnWndProc——最重要的参数,它指定了基于这个类建立的窗口的窗口过程地址。通过这个参数,Windows就知道了在DispatchMessage函数中把窗口消息发到哪里去,一个窗口过程可以为多个窗口服务,只要这些窗口是基于同一个窗口类建立的。Windows中不同应用程序中的按钮和文本框的行为都是一样的,就是因为它们是基于相同的Windows预定义类建立的,它们背后的窗口过程其实是同一段代码。
结构中的style表示窗口的风格,Windows已经有一些预定义的值,它们是以CS(Class Style的缩写)开始的标识符,如表4.1所示。
表4.1
一些窗口类的style预定义值
预定义值 16进制值 对应二进制位
CS_VREDRAW 00000001h 0
CS_HREDRAW 00000002h 1
CS_KEYCVTWINDOW 00000004h 2
CS_DBLCLKS 00000008h 3
CS_OWNDC 00000020h 5
CS_CLASSDC 00000040h 6
„
可以看到,这些预定义值实际上在使用不重复的数据位,所以可以组合起来使用,同时使用不同的预定义值并不会引起混淆。
摘自《Windows环境下32汇编语言程序设计》,有所修改。
1.实例句柄可以用GetModuleHandle函数获取,因为本来参数是文本型,但是只要填0就可以取得程序本身的实例句柄。
所以我改了参数的类型,当然也在函数后面加了后缀成了API_GetModuleHandle_int代表我改过了。
2.结构大小需要我们来计算,内存中每个整数型占4字节,文本型传递的是指针,所以也是4字节。12*4就是48了。
3.位或()是位运算中的一个命令,用来组合多种风格,弄到一坨。有兴趣的可以自己看看位运算,了解还是比较好的。
4.LoadCursor和LoadIcon分别用来装载鼠标光标和图标,如果装载系统预设的,第一个参数实例句柄就必须填0。所以获取默认的鼠标光标句柄是API_LoadCursor (0, #IDC_ARROW),而易语言图标是在程序中而不是系统预设的,易语言图标的ID是129,所以API_LoadIcon (集_实例句柄, 129)装载易语言图标。
5.子程序的地址可以用 到整数( &子程序名 )获得。 &是取子程序指针 到整数转换为整数型。
注册完了窗口类,就可以创建我们的窗口了。
建立窗口
创建窗口用到的函数是CreateWindowEx,函数声明如下:
下载 (51.77 KB)
2010-7-17 21:29
?
lpClassName—建立窗口使用的类名字符串指针,在FirstWindow程序中指向“MyClass”字符串,表示使用“MyClass”类建立窗口,这正是我们自己注册的类,这样一来,这个窗口就有“MyClass”的所有属性,并且消息将被发到“MyClass”中指定的窗口过程中去,当然,这里也可以是Windows预定义的类名。
?
lpWindowName——指向表示窗口名称的字符串,该名称会显示在标题栏上。如果该参数空白,则标题栏上什么都没有。
?
hMenu——窗口上要出现的菜单的句柄。在注册窗口类的时候也定义了一个菜单,那是窗口的默认菜单,意思是如果这里没有定义菜单(用参数NULL)而注册窗口类时定义了菜单,则使用窗口类中定义的菜单;如果这里指定了菜单句柄,则不管窗口类中有没有定义都将使用这里定义的菜单;两个地方都没有定义菜单句柄,则窗口上没有菜单。另外,当建立的窗口是子窗口时(dwStyle中指定了WS_CHILD),这个参数是另一个含义,这时hMenu参数指定的是子窗口的ID号,这样可以节省一个参数的位置,因为反正子窗口不会有菜单。
?
lpParam——这是一个指针,指向一个欲传给窗口的参数,这个参数在WM_CREATE消息中可以被获取,一般情况下用不到这个字段。 ?
hInstance——模块句柄,和注册窗口类时一样,指定了窗口所属的程序模块。 ?
hWndParent——窗口所属的父窗口,对于普通窗口(相对于子窗口),这里的“父子”关系只是从属关系,主要用来在父窗口销毁时一同将其“子”窗口销毁,并不会把窗口位置限制在父窗口的客户区范围内,但如果要建立的是真正的子窗口(dwStyle中指定了WS_CHILD的时候),这时窗口位置会被限制在父窗口的客户区范围内,同时窗口的坐标(x,y)也是以父窗口的左上角为基准的。
?
x,y——指定窗口左上角位置,单位是像素。默认时可指定
为 CW_USEDEFAULT,这样Windows会自动为窗口指定最合适的位置,当建立子窗口时,位置是以父窗口的左上角为基准的,否则,以屏幕左上角为基准。 ?
nWidth,nHeight—窗口的宽度和高度,也就是窗口的大小,同样是以像素为单位的。默认时可指定为CW_USEDEFAULT,这样Windows会自动为窗口指定最合适的大小。
窗口的两个参数dwStyle和dwExStyle决定了窗口的外形和行为,dwStyle是从Win16开始就有的属性,表4.2列出了一些常见的dwStyle定义,它们是一些以WS(Windows Style的缩写)为开头的预定义值。 表4.2
窗口风格的预定义值
含 预定义值 16进制值 义
WS_OVERLAPPED 00000000h 普通的重叠式窗口
WS_POPUP 80000000h 弹出式窗口(没有标题栏)
WS_CHILD 40000000h 子窗口
WS_MINIMIZE 20000000h 初始状态是最小化的
WS_VISIBLE 10000000h 初始状态是可见的
WS_DISABLED 08000000h 初始状态是被禁止的
WS_MAXIMIZE 01000000h 初始状态是最大化的
WS_BORDER 00800000h 单线条边框
WS_DLGFRAME 00400000h 对话框类型的边框
WS_VSCROLL 00200000h 带垂直滚动条
WS_HSCROLL 00100000h 带水平滚动条
WS_SYSMENU 00080000h 带系统菜单(即带标题栏左上角的图标) WS_THICKFRAME 00040000h 可以拖动调整大小的边框
WS_MINIMIZEBOX 00020000h 有最小化按钮
WS_MAXIMIZEBOX 00010000h 有最大化按钮
为了容易理解,Windows也为一些定义取了一些别名,同时,由于窗口的风格往往是几种风格的组合,所以Windows也预定义了一些组合值,如表4.3所示。 表4.3
等效的窗口风格预定义值
等
预定义值 效
值
WS_CHILDWINDOW WS_CHILD
WS_TILED WS_OVERLAPPED
WS_ICONIC WS_MINIMIZE
WS_SIZEBOX WS_THICKFRAME
WS_OVERLAPPED or WS_CAPTION or WS_SYSMENU or WS_THICKFRAME or WS_OVERLAPPEDWINDOW WS_MINIMIZEBOX or WS_MAXIMIZEBOX
WS_TILEDWINDOW WS_OVERLAPPEDWINDOW
WS_POPUPWINDOW WS_POPUP or WS_BORDER or WS_SYSMENU
dwExStyle是Win32中扩展的,它们是一些以WS_EX_开头的预定义值,主要定义了一些特殊的风格,表4.4给出了一些最常用的特殊风格。
表4.4
窗口扩展风格的预定义值
含 预定义值 16进制值 义
WS_EX_TOPMOST 00000008h 总在顶层的窗口
WS_EX_ACCEPTFILES 00000010h 允许窗口进行鼠标拖放操作
WS_EX_TOOLWINDOW 00000080h 工具窗口(很窄的标题栏)
WS_EX_WINDOWEDGE 00000100h 立体感的边框
WS_EX_CLIENTEDGE 00000200h 客户区立体边框
含 预定义值 16进制值 义
WS_EX_OVERLAPPEDWINDOW WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE
WS_EX_WINDOWEDGE or WS_EX_TOOLWINDOW or WS_EX_PALETTEWINDOW WS_EX_TOPMOST
用预定义的组合值WS_EX_PALETTEWINDOW可以很方便地构成浮在其他窗口前面的工具栏。
集_窗口句柄 , API_CreateWindowEx (0, “www.xxbc8.cn”, “[able教你Win32编程] 初识窗口”, 位或 (#WS_VISIBLE, #WS_MAXIMIZEBOX, #WS_MINIMIZEBOX,
#WS_SYSMENU), 0, 0, 400, 300, 0, 0, 集_实例句柄, 0)
这行代码会创建一个没有拓展风格的类名为“www.xxbc8.cn”,标题为“[able教你Win32编程] 初识窗口”,可以看到的,有最大化最小化菜单按钮并且带系统自带的菜单(最大化,最小化,还原,关闭),宽为400,高为300的一个窗口,且创建后在屏幕的左上角。
CreateWindowEx会返回创建窗口的窗口句柄,接下来我们只要Show(显示)Window,Update(更新)Window。窗口就显示了API_ShowWindow (集_窗口句柄, #SW_SHOW) ? 显示窗口
API_UpdateWindow (集_窗口句柄) ? 更新窗口,重画
紧接着就是消息循环了,下一篇文章(二)将介绍消息循环和窗口过程函数,敬请期待。 Ps:初学者可能有点头晕,不过没关系,混过去就好,之后的内容更容易接受,概念性的东西有点印象,说不定哪天就开窍了。
易语言教程-Win32编程(二)
admin 发表于 2010-08-06 18:41 | 来源: | 阅读 266 views 上篇文章我们说了窗口类的注册和窗口的创建与显示更新窗口,马上进入的就是消息循环了。 如果我们的“_启动子程序”返回了,那我们的程序也就结束了,所以窗口创建以后后面接着消息循环是必然的。
Ps:后面将介绍的模态对话框稍有不同。要说消息循环,必须先简单介绍消息机制了。 Windows消息机制
说到消息机制,那就先扯扯DOS下编程了:
DOS下的编程语言一般只能是16位的汇编语言,如果想要捕获用户动作,就得通过各种中断,天天翻中断手册是非常痛苦的。
但是现在好了,中断进化了,摇身一变成了消息机制。
用户的动作系统会用消息提醒我们的窗口,消息是非常非常多的,譬如说我们轻轻动一下鼠标,结果是产生10多条消息。
消息按照产生的时间排队组成了一个队伍,程序一条条的来处理,这就是消息队列,系统会为每个线程都维护一个队列。
Ps:每个进程中有1个或者多个线程工作。
消息循环
消息循环就是不断的从消息队列中提取出消息并且转译+转移的过程。
转译,就是将虚拟键消息转换为字符消息,比如WM_KEYDOWN(键盘按下消息)还要产生WM_CHAR(字符输入消息)。
转移,就是把消息发送给窗口过程函数了,后面会介绍到。
一般的消息循环就是我们这个结构了:
下载 (19.72 KB)
2010-7-18 23:33
窗口过程函数
窗口会收到许许多多的消息,我们要处理他们,处理的方式就是系统把消息传达给我们的窗口函
数(WndProc),在窗口函数中处理。
窗口过程函数定义如下:
下载 (18.45 KB)
2010-7-19 07:31
其中消息标志是非常丰富的,wParam和lParam是随消息标志的不同而有不同含义的,而具体是什么样得通过查阅资料,比如MSDN Library。
窗口函数是在注册窗口类的时候把地址注册给系统了,所以系统能够根据类名发送消息到窗口函数来,如果我们注册了一个类,并且用这个类注册了2个窗口,那么2个窗口是共用这个WndProc的。
处理消息
下面看看我们窗口函数的内容:
下载 (20.32 KB)
2010-7-19 07:37
其实看起来不是那么复杂,我们只是判断收到的是什么消息,然后做我们想做的事。回想一下易语言的事件,不就是这么来的吗,
比如键盘按下事件是收到WM_KEYDOWN消息后触发的,可否关闭事件是收到WM_CLOSE消息后触发的。
当然消息的种类是十分多的,我们自己处理的消息只是极少部分,返回值一般0就可以了,具体还得查阅MSDN Library。
对于我们不想处理的消息系统可以帮我们来处理,那就是我们的最后一行了。Def(Define定义)WindowProc,就是系统按照默认的方式来处理消息了。Ps:当然不要忘了返回他的返回值。
嘛,整个程序的脉络清楚之后,50行代码也算不上啥了是吧。
VC++ 捕捉摄像头视频
作者: 来源:csdn 发布者:admin
时间:2009-07-08 11:26:10 点击:1895
VC++ 捕捉摄像头视频!摘要:本文主要讲述用Directshow进行视频捕捉(捕捉静态图像)的编程思路,并提供针对摄像头编程的一个视频捕捉类CcaptureVideo和一个示例。
前言
DirectShow是微软公司提供的一套在Windows平台上进行流媒体处理的开发包,与DirectX开发包一起发布。DirectShow为多媒体流的捕捉和回放提供了强有力的支持。用DirectShow开发应用程序,我们可以很方便地从支持WDM驱动模型的采集卡上捕获数据,并且进行相应的后期处理乃至存储到文件中。
DirectShow是基于COM的,为了编写DirectShow应用程序,需要了解COM客户程序编写的基础知识。DirectShow提供了大量的接口,但在编程中发现还是不够方便,如果能构建一个视频捕捉类把常用的一些动作封装起来,那么就更方便了。
编程思路
为了更加容易建立视频捕捉应用程序,DirectShow提供了一个叫做Capture Graph Builder的对象,Capture Graph Builder提供IcaptureGraphBuilder2接口,该接口可以建立和控制Capture Graph。
建立视频捕捉程序,必须首先获取并初始化IcaptureGraphBuilder2接口,然后选择一个适当的视频捕捉设备。选择好设备后,为该设备创建Capture filter,然后调用AddFilter把Capture filter添加到Filter Graph。
如果仅仅希望用摄像头来进行实时监控的话,只需要在上面的基础上调用ICaptureGraphBuilder2::RenderStream就可以了:
ICaptureGraphBuilder2 *pBuild; // Capture Graph Builder
//省略初始化部分代码
IBaseFilter *pCap; // Video capture filter. //省略初始化和添加到Filter Graph部分代码
pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap, NULL, NULL);
DirectShow提供了一个捕捉静态图像的方法:使用Sample Grabber filter。依次按照
以下三个步骤就可以了:
第一步, 定义一个类实现Sample Grabber的回调接口IsampleGrabberCB:
class CSampleGrabberCB : public ISampleGrabberCB
{
//在后面提供的类中具体完成
}
CSampleGrabberCB mCB;
第二步、调用RenderStream依次把Still pin、Sample Grabber和系统默认Renderer
Filter连接起来。
第三步、配置Sample Grabber以捕获数据。
视频捕捉类CCaptureVideo的具体实现
// CCaptureVideo视频捕捉类头文件
///////////////////////////////////////////////////////////////////// #if !defined(AFX_CAPTUREVIDEO_H__F5345AA4_A39F_4B07_B843_3D87C4287AA0__INCLUDED_)
#define
AFX_CAPTUREVIDEO_H__F5345AA4_A39F_4B07_B843_3D87C4287AA0__INCLUDED_
///////////////////////////////////////////////////////////////////// // CaptureVideo.h : header file
/////////////////////////////////////////////////////////////////////
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000 #include
#include
#include
#ifndef SAFE_RELEASE
#define SAFE_RELEASE( x ) \ if ( NULL != x ) \
{ \
x->Release( ); \
x = NULL; \
}
#endif
class CSampleGrabberCB;
class CCaptureVideo : public CWnd {
friend class CSampleGrabberCB;
public:
void GrabOneFrame(BOOL bGrab);
HRESULT Init(int iDeviceID,HWND hWnd);
int EnumDevices(HWND hList);
CCaptureVideo();
virtual ~CCaptureVideo();
private:
HWND m_hWnd;
IGraphBuilder *m_pGB;
ICaptureGraphBuilder2* m_pCapture;
IBaseFilter* m_pBF;
IMediaControl* m_pMC;
IVideoWindow* m_pVW;
CComPtr m_pGrabber;
protected:
void FreeMediaType(AM_MEDIA_TYPE& mt);
bool BindFilter(int deviceId, IBaseFilter **pFilter);
void ResizeVideoWindow();
HRESULT SetupVideoWindow();
HRESULT InitCaptureGraphBuilder();
};
#endif
// !defined(AFX_CAPTUREVIDEO_H__F5345AA4_A39F_4B07_B843_3D87C4287AA0__INCLUDED_)
//------------------------------------------------------------------- // CCaptureVideo视频捕捉类实现文件CaptureVideo.cpp
//------------------------------------------------------------------- // CaptureVideo.cpp: implementation of the CCaptureVideo class. //
///////////////////////////////////////////////////////////////////// #include "stdafx.h"
#include "CaptureVideo.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
BOOL bOneShot=FALSE;//全局变量
class CSampleGrabberCB : public ISampleGrabberCB {
public:
long lWidth;
long lHeight;
TCHAR m_szFileName[MAX_PATH];// 位图文件名称
CSampleGrabberCB( ){
strcpy(m_szFileName, "c:\\donaldo.bmp");
}
STDMETHODIMP_(ULONG) AddRef() { return 2; }
STDMETHODIMP_(ULONG) Release() { return 1; }
STDMETHODIMP QueryInterface(REFIID riid, void ** ppv){
if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown ){
*ppv = (void *) static_cast ( this );
return NOERROR;
}
return E_NOINTERFACE;
}
STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample ){
return 0;
}
STDMETHODIMP BufferCB( double dblSampleTime, BYTE * pBuffer, long lBufferSize ){
if( !bOneShot )return 0;
if (!pBuffer)return E_POINTER;
SaveBitmap(pBuffer, lBufferSize);
bOneShot = FALSE;
return 0;
}
//创建位图文件
BOOL SaveBitmap(BYTE * pBuffer, long lBufferSize ) {
HANDLE hf = CreateFile(
m_szFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, NULL, NULL );
if( hf == INVALID_HANDLE_VALUE )return 0;
// 写文件头
BITMAPFILEHEADER bfh;
memset( &bfh, 0, sizeof( bfh ) );
bfh.bfType = ?MB?;
bfh.bfSize = sizeof( bfh ) + lBufferSize + sizeof( BITMAPINFOHEADER );
bfh.bfOffBits = sizeof( BITMAPINFOHEADER ) + sizeof( BITMAPFILEHEADER );
DWORD dwWritten = 0;
WriteFile( hf, &bfh, sizeof( bfh ), &dwWritten, NULL );
// 写位图格式
BITMAPINFOHEADER bih;
memset( &bih, 0, sizeof( bih ) );
bih.biSize = sizeof( bih );
bih.biWidth = lWidth;
bih.biHeight = lHeight;
bih.biPlanes = 1;
bih.biBitCount = 24;
WriteFile( hf, &bih, sizeof( bih ), &dwWritten, NULL );
// 写位图数据
WriteFile( hf, pBuffer, lBufferSize, &dwWritten, NULL );
CloseHandle( hf );
return 0;
}
};
CSampleGrabberCB mCB;
////////////////////////////////////////////////////////////////////// // Construction/Destruction
////////////////////////////////////////////////////////////////////// CCaptureVideo::CCaptureVideo()
{
//COM Library Intialization
if(FAILED(CoInitialize(NULL))) /*, COINIT_APARTMENTTHREADED)))*/
{
AfxMessageBox("CoInitialize Failed!\r\n");
return;
}
m_hWnd = NULL;
m_pVW = NULL;
m_pMC = NULL;
m_pGB = NULL;
m_pCapture = NULL;
}
CCaptureVideo::~CCaptureVideo() {
// Stop media playback
if(m_pMC)m_pMC->Stop();
if(m_pVW){
m_pVW->put_Visible(OAFALSE);
m_pVW->put_Owner(NULL);
}
SAFE_RELEASE(m_pCapture);
SAFE_RELEASE(m_pMC);
SAFE_RELEASE(m_pGB);
SAFE_RELEASE(m_pBF);
CoUninitialize( );
}
int CCaptureVideo::EnumDevices(HWND hList)
{
if (!hList)
return -1;
int id = 0;
//枚举视频扑捉设备
ICreateDevEnum *pCreateDevEnum;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum);
if (hr != NOERROR)return -1;
CComPtr pEm;
hr =
pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm,
0);
if (hr != NOERROR)return -1;
pEm->Reset();
ULONG cFetched;
IMoniker *pM;
while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
{
IPropertyBag *pBag;
hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
if(SUCCEEDED(hr))
{
VARIANT var;
var.vt = VT_BSTR;
hr = pBag->Read(L"FriendlyName", &var, NULL);
if (hr == NOERROR)
{
TCHAR str[2048];
id++;
WideCharToMultiByte(CP_ACP,0,var.bstrVal, -1, str, 2048, NULL, NULL);
::SendMessage(hList, CB_ADDSTRING, 0,(LPARAM)str);
SysFreeString(var.bstrVal);
}
pBag->Release();
}
pM->Release();
}
return id;
}
HRESULT CCaptureVideo::Init(int iDeviceID, HWND hWnd) {
HRESULT hr;
hr = InitCaptureGraphBuilder();
if (FAILED(hr)){
AfxMessageBox("Failed to get video interfaces!");
return hr;
}
// Bind Device Filter. We know the device because the id was passed in
if(!BindFilter(iDeviceID, &m_pBF))return S_FALSE;
hr = m_pGB->AddFilter(m_pBF, L"Capture Filter");
// hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
// m_pBF, NULL, NULL);
// create a sample grabber
hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
if( !m_pGrabber ){
AfxMessageBox("Fail to create SampleGrabber, maybe qedit.dll is not registered?");
return hr;
}
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
//设置视频格式
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
mt.majortype = MEDIATYPE_Video;
mt.subtype = MEDIASUBTYPE_RGB24;
hr = m_pGrabber->SetMediaType(&mt);
if( FAILED( hr ) ){
AfxMessageBox("Fail to set media type!");
return hr;
}
hr = m_pGB->AddFilter( pGrabBase, L"Grabber" );
if( FAILED( hr ) ){
AfxMessageBox("Fail to put sample grabber in graph");
return hr;
}
// try to render preview/capture pin
hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
if( FAILED( hr ) )
hr = m_pCapture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
if( FAILED( hr ) ){
AfxMessageBox("Can?t build the graph");
return hr;
}
hr = m_pGrabber->GetConnectedMediaType( &mt );
if ( FAILED( hr) ){
AfxMessageBox("Failt to read the connected media type");
return hr;
}
VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat;
mCB.lWidth = vih->bmiHeader.biWidth;
mCB.lHeight = vih->bmiHeader.biHeight;
FreeMediaType(mt);
hr = m_pGrabber->SetBufferSamples( FALSE );
hr = m_pGrabber->SetOneShot( FALSE );
hr = m_pGrabber->SetCallback( &mCB, 1 );
//设置视频捕捉窗口
m_hWnd = hWnd ;
SetupVideoWindow();
hr = m_pMC->Run();//开始视频捕捉
if(FAILED(hr)){AfxMessageBox("Couldn?t run the graph!");return hr;}
return S_OK;
}
bool CCaptureVideo::BindFilter(int deviceId, IBaseFilter **pFilter)
{
if (deviceId < 0)
return false;
// enumerate all video capture devices
CComPtr pCreateDevEnum;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void**)&pCreateDevEnum);
if (hr != NOERROR)
{
return false;
}
CComPtr pEm;
hr =
pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm,
0);
if (hr != NOERROR)
{
return false;
}
pEm->Reset();
ULONG cFetched;
IMoniker *pM;
int index = 0;
while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK, index <= deviceId)
{
IPropertyBag *pBag;
hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
if(SUCCEEDED(hr))
{
VARIANT var;
var.vt = VT_BSTR;
hr = pBag->Read(L"FriendlyName", &var, NULL);
if (hr == NOERROR)
{
if (index == deviceId)
{
pM->BindToObject(0, 0, IID_IBaseFilter, (void**)pFilter);
}
SysFreeString(var.bstrVal);
}
pBag->Release();
}
pM->Release();
index++;
}
return true;
}
HRESULT CCaptureVideo::InitCaptureGraphBuilder() {
HRESULT hr;
// 创建IGraphBuilder接口
hr=CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&m_pGB);
// 创建ICaptureGraphBuilder2接口
hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,
IID_ICaptureGraphBuilder2, (void **) &m_pCapture);
if (FAILED(hr))return hr;
m_pCapture->SetFiltergraph(m_pGB);
hr = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
if (FAILED(hr))return hr;
hr = m_pGB->QueryInterface(IID_IVideoWindow, (LPVOID *) &m_pVW);
if (FAILED(hr))return hr;
return hr;
}
HRESULT CCaptureVideo::SetupVideoWindow()
{
HRESULT hr;
hr = m_pVW->put_Owner((OAHWND)m_hWnd);
if (FAILED(hr))return hr;
hr = m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);
if (FAILED(hr))return hr;
ResizeVideoWindow();
hr = m_pVW->put_Visible(OATRUE);
return hr;
}
void CCaptureVideo::ResizeVideoWindow() {
if (m_pVW){
//让图像充满整个窗口
CRect rc;
::GetClientRect(m_hWnd,&rc);
m_pVW->SetWindowPosition(0, 0, rc.right, rc.bottom);
}
}
void CCaptureVideo::GrabOneFrame(BOOL bGrab)
{
bOneShot = bGrab;
}
void CCaptureVideo::FreeMediaType(AM_MEDIA_TYPE& mt)
{
if (mt.cbFormat != 0) {
CoTaskMemFree((PVOID)mt.pbFormat);
// Strictly unnecessary but tidier
mt.cbFormat = 0;
mt.pbFormat = NULL;
}
if (mt.pUnk != NULL) {
mt.pUnk->Release();
mt.pUnk = NULL;
}
}
如何使用视频捕捉类CCaptureVideo
构建CCaptureVideo类以后,使用就方便多了,我们在编程中只需要是要下面三个类成员函数就可以实现用摄像头进行视频捕捉:
?int EnumDevices(HWND hList); //hList是下拉列表框的句柄,本函数用于枚举当前系统安装的所有视频捕捉设备
?HRESULT Init(int iDeviceID,HWND hWnd);//iDeviceID是视频捕捉设备序号,hWnd是视频捕捉窗口的句柄
?void GrabOneFrame(BOOL bGrab);//调用GrabOneFrame(true)就可以捕获当前的静态图像并保存到硬盘上
具体示例:用MFC AppWizard(exe)创建一个对话框应用程序,取名为ds,给对话框添加一个下拉列表框(IDC_COMBO1)、两个按钮(IDC_PHOTO、IDC_HAVEALOOK)和一个Picture控件(ID:IDC_STATIC_SCREEN,Type: Rectangle,Color:Gray)。
1、使用向导添加成员变量
CStatic m_staticScreen; // IDC_STATIC_SCREEN CComboBox m_ListCtrl; // IDC_COMBO1 CCaptureVideo m_cap;
2、为BOOL CDsDlg::OnInitDialog()添加如下代码:
// TODO: Add extra initialization here m_cap.EnumDevices (m_ListCtrl); m_ListCtrl.SetCurSel (0);
3、为确定按钮添加代码如下:
void CDsDlg::OnOK()
{
//只需要四行代码就可以进行视频捕捉了
UpdateData();
HWND hWnd = m_staticScreen.GetSafeHwnd() ;
HRESULT hr = m_cap.Init(m_ListCtrl.GetCurSel (),hWnd);
GetDlgItem(IDOK)->EnableWindow(FALSE); }
4、如果希望捕捉静态图像,为照相按钮添加如下代码:
void CDsDlg::OnPhoto()
{
m_cap.GrabOneFrame(true);
}