AviCap

ExpandedBlockStart.gif 代码
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);
    }

}
// }

 

转载于:https://www.cnblogs.com/jgjgjg23/archive/2010/07/16/1778530.html

你可能感兴趣的:(AviCap)