代码
using
System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
// namespace AviCap
// {
public class AviCap
{
#region 外部方法
[DllImport( " avicap32.dll " )]
public static extern IntPtr capCreateCaptureWindowA( byte [] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);
[DllImport( " avicap32.dll " )]
public static extern bool capGetDriverDescriptionA( short wDriver, byte [] lpszName, int cbName, byte [] lpszVer, int cbVer);
[DllImport( " User32.dll " )]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, bool wParam, int lParam);
[DllImport( " User32.dll " )]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, int lParam);
public delegate void FrameEventHandler(IntPtr lwnd, IntPtr lpVHdr);
[DllImport( " User32.dll " )]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, FrameEventHandler lParam);
[DllImport( " User32.dll " )]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref BITMAPINFO lParam);
///
/// 该函数改变一个子窗口,弹出式窗口式顶层窗口的尺寸,位置和Z序。子窗口,弹出式窗口,及顶层窗口根据它们在屏幕上出现的顺序排序、顶层窗口设置的级别最高,并且被设置为Z序的第一个窗口。
///
[DllImport( " User32.dll " )]
public static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, int wFlags);
[DllImport( " avicap32.dll " )]
public static extern int capGetVideoFormat(IntPtr hWnd, IntPtr psVideoFormat, int wSize);
#endregion
#region 消息常量(向窗口发送消息的指令)
// 消息常量 --------------------------------------------
public const int WM_START = 0x400 ; // 此并非摄像头消息0x400表示的就是1024
public const int WS_CHILD = 0x40000000 ;
public const int WS_VISIBLE = 0x10000000 ;
public const int SWP_NOMOVE = 0x2 ;
public const int SWP_NOZORDER = 0x4 ;
public const int WM_CAP_GET_CAPSTREAMPTR = WM_START + 1 ;
public const int WM_CAP_SET_CALLBACK_ERROR = WM_START + 2 ; // 设置收回错误
public const int WM_CAP_SET_CALLBACK_STATUS = WM_START + 3 ; // 设置收回状态
public const int WM_CAP_SET_CALLBACK_YIELD = WM_START + 4 ; // 设置收回出产
public const int WM_CAP_SET_CALLBACK_FRAME = WM_START + 5 ; // 设置收回结构
public const int WM_CAP_SET_CALLBACK_VIDEOSTREAM = WM_START + 6 ; // 设置收回视频流
public const int WM_CAP_SET_CALLBACK_WAVESTREAM = WM_START + 7 ; // 设置收回视频波流
public const int WM_CAP_GET_USER_DATA = WM_START + 8 ; // 获得使用者数据
public const int WM_CAP_SET_USER_DATA = WM_START + 9 ; // 设置使用者数据
public const int WM_CAP_DRIVER_CONNECT = WM_START + 10 ; // 驱动程序连接
public const int WM_CAP_DRIVER_DISCONNECT = WM_START + 11 ; // 断开启动程序连接
public const int WM_CAP_DRIVER_GET_NAME = WM_START + 12 ; // 获得驱动程序名字
public const int WM_CAP_DRIVER_GET_VERSION = WM_START + 13 ; // 获得驱动程序版本
public const int WM_CAP_DRIVER_GET_CAPS = WM_START + 14 ; // 获得驱动程序帽子
public const int WM_CAP_FILE_SET_CAPTURE_FILE = WM_START + 20 ; // 设置捕获文件
public const int WM_CAP_FILE_GET_CAPTURE_FILE = WM_START + 21 ; // 获得捕获文件
public const int WM_CAP_FILE_ALLOCATE = WM_START + 22 ; // 分派文件
public const int WM_CAP_FILE_SAVEAS = WM_START + 23 ; // 另存文件为
public const int WM_CAP_FILE_SET_INFOCHUNK = WM_START + 24 ; // 设置开始文件
public const int WM_CAP_FILE_SAVEDIB = WM_START + 25 ; // 保存文件
public const int WM_CAP_EDIT_COPY = WM_START + 30 ; // 编辑复制
public const int WM_CAP_SET_AUDIOFORMAT = WM_START + 35 ; // 设置音频格式
public const int WM_CAP_GET_AUDIOFORMAT = WM_START + 36 ; // 捕获音频格式
public const int WM_CAP_DLG_VIDEOFORMAT = WM_START + 41 ; // 1065 打开视频格式设置对话框
public const int WM_CAP_DLG_VIDEOSOURCE = WM_START + 42 ; // 1066 打开属性设置对话框,设置对比度亮度等
public const int WM_CAP_DLG_VIDEODISPLAY = WM_START + 43 ; // 1067 打开视频显示
public const int WM_CAP_GET_VIDEOFORMAT = WM_START + 44 ; // 1068 获得视频格式
public const int WM_CAP_SET_VIDEOFORMAT = WM_START + 45 ; // 1069 设置视频格式
public const int WM_CAP_DLG_VIDEOCOMPRESSION = WM_START + 46 ; // 1070 打开压缩设置对话框
public const int WM_CAP_SET_PREVIEW = WM_START + 50 ; // 设置预览
public const int WM_CAP_SET_OVERLAY = WM_START + 51 ; // 设置覆盖
public const int WM_CAP_SET_PREVIEWRATE = WM_START + 52 ; // 设置预览比例
public const int WM_CAP_SET_SCALE = WM_START + 53 ; // 设置刻度
public const int WM_CAP_GET_STATUS = WM_START + 54 ; // 获得状态
public const int WM_CAP_SET_SCROLL = WM_START + 55 ; // 设置卷
public const int WM_CAP_GRAB_FRAME = WM_START + 60 ; // 逮捕结构
public const int WM_CAP_GRAB_FRAME_NOSTOP = WM_START + 61 ; // 停止逮捕结构
public const int WM_CAP_SEQUENCE = WM_START + 62 ; // 次序
public const int WM_CAP_SEQUENCE_NOFILE = WM_START + 63 ; // 使用WM_CAP_SEUENCE_NOFILE消息(capCaptureSequenceNoFile宏),可以不向磁盘文件写入数据。该消息仅在配合回调函数时有用,它允许你的应用程序直接使用音视频数据。
public const int WM_CAP_SET_SEQUENCE_SETUP = WM_START + 64 ; // 设置安装次序
public const int WM_CAP_GET_SEQUENCE_SETUP = WM_START + 65 ; // 获得安装次序
public const int WM_CAP_SET_MCI_DEVICE = WM_START + 66 ; // 设置媒体控制接口
public const int WM_CAP_GET_MCI_DEVICE = WM_START + 67 ; // 获得媒体控制接口
public const int WM_CAP_STOP = WM_START + 68 ; // 停止
public const int WM_CAP_ABORT = WM_START + 69 ; // 异常中断
public const int WM_CAP_SINGLE_FRAME_OPEN = WM_START + 70 ; // 打开单一的结构
public const int WM_CAP_SINGLE_FRAME_CLOSE = WM_START + 71 ; // 关闭单一的结构
public const int WM_CAP_SINGLE_FRAME = WM_START + 72 ; // 单一的结构
public const int WM_CAP_PAL_OPEN = WM_START + 80 ; // 打开视频
public const int WM_CAP_PAL_SAVE = WM_START + 81 ; // 保存视频
public const int WM_CAP_PAL_PASTE = WM_START + 82 ; // 粘贴视频
public const int WM_CAP_PAL_AUTOCREATE = WM_START + 83 ; // 自动创造
public const int WM_CAP_PAL_MANUALCREATE = WM_START + 84 ; // 手动创造
public const int WM_CAP_SET_CALLBACK_CAPCONTROL = WM_START + 85 ; // 设置收回的错误
// 其它
public const int WM_CAP_SAVEDIB = WM_CAP_START + 25 ;
public const int WM_USER = 0x400 ; // 1024
public const int WM_CAP_START = WM_USER;
public const int WM_CAP_UNICODE_START = WM_USER + 100 ; // 开始
public const int WM_CAP_GRAB_FRame = (WM_CAP_START + 60 ); // 逮捕结构
public const int WM_CAP_GRAB_FRame_NOSTOP = (WM_CAP_START + 61 ); // 停止逮捕结构
public const int WM_CAP_SINGLE_FRame_OPEN = (WM_CAP_START + 70 ); // 打开单一的结构
public const int WM_CAP_SINGLE_FRame_CLOSE = (WM_CAP_START + 71 ); // 关闭单一的结构
public const int WM_CAP_SINGLE_FRame = (WM_CAP_START + 72 ); // 单一的结构
// Following added post VFW 1.1
public const int WM_CAP_END = WM_CAP_SET_CALLBACK_CAPCONTROL;
#endregion
#region 结构体
[StructLayout(LayoutKind.Sequential)]
public struct VIDEOHDR
{
[MarshalAs(UnmanagedType.I4)]
public int lpData;
[MarshalAs(UnmanagedType.I4)]
public int dwBufferLength;
[MarshalAs(UnmanagedType.I4)]
public int dwBytesUsed;
[MarshalAs(UnmanagedType.I4)]
public int dwTimeCaptured;
[MarshalAs(UnmanagedType.I4)]
public int dwUser;
[MarshalAs(UnmanagedType.I4)]
public int dwFlags;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4 )]
public int [] dwReserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFOHEADER
{
[MarshalAs(UnmanagedType.I4)]
public Int32 biSize;
[MarshalAs(UnmanagedType.I4)]
public Int32 biWidth;
[MarshalAs(UnmanagedType.I4)]
public Int32 biHeight;
[MarshalAs(UnmanagedType.I2)]
public short biPlanes;
[MarshalAs(UnmanagedType.I2)]
public short biBitCount;
[MarshalAs(UnmanagedType.I4)]
public Int32 biCompression;
[MarshalAs(UnmanagedType.I4)]
public Int32 biSizeImage;
[MarshalAs(UnmanagedType.I4)]
public Int32 biXPelsPerMeter;
[MarshalAs(UnmanagedType.I4)]
public Int32 biYPelsPerMeter;
[MarshalAs(UnmanagedType.I4)]
public Int32 biClrUsed;
[MarshalAs(UnmanagedType.I4)]
public Int32 biClrImportant;
}
#region BITMAPINFO结构
// BITMAPINFO结构具有如下形式:
// typedef struct tagBITMAPINFO
// {
// BITMAPINFOHEADER bmiHeader;
// RGBQUAD bmiColors[1];
// } BITMAPINFO;
// BITMAPINFO结构定义了Windows设备无关位图(DIB)的度量和颜色信息。
// 成员:
// bmiHeader 指定了一个BITMAPINFOHEADER结构,包含了有关设备相关位图的度量和颜色格式的信息。
// bmiColors 指定了一个RGBQUAD或DWORD数据类型的数组,定义了位图中的颜色。
// 注释:
// 设备无关位图由两个部分组成:
// (1) 一个BITMAPINFO结构,描述了位图的度量和颜色信息;
// (2) 一个字节数组,定义了位图的像素。数组中的字节被组合在一起,但是每个扫描行必须用零填补,在一个LONG边界结束。如果高度为正的,位图的起始位置在左下角。如果高度为负,起始位置在左上角。
// (3) BITMAPINFOHEADER结构中的biBitCount成员决定了定义像素的位数以及位图中的最大颜色数。这个成员可以是下列值之一:
// · 位图是单色的,bmiColors成员包含两个入口。位图数组中的每一位代表一个像素。如果该位被清除,则用bmiColors表中的第一种颜色显示该像素。如果该位被置位,则用表中的第二种颜色显示该像素。
// · 位图最多有16种颜色,bmiColors成员中包含了最多可达16个入口。位图中的每个像素用一个4位的值来表示,该值用作颜色表的索引。例如,如果位图中的第一个字节是0x1F,这个字节代表两个像素。第一个像素包含了颜色表中第二种颜色,第二个像素包含了颜色表中第十六种颜色。
// · 位图最多有256种颜色,bmiColors成员包含了多达256个入口。在这种情况下,数组中的每个字节代表一个像素。
// · 位图最多有216种颜色。BITMAPINFOHEADER的biCompression成员必须是BI_BITFIELDS。bmiColors成员包含了3个DWORD型颜色掩码,分别代表了每个像素中的红,绿和蓝色成分。DWORD型掩码中的位必须是连续的,不能与其它掩码重叠。并非像素中的所有位都必须被使用。数组中的每个WORD值代表一个像素。
// · 位图最多具有224种颜色,bmiColors成员为NULL。位图数组中的每个三字节组合分别代表像素中蓝,绿红的深度。
// · 位图中最多具有232种颜色。BITMAPINFOHEADER中的biCompression成员必须是BI_BITFIELDS。bmiColors成员中包含了三个DWORD颜色掩码,分别指定了像素的红,绿和蓝成分。DWORD掩码中的位必须是连续的,并且不能与其它掩码重叠。并非像素中的所有位都必须被使用。数组中的每个DWORD值代表一个像素。
// BITMAPINFOHEADER结构中的biClrUsed成员指定了颜色表中实际使用的索引的数目。如果biClrUsed成员被设为0,位图将使用biBitCount成员中指定的最大颜色数。
// bmiColors表中的颜色应当按照其重要性的顺序出现。另一种情况是,对于使用DIB函数,bmiColors成员可以是一个16位无符号整数的数组,指定了当前实现的逻辑调色板中的索引,而不是确切的RGB值。在这种情况下,使用位图的应用程序必须调用Windows的DIB函数(CreateDIBitmap,CreateDIBPatternBrush和CreateDIBSection),iUsage参数应被设为DIB_PAL_COLORS。
// 如果位图是一个压缩位图(这意味着,这种位图的数组直接跟在一个指针所引用的BITMAPINFO头的后面),在使用DIB_PAL_COLORS模式的时候,biClrUsed成员必须被设为偶数,以便使DIB位图数组从DWORD边界开始。
// 注意:
// 如果位图被保存在文件中,或者要被传送到另一个应用程序,bmiColors成员不能包含调色板索引。除非应用程序独占地使用和控制位图,位图的颜色表中应当包含准确的RGB值。
#endregion
///
/// BITMAPINFO结构定义了Windows设备无关位图(DIB)的度量和颜色信息。
///
[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFO
{
///
/// 指定了一个BITMAPINFOHEADER结构,包含了有关设备相关位图的度量和颜色格式的信息。
///
[MarshalAs(UnmanagedType.Struct, SizeConst = 40 )]
public BITMAPINFOHEADER bmiHeader;
///
/// 指定了一个RGBQUAD或DWORD数据类型的数组,定义了位图中的颜色。
///
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024 )]
public Int32[] bmiColors;
}
#endregion
#region 属性
private IntPtr lwndC; // 保存无符号句柄
private IntPtr mControlPtr; // 保存管理指示器 用于显示视频内容的控件地址指针
private int mWidth;
private int mHeight;
// 委托 祯 回调事件定义
public delegate void RecievedFrameEventHandler( byte [] data);
public event RecievedFrameEventHandler RecievedFrame;
private FrameEventHandler mFrameEventHandler; // Delegate instance for the frame callback - must keep alive! gc should NOT collect it
#endregion
///
/// 构造方法
///
/// 显示视频控件的句柄
/// 视频宽度
/// 视频高度
public AviCap(IntPtr handle, int width, int height)
{
mControlPtr = handle;
mWidth = width;
mHeight = height;
}
#region 静态方法
public static object GetStructure(IntPtr ptr, ValueType structure)
{
return Marshal.PtrToStructure(ptr, structure.GetType());
}
public static object GetStructure( int ptr, ValueType structure)
{
return GetStructure( new IntPtr(ptr), structure);
}
public static void Copy(IntPtr ptr, byte [] data)
{
Marshal.Copy(ptr, data, 0 , data.Length);
}
public static void Copy( int ptr, byte [] data)
{
Copy( new IntPtr(ptr), data);
}
public static int SizeOf( object structure)
{
return Marshal.SizeOf(structure);
}
#endregion
// 开启摄像头方法
public void StartWebCam()
{
byte [] lpszName = new byte [ 100 ]; // 名字
byte [] lpszVer = new byte [ 100 ]; // 版本号
AviCap.capGetDriverDescriptionA( 0 , lpszName, 100 , lpszVer, 100 );
this .lwndC = AviCap.capCreateCaptureWindowA(lpszName, WS_VISIBLE + WS_CHILD, 0 , 0 , mWidth, mHeight, mControlPtr, 0 );
if ( this .DriverConnect( 0 ))
{
this .PreviewRate( 66 );
this .Preview( true );
BITMAPINFO bitmapinfo = new BITMAPINFO();
bitmapinfo.bmiHeader.biSize = AviCap.SizeOf(bitmapinfo.bmiHeader);
// bitmapinfo.bmiHeader.biWidth = 352;
// bitmapinfo.bmiHeader.biHeight = 288;
bitmapinfo.bmiHeader.biWidth = mWidth;
bitmapinfo.bmiHeader.biHeight = mHeight;
bitmapinfo.bmiHeader.biPlanes = 1 ;
bitmapinfo.bmiHeader.biBitCount = 24 ;
// this.SetVideoFormat(ref bitmapinfo, AviCap.SizeOf(bitmapinfo));
// this.mFrameEventHandler = new AviCap.FrameEventHandler(FrameCallBack);
this .SetCallbackOnFrame( this .mFrameEventHandler);
AviCap.SetWindowPos( this .lwndC, 0 , 0 , 0 , mWidth, mHeight, 6 );
}
// byte[] lpszName = new byte[100];
// byte[] lpszVer = new byte[100];
// VideoAPI.capGetDriverDescriptionA(0, lpszName, 100, lpszVer, 100);
// this.lwndC = VideoAPI.capCreateCaptureWindowA(lpszName, VideoAPI.WS_CHILD | VideoAPI.WS_VISIBLE, 0, 0, mWidth, mHeight, mControlPtr, 0);
// if (VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_DRIVER_CONNECT, 0, 0))
// {
// VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_SET_PREVIEWRATE, 100, 0);
// VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_SET_PREVIEW, true, 0);
// }
}
// 关闭摄像头方法
public void CloseWebcam()
{
this .DriverDisconnect();
}
///
/// 拍照
///
/// BMP路由
public void GrabImage( string path)
{
IntPtr hBmp = Marshal.StringToHGlobalAnsi(path);
SendMessage( this .lwndC, WM_CAP_SAVEDIB, 0 , hBmp.ToInt32());
}
public bool DriverConnect( short nCameraID)
{
return SendMessage( this .lwndC, WM_CAP_DRIVER_CONNECT, nCameraID, 0 );
}
///
/// 驱动断开
///
///
///
public bool DriverDisconnect()
{
return SendMessage( this .lwndC, WM_CAP_DRIVER_DISCONNECT, 0 , 0 );
}
///
/// 预览
///
///
///
public bool Preview( bool f)
{
return SendMessage( this .lwndC, WM_CAP_SET_PREVIEW, f, 0 );
}
///
/// 设置预览比例
///
///
///
public bool PreviewRate( short wMS)
{
return SendMessage( this .lwndC, WM_CAP_SET_PREVIEWRATE, wMS, 0 );
}
///
/// 设置回调事件
///
private bool SetCallbackOnFrame(FrameEventHandler lpProc)
{
return SendMessage( this .lwndC, WM_CAP_SET_CALLBACK_FRAME, 0 , lpProc);
}
///
/// 设置视频格式
///
///
///
///
///
public bool SetVideoFormat( ref BITMAPINFO BmpFormat, int CapFormatSize)
{
return SendMessage( this .lwndC, WM_CAP_SET_VIDEOFORMAT, CapFormatSize, ref BmpFormat);
}
private void FrameCallBack(IntPtr lwnd, IntPtr lpVHdr)
{
VIDEOHDR videoHeader = new VIDEOHDR();
byte [] VideoData;
videoHeader = (VIDEOHDR)GetStructure(lpVHdr, videoHeader);
VideoData = new byte [videoHeader.dwBytesUsed];
Copy(videoHeader.lpData, VideoData);
if ( this .RecievedFrame != null )
this .RecievedFrame(VideoData);
}
}
// }
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
// namespace AviCap
// {
public class AviCap
{
#region 外部方法
[DllImport( " avicap32.dll " )]
public static extern IntPtr capCreateCaptureWindowA( byte [] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);
[DllImport( " avicap32.dll " )]
public static extern bool capGetDriverDescriptionA( short wDriver, byte [] lpszName, int cbName, byte [] lpszVer, int cbVer);
[DllImport( " User32.dll " )]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, bool wParam, int lParam);
[DllImport( " User32.dll " )]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, int lParam);
public delegate void FrameEventHandler(IntPtr lwnd, IntPtr lpVHdr);
[DllImport( " User32.dll " )]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, FrameEventHandler lParam);
[DllImport( " User32.dll " )]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref BITMAPINFO lParam);
///
/// 该函数改变一个子窗口,弹出式窗口式顶层窗口的尺寸,位置和Z序。子窗口,弹出式窗口,及顶层窗口根据它们在屏幕上出现的顺序排序、顶层窗口设置的级别最高,并且被设置为Z序的第一个窗口。
///
[DllImport( " User32.dll " )]
public static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, int wFlags);
[DllImport( " avicap32.dll " )]
public static extern int capGetVideoFormat(IntPtr hWnd, IntPtr psVideoFormat, int wSize);
#endregion
#region 消息常量(向窗口发送消息的指令)
// 消息常量 --------------------------------------------
public const int WM_START = 0x400 ; // 此并非摄像头消息0x400表示的就是1024
public const int WS_CHILD = 0x40000000 ;
public const int WS_VISIBLE = 0x10000000 ;
public const int SWP_NOMOVE = 0x2 ;
public const int SWP_NOZORDER = 0x4 ;
public const int WM_CAP_GET_CAPSTREAMPTR = WM_START + 1 ;
public const int WM_CAP_SET_CALLBACK_ERROR = WM_START + 2 ; // 设置收回错误
public const int WM_CAP_SET_CALLBACK_STATUS = WM_START + 3 ; // 设置收回状态
public const int WM_CAP_SET_CALLBACK_YIELD = WM_START + 4 ; // 设置收回出产
public const int WM_CAP_SET_CALLBACK_FRAME = WM_START + 5 ; // 设置收回结构
public const int WM_CAP_SET_CALLBACK_VIDEOSTREAM = WM_START + 6 ; // 设置收回视频流
public const int WM_CAP_SET_CALLBACK_WAVESTREAM = WM_START + 7 ; // 设置收回视频波流
public const int WM_CAP_GET_USER_DATA = WM_START + 8 ; // 获得使用者数据
public const int WM_CAP_SET_USER_DATA = WM_START + 9 ; // 设置使用者数据
public const int WM_CAP_DRIVER_CONNECT = WM_START + 10 ; // 驱动程序连接
public const int WM_CAP_DRIVER_DISCONNECT = WM_START + 11 ; // 断开启动程序连接
public const int WM_CAP_DRIVER_GET_NAME = WM_START + 12 ; // 获得驱动程序名字
public const int WM_CAP_DRIVER_GET_VERSION = WM_START + 13 ; // 获得驱动程序版本
public const int WM_CAP_DRIVER_GET_CAPS = WM_START + 14 ; // 获得驱动程序帽子
public const int WM_CAP_FILE_SET_CAPTURE_FILE = WM_START + 20 ; // 设置捕获文件
public const int WM_CAP_FILE_GET_CAPTURE_FILE = WM_START + 21 ; // 获得捕获文件
public const int WM_CAP_FILE_ALLOCATE = WM_START + 22 ; // 分派文件
public const int WM_CAP_FILE_SAVEAS = WM_START + 23 ; // 另存文件为
public const int WM_CAP_FILE_SET_INFOCHUNK = WM_START + 24 ; // 设置开始文件
public const int WM_CAP_FILE_SAVEDIB = WM_START + 25 ; // 保存文件
public const int WM_CAP_EDIT_COPY = WM_START + 30 ; // 编辑复制
public const int WM_CAP_SET_AUDIOFORMAT = WM_START + 35 ; // 设置音频格式
public const int WM_CAP_GET_AUDIOFORMAT = WM_START + 36 ; // 捕获音频格式
public const int WM_CAP_DLG_VIDEOFORMAT = WM_START + 41 ; // 1065 打开视频格式设置对话框
public const int WM_CAP_DLG_VIDEOSOURCE = WM_START + 42 ; // 1066 打开属性设置对话框,设置对比度亮度等
public const int WM_CAP_DLG_VIDEODISPLAY = WM_START + 43 ; // 1067 打开视频显示
public const int WM_CAP_GET_VIDEOFORMAT = WM_START + 44 ; // 1068 获得视频格式
public const int WM_CAP_SET_VIDEOFORMAT = WM_START + 45 ; // 1069 设置视频格式
public const int WM_CAP_DLG_VIDEOCOMPRESSION = WM_START + 46 ; // 1070 打开压缩设置对话框
public const int WM_CAP_SET_PREVIEW = WM_START + 50 ; // 设置预览
public const int WM_CAP_SET_OVERLAY = WM_START + 51 ; // 设置覆盖
public const int WM_CAP_SET_PREVIEWRATE = WM_START + 52 ; // 设置预览比例
public const int WM_CAP_SET_SCALE = WM_START + 53 ; // 设置刻度
public const int WM_CAP_GET_STATUS = WM_START + 54 ; // 获得状态
public const int WM_CAP_SET_SCROLL = WM_START + 55 ; // 设置卷
public const int WM_CAP_GRAB_FRAME = WM_START + 60 ; // 逮捕结构
public const int WM_CAP_GRAB_FRAME_NOSTOP = WM_START + 61 ; // 停止逮捕结构
public const int WM_CAP_SEQUENCE = WM_START + 62 ; // 次序
public const int WM_CAP_SEQUENCE_NOFILE = WM_START + 63 ; // 使用WM_CAP_SEUENCE_NOFILE消息(capCaptureSequenceNoFile宏),可以不向磁盘文件写入数据。该消息仅在配合回调函数时有用,它允许你的应用程序直接使用音视频数据。
public const int WM_CAP_SET_SEQUENCE_SETUP = WM_START + 64 ; // 设置安装次序
public const int WM_CAP_GET_SEQUENCE_SETUP = WM_START + 65 ; // 获得安装次序
public const int WM_CAP_SET_MCI_DEVICE = WM_START + 66 ; // 设置媒体控制接口
public const int WM_CAP_GET_MCI_DEVICE = WM_START + 67 ; // 获得媒体控制接口
public const int WM_CAP_STOP = WM_START + 68 ; // 停止
public const int WM_CAP_ABORT = WM_START + 69 ; // 异常中断
public const int WM_CAP_SINGLE_FRAME_OPEN = WM_START + 70 ; // 打开单一的结构
public const int WM_CAP_SINGLE_FRAME_CLOSE = WM_START + 71 ; // 关闭单一的结构
public const int WM_CAP_SINGLE_FRAME = WM_START + 72 ; // 单一的结构
public const int WM_CAP_PAL_OPEN = WM_START + 80 ; // 打开视频
public const int WM_CAP_PAL_SAVE = WM_START + 81 ; // 保存视频
public const int WM_CAP_PAL_PASTE = WM_START + 82 ; // 粘贴视频
public const int WM_CAP_PAL_AUTOCREATE = WM_START + 83 ; // 自动创造
public const int WM_CAP_PAL_MANUALCREATE = WM_START + 84 ; // 手动创造
public const int WM_CAP_SET_CALLBACK_CAPCONTROL = WM_START + 85 ; // 设置收回的错误
// 其它
public const int WM_CAP_SAVEDIB = WM_CAP_START + 25 ;
public const int WM_USER = 0x400 ; // 1024
public const int WM_CAP_START = WM_USER;
public const int WM_CAP_UNICODE_START = WM_USER + 100 ; // 开始
public const int WM_CAP_GRAB_FRame = (WM_CAP_START + 60 ); // 逮捕结构
public const int WM_CAP_GRAB_FRame_NOSTOP = (WM_CAP_START + 61 ); // 停止逮捕结构
public const int WM_CAP_SINGLE_FRame_OPEN = (WM_CAP_START + 70 ); // 打开单一的结构
public const int WM_CAP_SINGLE_FRame_CLOSE = (WM_CAP_START + 71 ); // 关闭单一的结构
public const int WM_CAP_SINGLE_FRame = (WM_CAP_START + 72 ); // 单一的结构
// Following added post VFW 1.1
public const int WM_CAP_END = WM_CAP_SET_CALLBACK_CAPCONTROL;
#endregion
#region 结构体
[StructLayout(LayoutKind.Sequential)]
public struct VIDEOHDR
{
[MarshalAs(UnmanagedType.I4)]
public int lpData;
[MarshalAs(UnmanagedType.I4)]
public int dwBufferLength;
[MarshalAs(UnmanagedType.I4)]
public int dwBytesUsed;
[MarshalAs(UnmanagedType.I4)]
public int dwTimeCaptured;
[MarshalAs(UnmanagedType.I4)]
public int dwUser;
[MarshalAs(UnmanagedType.I4)]
public int dwFlags;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4 )]
public int [] dwReserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFOHEADER
{
[MarshalAs(UnmanagedType.I4)]
public Int32 biSize;
[MarshalAs(UnmanagedType.I4)]
public Int32 biWidth;
[MarshalAs(UnmanagedType.I4)]
public Int32 biHeight;
[MarshalAs(UnmanagedType.I2)]
public short biPlanes;
[MarshalAs(UnmanagedType.I2)]
public short biBitCount;
[MarshalAs(UnmanagedType.I4)]
public Int32 biCompression;
[MarshalAs(UnmanagedType.I4)]
public Int32 biSizeImage;
[MarshalAs(UnmanagedType.I4)]
public Int32 biXPelsPerMeter;
[MarshalAs(UnmanagedType.I4)]
public Int32 biYPelsPerMeter;
[MarshalAs(UnmanagedType.I4)]
public Int32 biClrUsed;
[MarshalAs(UnmanagedType.I4)]
public Int32 biClrImportant;
}
#region BITMAPINFO结构
// BITMAPINFO结构具有如下形式:
// typedef struct tagBITMAPINFO
// {
// BITMAPINFOHEADER bmiHeader;
// RGBQUAD bmiColors[1];
// } BITMAPINFO;
// BITMAPINFO结构定义了Windows设备无关位图(DIB)的度量和颜色信息。
// 成员:
// bmiHeader 指定了一个BITMAPINFOHEADER结构,包含了有关设备相关位图的度量和颜色格式的信息。
// bmiColors 指定了一个RGBQUAD或DWORD数据类型的数组,定义了位图中的颜色。
// 注释:
// 设备无关位图由两个部分组成:
// (1) 一个BITMAPINFO结构,描述了位图的度量和颜色信息;
// (2) 一个字节数组,定义了位图的像素。数组中的字节被组合在一起,但是每个扫描行必须用零填补,在一个LONG边界结束。如果高度为正的,位图的起始位置在左下角。如果高度为负,起始位置在左上角。
// (3) BITMAPINFOHEADER结构中的biBitCount成员决定了定义像素的位数以及位图中的最大颜色数。这个成员可以是下列值之一:
// · 位图是单色的,bmiColors成员包含两个入口。位图数组中的每一位代表一个像素。如果该位被清除,则用bmiColors表中的第一种颜色显示该像素。如果该位被置位,则用表中的第二种颜色显示该像素。
// · 位图最多有16种颜色,bmiColors成员中包含了最多可达16个入口。位图中的每个像素用一个4位的值来表示,该值用作颜色表的索引。例如,如果位图中的第一个字节是0x1F,这个字节代表两个像素。第一个像素包含了颜色表中第二种颜色,第二个像素包含了颜色表中第十六种颜色。
// · 位图最多有256种颜色,bmiColors成员包含了多达256个入口。在这种情况下,数组中的每个字节代表一个像素。
// · 位图最多有216种颜色。BITMAPINFOHEADER的biCompression成员必须是BI_BITFIELDS。bmiColors成员包含了3个DWORD型颜色掩码,分别代表了每个像素中的红,绿和蓝色成分。DWORD型掩码中的位必须是连续的,不能与其它掩码重叠。并非像素中的所有位都必须被使用。数组中的每个WORD值代表一个像素。
// · 位图最多具有224种颜色,bmiColors成员为NULL。位图数组中的每个三字节组合分别代表像素中蓝,绿红的深度。
// · 位图中最多具有232种颜色。BITMAPINFOHEADER中的biCompression成员必须是BI_BITFIELDS。bmiColors成员中包含了三个DWORD颜色掩码,分别指定了像素的红,绿和蓝成分。DWORD掩码中的位必须是连续的,并且不能与其它掩码重叠。并非像素中的所有位都必须被使用。数组中的每个DWORD值代表一个像素。
// BITMAPINFOHEADER结构中的biClrUsed成员指定了颜色表中实际使用的索引的数目。如果biClrUsed成员被设为0,位图将使用biBitCount成员中指定的最大颜色数。
// bmiColors表中的颜色应当按照其重要性的顺序出现。另一种情况是,对于使用DIB函数,bmiColors成员可以是一个16位无符号整数的数组,指定了当前实现的逻辑调色板中的索引,而不是确切的RGB值。在这种情况下,使用位图的应用程序必须调用Windows的DIB函数(CreateDIBitmap,CreateDIBPatternBrush和CreateDIBSection),iUsage参数应被设为DIB_PAL_COLORS。
// 如果位图是一个压缩位图(这意味着,这种位图的数组直接跟在一个指针所引用的BITMAPINFO头的后面),在使用DIB_PAL_COLORS模式的时候,biClrUsed成员必须被设为偶数,以便使DIB位图数组从DWORD边界开始。
// 注意:
// 如果位图被保存在文件中,或者要被传送到另一个应用程序,bmiColors成员不能包含调色板索引。除非应用程序独占地使用和控制位图,位图的颜色表中应当包含准确的RGB值。
#endregion
///
/// BITMAPINFO结构定义了Windows设备无关位图(DIB)的度量和颜色信息。
///
[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFO
{
///
/// 指定了一个BITMAPINFOHEADER结构,包含了有关设备相关位图的度量和颜色格式的信息。
///
[MarshalAs(UnmanagedType.Struct, SizeConst = 40 )]
public BITMAPINFOHEADER bmiHeader;
///
/// 指定了一个RGBQUAD或DWORD数据类型的数组,定义了位图中的颜色。
///
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024 )]
public Int32[] bmiColors;
}
#endregion
#region 属性
private IntPtr lwndC; // 保存无符号句柄
private IntPtr mControlPtr; // 保存管理指示器 用于显示视频内容的控件地址指针
private int mWidth;
private int mHeight;
// 委托 祯 回调事件定义
public delegate void RecievedFrameEventHandler( byte [] data);
public event RecievedFrameEventHandler RecievedFrame;
private FrameEventHandler mFrameEventHandler; // Delegate instance for the frame callback - must keep alive! gc should NOT collect it
#endregion
///
/// 构造方法
///
/// 显示视频控件的句柄
/// 视频宽度
/// 视频高度
public AviCap(IntPtr handle, int width, int height)
{
mControlPtr = handle;
mWidth = width;
mHeight = height;
}
#region 静态方法
public static object GetStructure(IntPtr ptr, ValueType structure)
{
return Marshal.PtrToStructure(ptr, structure.GetType());
}
public static object GetStructure( int ptr, ValueType structure)
{
return GetStructure( new IntPtr(ptr), structure);
}
public static void Copy(IntPtr ptr, byte [] data)
{
Marshal.Copy(ptr, data, 0 , data.Length);
}
public static void Copy( int ptr, byte [] data)
{
Copy( new IntPtr(ptr), data);
}
public static int SizeOf( object structure)
{
return Marshal.SizeOf(structure);
}
#endregion
// 开启摄像头方法
public void StartWebCam()
{
byte [] lpszName = new byte [ 100 ]; // 名字
byte [] lpszVer = new byte [ 100 ]; // 版本号
AviCap.capGetDriverDescriptionA( 0 , lpszName, 100 , lpszVer, 100 );
this .lwndC = AviCap.capCreateCaptureWindowA(lpszName, WS_VISIBLE + WS_CHILD, 0 , 0 , mWidth, mHeight, mControlPtr, 0 );
if ( this .DriverConnect( 0 ))
{
this .PreviewRate( 66 );
this .Preview( true );
BITMAPINFO bitmapinfo = new BITMAPINFO();
bitmapinfo.bmiHeader.biSize = AviCap.SizeOf(bitmapinfo.bmiHeader);
// bitmapinfo.bmiHeader.biWidth = 352;
// bitmapinfo.bmiHeader.biHeight = 288;
bitmapinfo.bmiHeader.biWidth = mWidth;
bitmapinfo.bmiHeader.biHeight = mHeight;
bitmapinfo.bmiHeader.biPlanes = 1 ;
bitmapinfo.bmiHeader.biBitCount = 24 ;
// this.SetVideoFormat(ref bitmapinfo, AviCap.SizeOf(bitmapinfo));
// this.mFrameEventHandler = new AviCap.FrameEventHandler(FrameCallBack);
this .SetCallbackOnFrame( this .mFrameEventHandler);
AviCap.SetWindowPos( this .lwndC, 0 , 0 , 0 , mWidth, mHeight, 6 );
}
// byte[] lpszName = new byte[100];
// byte[] lpszVer = new byte[100];
// VideoAPI.capGetDriverDescriptionA(0, lpszName, 100, lpszVer, 100);
// this.lwndC = VideoAPI.capCreateCaptureWindowA(lpszName, VideoAPI.WS_CHILD | VideoAPI.WS_VISIBLE, 0, 0, mWidth, mHeight, mControlPtr, 0);
// if (VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_DRIVER_CONNECT, 0, 0))
// {
// VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_SET_PREVIEWRATE, 100, 0);
// VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_SET_PREVIEW, true, 0);
// }
}
// 关闭摄像头方法
public void CloseWebcam()
{
this .DriverDisconnect();
}
///
/// 拍照
///
/// BMP路由
public void GrabImage( string path)
{
IntPtr hBmp = Marshal.StringToHGlobalAnsi(path);
SendMessage( this .lwndC, WM_CAP_SAVEDIB, 0 , hBmp.ToInt32());
}
public bool DriverConnect( short nCameraID)
{
return SendMessage( this .lwndC, WM_CAP_DRIVER_CONNECT, nCameraID, 0 );
}
///
/// 驱动断开
///
///
///
public bool DriverDisconnect()
{
return SendMessage( this .lwndC, WM_CAP_DRIVER_DISCONNECT, 0 , 0 );
}
///
/// 预览
///
///
///
public bool Preview( bool f)
{
return SendMessage( this .lwndC, WM_CAP_SET_PREVIEW, f, 0 );
}
///
/// 设置预览比例
///
///
///
public bool PreviewRate( short wMS)
{
return SendMessage( this .lwndC, WM_CAP_SET_PREVIEWRATE, wMS, 0 );
}
///
/// 设置回调事件
///
private bool SetCallbackOnFrame(FrameEventHandler lpProc)
{
return SendMessage( this .lwndC, WM_CAP_SET_CALLBACK_FRAME, 0 , lpProc);
}
///
/// 设置视频格式
///
///
///
///
///
public bool SetVideoFormat( ref BITMAPINFO BmpFormat, int CapFormatSize)
{
return SendMessage( this .lwndC, WM_CAP_SET_VIDEOFORMAT, CapFormatSize, ref BmpFormat);
}
private void FrameCallBack(IntPtr lwnd, IntPtr lpVHdr)
{
VIDEOHDR videoHeader = new VIDEOHDR();
byte [] VideoData;
videoHeader = (VIDEOHDR)GetStructure(lpVHdr, videoHeader);
VideoData = new byte [videoHeader.dwBytesUsed];
Copy(videoHeader.lpData, VideoData);
if ( this .RecievedFrame != null )
this .RecievedFrame(VideoData);
}
}
// }