AviCap

代码
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);

    
/// <summary>
    
/// 该函数改变一个子窗口,弹出式窗口式顶层窗口的尺寸,位置和Z序。子窗口,弹出式窗口,及顶层窗口根据它们在屏幕上出现的顺序排序、顶层窗口设置的级别最高,并且被设置为Z序的第一个窗口。
    
/// </summary>
    [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
    
/// <summary>
    
/// BITMAPINFO结构定义了Windows设备无关位图(DIB)的度量和颜色信息。
    
/// </summary>
    [StructLayout(LayoutKind.Sequential)]
    
public struct BITMAPINFO
    {
        
/// <summary>
        
/// 指定了一个BITMAPINFOHEADER结构,包含了有关设备相关位图的度量和颜色格式的信息。
        
/// </summary>
        [MarshalAs(UnmanagedType.Struct, SizeConst = 40)]
        
public BITMAPINFOHEADER bmiHeader;

        
/// <summary>
        
/// 指定了一个RGBQUAD或DWORD数据类型的数组,定义了位图中的颜色。
        
/// </summary>
        [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

    
/// <summary>
    
/// 构造方法
    
/// </summary>
    
/// <param name="handle">显示视频控件的句柄</param>
    
/// <param name="width">视频宽度</param>
    
/// <param name="height">视频高度</param>
    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, 00, 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, 000, 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();
    }

    
/// <summary>
    
/// 拍照
    
/// </summary>
    
/// <param name="path">BMP路由</param>
    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);
    }

    
/// <summary>
    
/// 驱动断开
    
/// </summary>
    
/// <param name="lwnd"></param>
    
/// <returns></returns>
    public bool DriverDisconnect()
    {
        
return SendMessage(this.lwndC, WM_CAP_DRIVER_DISCONNECT, 00);
    }

    
/// <summary>
    
/// 预览
    
/// </summary>
    
/// <param name="f"></param>
    
/// <returns></returns>
    public bool Preview(bool f)
    {
        
return SendMessage(this.lwndC, WM_CAP_SET_PREVIEW, f, 0);
    }

    
/// <summary>
    
/// 设置预览比例
    
/// </summary>
    
/// <param name="wMS"></param>
    
/// <returns></returns>
    public bool PreviewRate(short wMS)
    {
        
return SendMessage(this.lwndC, WM_CAP_SET_PREVIEWRATE, wMS, 0);
    }

    
/// <summary>
    
/// 设置回调事件
    
/// </summary>
    private bool SetCallbackOnFrame(FrameEventHandler lpProc)
    {
        
return SendMessage(this.lwndC, WM_CAP_SET_CALLBACK_FRAME, 0, lpProc);
    }

    
/// <summary>
    
/// 设置视频格式
    
/// </summary>
    
/// <param name="hCapWnd"></param>
    
/// <param name="BmpFormat"></param>
    
/// <param name="CapFormatSize"></param>
    
/// <returns></returns>
    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);
    }

}
//}

 

posted @ 2010-07-16 07:37  jgjg2323  阅读(543)  评论(0编辑  收藏  举报