《现代计算机接口技术实验.pdf》由会员分享,可在线阅读,更多相关《现代计算机接口技术实验.pdf(34页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、计算机接口技术实验指导书1 现代计算机接口技术及 MFC程序实现武汉工业学院计算机与信息工程系计算机接口技术实验指导书2 目录实验 1 定时与中断接口程序设计1 实验 2 操作 PC机上的 8250 实现串行通信 5 实验 3 基于 DLL与 HOOK技术的键盘消息拦截与读音10 实验 4 MFC串行通信程序设计 16 实验 5 DirectShow 接口实现视频显示与帧捕获20 实验 6 基于 Socket接口的网络通信MFC程序设计 27 计算机接口技术实验指导书3 实验 1 定时与中断接口程序设计一实验目的1了解定时器/计数器 8253、并行 I/O 接口 8255A 在 PC机中的电路
2、连接方法;2学习使用TURBO C+对 8253、8255 进行编程操作;3熟悉拦截PC机中断向量的TC+编程方法。二实验内容18253、8255 在 PC/XT机中的电路连接介绍PC机启动后,系统设置的初始状态为:芯片有关工作方式初值运行情况8253 通道 0#:方式 3(方波发生器)计数初值:0000HOUT输出 55ms 方波至 8259 的 IRQ0 通道 2#:?(1KHz)计数初值:?(1190)?(1KHz方波)8255 PB0、PB1:方式 0(简单输出)控制蜂鸣器发声。0:不发声,1:发声8259 IRQ0:允许中断中断类型号:8 CPU响应 8 号中断表中,8253 的通道
3、 2#的工作方式和计数初值未知,要求自己设置。2程序要求利用 TURBO C+开发环境设计程序,实现如下功能:(1)程序启动时,要求输入定时时间,以秒为单位。D7 D0IOR IOW A0 A1 IO/M A9 A2D7D0 OUT0RD GATE0 WR CLK0 A0 OUT1 A1 GATE1 CLK1 OUT2 CS GATE2 CLK0,1,2 地址译码40H43H 至 8259 IRQ0,中断类型=8+5V 至 8237 的 DRAM 刷新请求+5V 8088 8253&放大PB0 CS PB1 地址译码60H63H 8255 1.19MHz 计算机接口技术实验指导书4(2)按秒计
4、时,每秒到达时,在屏幕上显示当前为第几秒,同时蜂鸣器发出短促叫声;(3)当定时时间到,则显示“Time Up!”,结束程序。三实验环境硬件环境:PC机一台;软件环境:操作系统不限,TURBO C+3.0。四实验步骤1建立源文件启动 TURBO C+3.0,建立 Timer.CPP。保存到(学号)Timer.CPP;2设置 TC工作目录选菜单 Options/Directories,第 1、2 栏保持不变,第3、4 栏填写您的文件存放目录,OK。如此,TC生成的可执行文件等将会存放到此工作目录下。样例如下:3输入源程序以下源程序仅供参考。#include /支持标准输入输出,如printf()。
5、#include /支持接口访问、中断向量操作函数#include /支持 exit()函数#ifdef _cplusplus/定义 C+使用的中断函数标识符。若是.C程序,则不需要#define _CPPARGS.#else#define _CPPARGS#endif int nTick=0,sec=0,flag=0;unsigned char sys_PB,my_PB;计算机接口技术实验指导书5 void interrupt far(*sys_int_08)(_CPPARGS);/若是.C,则函数参数不写void interrupt far my_int_08(_CPPARGS)/若是.C
6、,则函数参数不写/8 号中断,每55ms 中断一次,由8253 的 0 号定时器定时,并向8259 IRQ0申请中断+nTick;if(tinck=1)outportb(0 x61,my_PB);/开始鸣叫else if(tinck=3)outportb(0 x61,sys_PB);/停止鸣叫else if(nTick18)/1second/55ms 近似等于18 flag=1;nTick=0;sec+;sys_int_08();/调用系统的中断向量/=void main()unsigned int Time_up;printf(Please input Up Time(5-30):);sca
7、nf(%d,&Time_up);printf(n);if(Time_up30)printf(Input Error!);exit(1);/结束程序 outportb(0 x63,0 x82);/设置 8255,PB为输入方式sys_PB=inportb(0 x61);/读取 PB口,内容my_PB=sys_PB|0 x03;/将 PB口低 2 位(PB0,PB1)置 1 outportb(0 x63,0 x80);/设置 8255,PB为输出方式/8253 通道 2,产生 1KHz方波,送到扬声器,使扬声器发声outportb(0 x43,0 xb6);/CW=10110110 B,通道 2,
8、先低字节,再高字节,方式3,二进制outportb(0 x42,0 xa6);/low byte,outportb(0 x42,0 x04);/high byte,0 x04a6=1190,f=1.19MHz,out=f/1190=1000Hz sys_int_08=getvect(0 x08);/保存系统的中断向量setvect(0 x08,my_int_08);/设置系统向量while(1)if(flag=1)flag=0;printf(%d,sec);if(sec=Time_up)break;printf(Timer Up!nn);计算机接口技术实验指导书6 outportb(0 x61
9、,sys_PB);/恢复系统的PB口状态setvect(0 x08,sys_int_08);/恢复系统的中断向量 4运行程序,再完成如下内容(1)8253 的通道 0 在程序中起什么作用?为什么在程序中没有对其进行初始化及赋初值?(2)修改 8253 通道 0#的初值,使计时精度严格为1 秒。提示:可采用动态初值,即一秒内的每次中断采用不同的初值,使每次中断得到的时间间隔之和为1000ms。55ms 的定时 65535 1/1.19MHz(3)my_int_08()函数什么时候被调用?(4)将 main()函数的最后一句注释掉,再执行,会有什么结果?假定是在纯DOS环境下执行这个程序。(5)本
10、程序为什么采用DOS环境编写程序,而不采用Windows 环境?六实验报告实验报告是科学实验中的重要技术文档,应如实记录实验中发生的现象、处理措施和结果。实验报告的组成一般为:实验项目名称(要求严格与本指导书一致)、实验日期、场地、采用的软硬件环境,实验者;对于为什么采用此环境,必要时可作出说明。例如,本实验为什么要采用TC,而不采用 VC?实验目的:具体写要做成什么,期望得出什么结果。不要照抄本指导书。实验过程:具体写操作的过程,对于源程序,不一定全部写出,但应画出模块图、流程图。核心代码可写出。特别要写出实验中碰到的问题及分析、解决办法。实验结果及分析:如实写出结果,对结果进行分析,可进一
11、步提出改进、提高的办法。计算机接口技术实验指导书7 实验 2 操作 PC机上的 8250 实现串行通信一实验目的1了解 8250 在 PC机中的电路连接方法;2学习使用TURBO C+对 8250 进行编程操作;3利用 8259 中断实现 RS232串行通信。二实验指导18250 内部基本结构简介为便于理解,以下仅给出8250 内部的简化逻辑结构和主要管脚,详情请参阅有关技术资料。28250 内部寄存器功能简介线路控制寄存器LCRDLAB SB SP EPS PEN STB WLS1 WLS0 数据位数00:5;01:6 10:7;11:8 停止位数0:1 1:1.5 或 2 注:各寄存器旁标
12、注的十六进制数是该寄存器在PC中的 I/O 地址。3FBH 3FDH 3F9H 3FAH(只读)3FEH 3FCH 3F9H 3F8H 3F8H(读)3F8H(写)线路控制寄存器LCR线路状态寄存器LSR中断允许寄存器IER中断标识寄存器IIR数据缓冲控制逻辑接收缓冲器RBR发送保持器THR除数寄存器(H)除数寄存器(L)波特率发生器Modem 控制寄存器MCRModem 状态寄存器MSRModem 控制逻辑DTR 数据终端就绪RTS 请求发送CTS 清除发送DSR 数据设备就绪RI 振铃RLSD 接收信号检测RXD 串行数据输入TXD 串行数据输出RESET CS A0 A1 A2 RD W
13、R INT CLK D7 D0 0:读写 RBR、THR 1:读写除数寄存器附加奇偶校验?0:不附加1:附加01:奇校验11:偶校验0:无校验计算机接口技术实验指导书8 线路状态寄存器LSR0 TSRE THRE BI FE PE OE DR 中断允许寄存器IER中断标识寄存器IIR(只读)除数寄存器用于设置波特率。波特率=时钟频率(16 除数寄存器的值)。若已知波特率,则:除数寄存器的值=时钟频率(16 波特率)。Modem 控制寄存器MCRModem 状态寄存器MSR读出值为8250 芯片的Modem 部分 4 个输入引脚的状态。“”表示比较前次的读出值有改变。38250 在 PC/XT机
14、中的电路连接介绍主板上有两片8250,分别对应串口1 和串口 2。8250(对应 COM1)的端口地址为3F8H3FFH,其中断信号传到8259 的 IRQ4。IRQ4的中断类型码为0CH。8250(对应 COM2)的端口地址为2F8H2FFH,其中断信号传到8259 的 IRQ3。IRQ3的中断类型码为0BH。本实验仅操作串口1 对应的 8250(对应 COM1),实现串行通信。0 0 0 0 I0E I3E I1E I2E 0 0 0 0 0 ID2 ID1E IP 0 0 0 LOOP OUT2 OUT1 RTS DTR RLSD RI DSR CTS RLSD TERI DSR CTS
15、 有否未决中断?0:无1:有1:允许接收出错中断接收重叠错?0:无错;1:有错接收格式错?0:无错1:有错发送保持空?0:不空1:空发送移位器空?0:不空,正在发1:空,发完接收奇偶错?0:无错1:有错接收缓冲器满?0:未满1:满1:允许 Modem 状态改变中断1:允许发送保持器空中断1:允许接收缓冲器满中断00:接收出错中断01:接收缓冲器满中断10:发送保持器空中断11:Modem 状态改变中断是何中断?1:环路检测(自发自收)1:请求发送1:数据终端就绪计算机接口技术实验指导书9 4程序要求利用 TURBO C+开发环境设计程序,实现如下功能:(1)设置 8250:波特率=1200,奇
16、校验,8 位数据,1 停止位;按 LOOP方式工作,自发自收;允许接收中断。(2)拦截 8259 IRQ4 中断,在此中断中接收数据,在程序中显示数据。(3)将程序改为两机之间通信,一机发送,另一机接收。三实验环境硬件环境:PC机一台;串行通信终接头一个(用于一个串口自发自收);串行通信电缆一根(用于两机之间通信)。软件环境:操作系统不限,TURBO C+3.0。四实验步骤1输入源程序(LOOP方式),自收自发实验。以下源程序仅供参考。#include#include void init_RS232();/初始化 COM1,包括 8250和 8259void interrupt far my_
17、interupt();/本程序的中断响应函数void interrupt far(*old_int_rs232)();/指向系统原来的中断响应函数unsigned int old_IMR;/保存 8259中断屏蔽寄存器IMR的原值,以便程序退出时复原unsigned char input_buf1024;/定义接收缓冲区unsigned char output_buf1024=0 xa1,0 xb2,0 xc3,0 xd4,0 xe5,0 xf6;/定义发送缓冲区及要发送的数据unsigned int input_buf_point;/指向当前存放接收数据的缓冲区位置unsigned int
18、output_buf_point;/指向当前要发送字节的缓冲区位置int send_OK;/收发完成标志。0=收发未完成,1=收发完成D7 D0 IOR IOW A0 A1 A2 IO/M INTR A9 A3 D7 D0 RXD RD TXD WR RTS A0 CTS A1 DSR A2 RLSD DTR CS RI INT CLK 地址译码3F8H3FFH DB9插座8088 8250 1.8432MHz INT IRQ4 8259 计算机接口技术实验指导书10 int output_bytes=6;/应发送的字节数,设要发送 6 个字节void main()int i;clrscr()
19、;/清屏init_RS232();/设置 8250、8259的初始化值send_OK=0;/先置为 0,表示收发未完成。for(;)printf(Press any key to send,q to exitnn);if(getch()=q)break;printf(Sending Data:);/先把待发送的数据显示出来for(i=0;i output_bytes;i+)printf(%02x,output_bufi);printf(n);output_buf_point=0;/目前已发送了0个数据input_buf_point=0;/目前收到 0个数据outportb(0 x3f8,out
20、put_bufoutput_buf_point+);/发送第一个字符,后续字符将在前一个/字符引起的中断响应中发送;while(!send_OK);/等待收发完成(收发工作在中断函数中进行)printf(receving Data:);/收发完成,把收到的数据显示出来for(i=0;i output_bytes;i+)printf(%02x,input_bufi);printf(nn);outportb(0 x21,old_IMR);/将 8259的中断屏蔽寄存器IMR复原setvect(0 x0c,old_int_rs232);/将 COM1的中断向量复原 void init_RS232()
21、/8250、8259初始设置函数 int i;disable();/由于要修改系统的中断方式,故先关中断,保证下面的操作不影响系统工作outportb(0 x3fb,0 x80);/1000 0000,写 8250 控制字,允许改动波特率outportb(0 x3f8,0 x60);/设置波特率=1200bps.8250 的时钟=1.8432MHz,除数=0060H=92,outportb(0 x3f9,0 x00);/故波特率=1.8432/(16*92)=0.001252Mbps=1252bps.outportb(0 x3fb,0 x2b);/0010 1011,再写控制字,锁定波特率,奇
22、校验,8 位数据,1 停止位outportb(0 x3fc,0 x13);/0001 0011,写 Modem控制字,LOOP=1,RTS=1,DTS=1outportb(0 x3f9,0 x05);/设置中断允许寄存器IER,允许接收中断old_int_rs232=getvect(0 x0c);/保存系统原中断向量。COM1的中断类型码=12setvect(0 x0c,my_interupt);/将 COM1的中断向量改为指向本程序中的中断函数old_IMR=inportb(0 x21);/读 8259中断屏蔽寄存器IMR,其 I/O 地址为 21H i=old_IMR&0 xef;/允许
23、IRQ4中断,其他中断源维持系统的原设置不变outportb(0 x21,i);outportb(0 x20,0 x20);/置位 OCW2中的 EOI,使中断服务寄存器自动清零,避免中断重复响应计算机接口技术实验指导书11 enable();void interrupt my_interupt()/COM1中断服务程序 unsigned int com_state;unsigned int data;com_state=inportb(0 x3fd);/读线路状态寄存器LSRcom_state=com_state&0 x0007;if(com_state=0 x0001)/接收器满data=
24、inportb(0 x3f8);/读取接收缓冲器input_bufinput_buf_point+=data;/将读得的数据存放到接收缓冲区if(output_buf_point=A&wParam0)/实际收到了BytesRead个字符RxdBuffBytesRead=0;/在收到的字符串后加结尾标志m_Receive+=_T(RxdBuff);/将收到的字符串连接到接收编辑框变量计算机接口技术实验指导书22 UpdateData(FALSE);/更新接收编辑框的显示 6 运行程序,实验(1*)COM1发送,COM1接收。先将计算机的COM1口(9 针插座)的2 脚(发送脚)和3 脚(接收脚)
25、用导线接通,再运行程序。(2)本机的 COM1和 COM2互相收发。先将本程序编译、连接生成Release版的 Scom.exe 文件,改名为 Scom1.exe;再将 CreateFile()、BuildCommDCB()函数中的 COM1改为 COM2,编译、连接生成Release版的Scom.exe 文件,改名为Scom2.exe;将 COM1口和 COM2口用串行通信电缆接通;使Scom1.exe和 Scom2.exe同时运行。(3)一机发送,另一机接收。先将两台计算机的COM1 口用串行通信电缆接通,再运行程序。(4)修改波特率和数据位数、读超时时间,再作实验,记录实验结果,分析原因
26、。思考题:(1)按本程序设置的波特率、定时时间以及每次试图接收的字节数,完成1000各字符的接收至少需要多少时间?改变波特率能减少这一时间吗?(2)按照500ms的定时时间间隔,在本程序设置的波特率、数据位数不变的情况下,试图接收的字符数最多不能超过多少?超过了会出现什么问题?(3)修改程序,利用线程进行串口数据侦听与接收。计算机接口技术实验指导书23 实验 5 DirectShow 接口实现视频显示与帧捕获一实验目的1了解运用DirectShow SDK开发视频显示与帧捕获应用程序的方法;2了解 COM 接口的工作机制与使用二实验指导1DirectShow SDK概述DirectShow 属
27、于DirectX 家族中的组件之一(DirectX 还包括Direct3D、DirectInput、DirectDraw、DirectSound 等组件)。在使用DirectShow 前,必须安装DirectX SDK开发包。这里推荐安装的版本是DirectX8.0 SDK,可以从微软的网站上下载得到。安装前,你的计算机上应已安装了VC+6.0。安装后,将在C 盘的根目录下生成一个mssdk 目录,该目录下有lib 子目录(含DirectX的函数库)、include 子目录(含头文件)、samples 子目录(各种源程序例子)、doc 子目录(使用说明文挡)等。同时,还会自动在VC+系统中设置
28、好DirectX SDK的 Include 路径和 Lib 路径,你可以启动VC查看。方法是选择菜单“Tools/Options”,在弹出的Options 对话框中选择 Directories 选项卡,看看Include files 和 Library files 中是否包含有DirectX SDK的 Include路径和 Lib 路径。DirectX SDK是用 COM 的方式发布的,下面对COM 的基本原理作一简介。2COM 简介COM 即组件对象模型,是一种跨应用、跨语言的机器代码共享方法。虽然DLL也在机器代码级共享,但这种共享只能由程序来负责实现,而不是由DLL本身。COM 定义的机
29、器代码标准独立于任何编程语言,任何编程语言都能按照标准的要求,轻松地利用COM 组件。COM 以类(coclass)的形式存在,COM 类中也有成员函数(或称为方法),但这些成员函数只能通过COM 接口 来调用。COM 类提供了若干个面向用户的接口,其中必有一个名为IUnknown 的接口,其他COM 接口都派生于IUnknown。如图。在应用程序中使用COM 接口首先要创建COM 对象,并从这个对象获得接口实例。创建COM 对象的 API 函数原型为:HRESULT CoCreateInstance(REFCLSID rclsid,/coclass 的 CLSID LPUNKNOWN pUn
30、kOuter,/COM 对象的聚合DWORD dwClsContext,/指定 COM 服务器的种类REFIID riid,/请求接口的IID LPVOID*ppv/接口指针的地址);COM 类IUnknown 接口 1 接口 n 计算机接口技术实验指导书24 若创建成功,则ppv 为接口指针,可通过ppv 来引用 COM 类中的成员函数。3程序要求利用 VC+开发环境设计程序,实现如下功能:(1)编写 MFC 单文档应用程序,运用DirectShow 显示视频;(2)实现抓帧功能。三实验环境硬件环境:PC机一台;软件环境:WindowsXP,VC+6.0,DirectX8.0 SDK(已安装
31、)。四实验步骤1建立 MFC AppWizardexe工程。以下假设工程名为Mpg。在第 1 步选Single document(单文档),第 25 步选默认设置,第6 步的 Base Class栏选 CformView,完成工程的设置。上述操作中,未提及的选项一律取默认值。于是,MFC 为我们建立了如右图所示的文件。2创建 IMediaDet 接口实例为了实现用DirectShow 抓帧,要使用DirectShow 的 IMediaDet 接口。因此工程中需要包含dshow.h、qedit.h、atlbase.h 文件及其库文件。请按如下方式操作:(1)在 MpgView.h 文件的 cla
32、ss CGrabView:public CformView 前添加(粗体字为自己添加,以下同):#include dshow.h#include qedit.h#include atlbase.hclass CGrabView:public CFormView (2)选 Project/Setings 菜单,在弹出的 Project Setings 对话框中选Link卡,在 Object/library modules 栏填写Strmiids.lib,点击 OK 按钮。(3)定义在程序中要用到的DirectShow COM 接口实例MediaDet。先在 MpgView.cpp 文件中定义Me
33、diaDet 接口实例。然后,在CMpgView 类的构造函数CMpgView:CMpgView()中对此接口进行初始化和创建。计算机接口技术实验指导书25 IMediaDet*pDet=NULL;/定义 IMediaDet接口实例,并赋以空指针值CMpgView:CMpgView():CFormView(CMpgView:IDD)/TODO:add construction code here CoInitialize(NULL);/初始化 COM接口HRESULT hr;hr=CoCreateInstance(CLSID_MediaDet,NULL,CLSCTX_INPROC_SERVER
34、,IID_IMediaDet,(void*)&pDet);if(FAILED(hr)/创建失败MessageBox(创建 IMediaDet接口实例失败!,错误,MB_ICONSTOP|MB_OK);3从视频文件中得到视频流信息本步骤要作的工作是:将待抓帧的影片文件与接口实例关联起来,使得以后调用接口函数操作,就是针对与之关联的影片文件进行的。从之关联的影片文件中的视频流中提取抓帧所需要的信息,如帧图像的高宽、帧速率、影片流的持续时间、帧间隔时间等。上述工作相对独立,可以设计一个函数来完成。将此函数命名为LoadMovie(),并且还需要定义存储上述参数的变量。为此,(1)在 MpgView.
35、h 文件中添加如下定义:class CMpgView:public CFormView /Attributes public:CMpgDoc*GetDocument();struct char MpegFile200;/影片文件名double Duration;/影片播完需要的时间double FrameRate;/帧速率,即每秒播放多少帧long TotalFrames;/影片中包含的总帧数MpgInfo;BITMAPINFOHEADER BmpInfo;/帧图像为 BMP格式,本处定义其信息头。char*DibBit;/存放一帧图像的像素数据,每一像素需要3 个字节存放其G、B、R 值lo
36、ng CurFrame;/当前正在处理第几帧BOOL LoadMovie();/定义从视频文件中得到视频流信息的函数(2)在 MpgView.cpp 文件的 CMpgView 类构造函数中对上述变量赋初值:CMpgView:CMpgView():CFormView(CMpgView:IDD)计算机接口技术实验指导书26/TODO:add construction code here DibBit=(char*)new char 40+921600;strcpy(MpgInfo.MpegFile,);BmpInfo.biSize=40;/DWORD BmpInfo.biWidth=640;/LO
37、NG BmpInfo.biHeight=480;/LONG BmpInfo.biPlanes=1;/WORD BmpInfo.biBitCount=24;/WORD BmpInfo.biCompression=0;/DWORD BmpInfo.biSizeImage=0;/DWORD BmpInfo.biXPelsPerMeter=2000;/LONG BmpInfo.biYPelsPerMeter=2000;/LONG BmpInfo.biClrUsed=0;/DWORD BmpInfo.biClrImportant=0;/DWORD CoInitialize(NULL);/初始化 COM接
38、口(3)在 MpgView.cpp 文件的 CMpgView 类的析构函数中删除为DibBit 申请的内存CMpgView:CMpgView()delete DibBit;(4)在 MpgView.cpp 文件后写出LoadMovie()函数的实体BOOL CMpgView:LoadMovie()HRESULT hr;CComBSTR FileName(MpgInfo.MpegFile);/将影片文件名转换成BSTR型字符串hr=pDet-put_Filename(FileName);/设置与 IMediaDet接口关联的影片文件if(FAILED(hr)return(FALSE);long
39、Streams;hr=pDet-get_OutputStreams(&Streams);/从影片中检索视频流和音频流if(FAILED(hr)return(FALSE);hr=pDet-get_StreamLength(&MpgInfo.Duration);/得到影片流的持续时间(秒)if(FAILED(hr)return(FALSE);/因帧的信息保存在视频流中,故先取出视频流,再得到帧信息BOOL bFound=FALSE;for(int i=0;iput_CurrentStream(i);if(SUCCEEDED(hr)hr=pDet-get_StreamType(&major_type
40、);/得到媒体类型if(FAILED(hr)break;if(major_type=MEDIATYPE_Video)/若媒体是视频hr=pDet-get_FrameRate(&MpgInfo.FrameRate);/得到帧速率(帧/秒)if(FAILED(hr)break;MpgInfo.FrameRate=1.0/MpgInfo.FrameRate;/计算帧间隔时间计算机接口技术实验指导书MpgInfo.TotalFrames=(int)(MpgInfo.Duration/MpgInfo.FrameRate+1);/计算总帧数bFound=TRUE;break;if(!bFound)retu
41、rn(FALSE);/得到 VIDEOINFOHEADER 结构指针,该结构包含视频的信息,如 BITMAPINFORHEADER 结构AM_MEDIA_TYPE mt;hr=pDet-get_StreamMediaType(&mt);if(FAILED(hr)return(FALSE);if(mt.formattype=FORMAT_VideoInfo)&(mt.cbFormat=sizeof(VIDEOINFOHEADER)VIDEOINFOHEADER*pVih=(VIDEOINFOHEADER*)(mt.pbFormat);BmpInfo.biWidth=pVih-bmiHeader.
42、biWidth;BmpInfo.biHeight=pVih-bmiHeader.biHeight;else return(FALSE);/释放 AM_MEDIA_TYPE 结构if(mt.cbFormat!=0)CoTaskMemFree(PVOID)mt.pbFormat);mt.cbFormat=0;mt.pbFormat=NULL;if(mt.pUnk!=NULL)mt.pUnk-Release();mt.pUnk=NULL;return(TRUE);24 抓帧的实现(1)建立“文件/打开”项的点击响应函数,目的是打开一个影片文件,再调用 LoadMovie()函数获得此影片文件的信息,
43、为抓帧作好准备。选 View/Class Wizard,弹出如下对话框;在 Class name栏选择 CmpgView,在 Object IDs 栏选择 ID_FILE_OPEN,在 Messages栏选择 COMMAND,点击 Add Function 按钮,再点击OK 计算机接口技术实验指导书28 按钮,于是,MFC自动在 MpgView.cpp 文件后生成响应函数OnFileOpen()。在此函数中添加如下代码:void CMpgView:OnFileOpen()/TODO:Add your command handler code here char*pcsun=视频文件(*.mpg
44、)|*.mpg|;CFileDialog fd(TRUE,NULL,0,OFN_OVERWRITEPROMPT,pcsun,NULL);if(fd.DoModal()=IDCANCEL)return;strcpy(MpgInfo.MpegFile,OpenDialog.GetPathName();GetDocument()-SetTitle(MpgInfo.MpegFile);GetDocument()-UpdateAllViews(NULL);/触发所有视图类的Update()函数BOOL OK=LoadMovie();if(!OK)MessageBox(无法抓取帧!请检查文件格式是否正确。
45、,错误,MB_ICONSTOP|MB_OK);return;CurFrame=0;/设当前帧为第0 帧(2)抓帧。MediaDet 提供了抓取帧、保存帧的接口函数,其原型如下:HRESULT GetBitmapBits(double StreamTime,/Time at which to retrieve the poster frame.long*pBufferSize,/Pointer to a variable that receives the required buffer size.char*pBuffer,/Pointer to a buffer that receives t
46、he poster frame.long Width,/Width of the poster frame image,in pixels.long Height/Height of the poster frame image,in pixels.);HRESULT WriteBitmapBits(double StreamTime,/Time at which to retrieve the poster frame long Width,/Width of the poster frame image,in pixels.long Height,/Height of the poster
47、 frame image,in pixels.BSTR Filename/Path of the file in which to save the poster frame.);现计划把影片中的所有帧都抓出来,每抓一帧,立即显示出来。操作如下:在 MpgView.cpp 文件的 CMpgView:OnFileOpen()函数中建立定时器,每隔120ms响应一次:void CMpgView:OnFileOpen()CurFrame=0;/设当前帧为第0 帧SetTimer(1,120,NULL);/定时抓帧建立定时器消息响应函数,实现定时抓帧和显示计算机接口技术实验指导书29 void CMp
48、gView:OnTimer(UINT nIDEvent)/TODO:Add your message handler code here and/or call default long s=0;CClientDC dc(this);pet-GetBitmapBits(CurFrame*0.12,&s,DibBit,BmpInfo.biWidth,BmpInfo.biHeight);dc.SetStretchBltMode(COLORONCOLOR);:StretchDIBits(dc.GetSafeHdc(),0,0,320,240,0,0,BmpInfo.biWidth,BmpInfo.b
49、iHeight,(LPBYTE)&DibBit40,(LPBITMAPINFO)&BmpInfo,DIB_RGB_COLORS,SRCCOPY);CurFrame+;if(CurFrame=MpgInfo.TotalFrames)KillTimer(1);CFormView:OnTimer(nIDEvent);运行程序,打开一个电影文件,可以看到播放效果。注意,常见的播放器并不是这样实现的。这里的意义在于我们捕捉到了帧,可以进一步逐帧分析画面中感兴趣的目标,尤其是运动的目标。计算机接口技术实验指导书30 实验 6 基于 Socket接口的网络通信MFC程序设计一实验目的1了解在VC+MFC环境
50、下使用WinSock(套接字)实现网络通信的方法;2了解 UDP协议;3了解 VC+线程工作机制及自定义消息的使用方法。二实验指导本实验要求在局域网上实现两台计算机相互通信。甲机发送数据,乙机收到后予以显示。局域网中不设置专门的服务器,因此,应采用UDP 协议,每台计算机既是服务器,也是客户机。本课题采用线程工作。线程是Windows 应用程序的基本执行单位。一个进程由若干个线程组成,各线程并行工作。一个进程中,必须有一个(且仅有一个)主线程,其余为工作线程。为使各线程相互协作,完成应用程序既定的目标,线程之间的同步与通信十分重要。本课题使用VC+MFC编程,主线程发送数据,再专门创建一个工作