C#调用两个至多个USB摄像头的问题

    技术2022-05-20  56

    using   System; using   System.Collections.Generic; using   System.Text; using   System.Runtime.InteropServices;using System.Drawing;

    namespace   USBcamera{         public   class   VideoWork         {                 private   const   int   WM_USER   =   0x400;                 private   const   int   WS_CHILD   =   0x40000000;                 private   const   int   WS_VISIBLE   =   0x10000000;                 private   const   int   WM_CAP_START   =   WM_USER;                 private   const   int   WM_CAP_STOP   =   WM_CAP_START   +   68;                 private   const   int   WM_CAP_DRIVER_CONNECT   =   WM_CAP_START   +   10;                 private   const   int   WM_CAP_DRIVER_DISCONNECT   =   WM_CAP_START   +   11;                 private   const   int   WM_CAP_SAVEDIB   =   WM_CAP_START   +   25;                 private   const   int   WM_CAP_GRAB_FRAME   =   WM_CAP_START   +   60;                 private   const   int   WM_CAP_SEQUENCE   =   WM_CAP_START   +   62;                 private   const   int   WM_CAP_FILE_SET_CAPTURE_FILEA   =   WM_CAP_START   +   20;                 private   const   int   WM_CAP_SEQUENCE_NOFILE   =   WM_CAP_START   +   63;                 private   const   int   WM_CAP_SET_OVERLAY   =   WM_CAP_START   +   51;                 private   const   int   WM_CAP_SET_PREVIEW   =   WM_CAP_START   +   50;                 private   const   int   WM_CAP_SET_CALLBACK_VIDEOSTREAM   =   WM_CAP_START   +   6;                 private   const   int   WM_CAP_SET_CALLBACK_ERROR   =   WM_CAP_START   +   2;                 private   const   int   WM_CAP_SET_CALLBACK_STATUSA   =   WM_CAP_START   +   3;                 private   const   int   WM_CAP_SET_CALLBACK_FRAME   =   WM_CAP_START   +   5;                 private   const   int   WM_CAP_SET_SCALE   =   WM_CAP_START   +   53;                 private   const   int   WM_CAP_SET_PREVIEWRATE   =   WM_CAP_START   +   52;                 private   IntPtr   hWndC;                private IntPtr hWndC_1;                private   bool   bWorkStart   =   false;                private bool bWorkStart_1 = false;                 private   IntPtr   mControlPtr;                private IntPtr mControlPtr_1;                 private   int   mWidth;                 private   int   mHeight;                 private   int   mLeft;                 private   int   mTop;

                    /**/                 ///   <summary>                 ///   初始化显示图像                 ///   </summary>                 ///   <param   name= "handle "> 控件的句柄 </param>                 ///   <param   name= "left "> 开始显示的左边距 </param>                 ///   <param   name= "top "> 开始显示的上边距 </param>                 ///   <param   name= "width "> 要显示的宽度 </param>                 ///   <param   name= "height "> 要显示的长度 </param>                 public   VideoWork(IntPtr   handle,   int   left,   int   top,   int   width,   int   height)                 {                         mControlPtr   =   handle;                        mControlPtr_1 = handle;                         mWidth   =   width;                         mHeight   =   height;                         mLeft   =   left;                         mTop   =   top;                 }                        [DllImport( "avicap32.dll ")]                         private   static   extern   IntPtr capCreateCaptureWindowA(byte[] lpszWindowName,int dwStyle,int x,int y,int nWidth,int nHeight,IntPtr hWndParent, int nID);            [DllImport("avicap32.dll ")]                 private static extern IntPtr capCreateCaptureWindowB(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID); /*新加的一个API调用,但是在编译的时候出错,提示“无法在 DLL“avicap32.dll ”中找到名为“capCreateCaptureWindowB”的入口点。”*/       

                    [DllImport( "avicap32.dll ")]                 private   static   extern   int   capGetVideoFormat(IntPtr   hWnd,   IntPtr   psVideoFormat,   int   wSize);

                    //                 //这里特别注意,因为WinAPI中的long为32位,而C#中的long为64wei,所以需要将lParam该为int                 //                 [DllImport( "User32.dll ")]                 private   static   extern   bool   SendMessage(IntPtr   hWnd,   int   wMsg,   int   wParam,   int   lParam);

                    /**/                 ///   <summary>                 ///   开始显示图像                 ///   </summary>                 public   void   Start()                 {                    if (bWorkStart)                        return;

                            bWorkStart   =   true;                         byte[]   lpszName   =   new   byte[100];

                            hWndC   =   capCreateCaptureWindowA(lpszName,   WS_CHILD   |   WS_VISIBLE,   mLeft,   mTop,   mWidth,   mHeight,   mControlPtr,   0);

                            if   (hWndC.ToInt32()   !=   0)                         {                                 SendMessage(hWndC,   WM_CAP_SET_CALLBACK_VIDEOSTREAM,   0,   0);                                 SendMessage(hWndC,   WM_CAP_SET_CALLBACK_ERROR,   0,   0);                                 SendMessage(hWndC,   WM_CAP_SET_CALLBACK_STATUSA,   0,   0);                                 SendMessage(hWndC,   WM_CAP_DRIVER_CONNECT,   0,   0);                                 SendMessage(hWndC,   WM_CAP_SET_SCALE,   1,   0);                                 SendMessage(hWndC,   WM_CAP_SET_PREVIEWRATE,   66,   0);                                 SendMessage(hWndC,   WM_CAP_SET_OVERLAY,   1,   0);                                 SendMessage(hWndC,   WM_CAP_SET_PREVIEW,   1,   0);                                 //Global.log.Write( "SendMessage ");                         }                         return;

                    }            //[DllImport("avicap32.dll ")]//add a window            //private static extern IntPtr capCreateCaptureWindowB(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);             public void Start(int i)///这是我新添的一个方法,想用来调用另外一个摄像头,            {                //if (bWorkStart_1)                   // return;

                    bWorkStart_1 = true;                byte[] lpszName_1 = new byte[100];

                    hWndC_1 = capCreateCaptureWindowB(lpszName_1, WS_CHILD | WS_VISIBLE, mLeft, mTop, mWidth, mHeight, mControlPtr_1, 0);

                    if (hWndC_1.ToInt32() != 0)                {                    SendMessage(hWndC_1, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 1);                    SendMessage(hWndC_1, WM_CAP_SET_CALLBACK_ERROR, 0, 0);                    SendMessage(hWndC_1, WM_CAP_SET_CALLBACK_STATUSA, 0, 0);                    SendMessage(hWndC_1, WM_CAP_DRIVER_CONNECT, 1,0);                    SendMessage(hWndC_1, WM_CAP_SET_SCALE, 1, 0);                    SendMessage(hWndC_1, WM_CAP_SET_PREVIEWRATE, 66, 0);                    SendMessage(hWndC_1, WM_CAP_SET_OVERLAY, 1, 0);                    SendMessage(hWndC_1, WM_CAP_SET_PREVIEW, 1, 0);                    //Global.log.Write( "SendMessage ");                 }                return;

                }                 /**/                 ///   <summary>                 ///   停止显示                 ///   </summary>                 public   void   Stop()                 {                         SendMessage(hWndC,   WM_CAP_DRIVER_DISCONNECT,   0,   0);                         bWorkStart   =   false;                 }

                    /**/                 ///   <summary>                 ///   抓图                 ///   </summary>                 ///   <param   name= "path "> 要保存bmp文件的路径 </param>                 public   void   GrabImage(string   path)                 {                         IntPtr   hBmp   =   Marshal.StringToHGlobalAnsi(path);                        //SendMessage(hWndC,   WM_CAP_SAVEDIB,   0,   hBmp.ToInt32());                 }                    } }

     

     

     

    主窗体中的调用方法是

     private void Form1_Load(object sender, EventArgs e)        {                       

               VideoWork   VideoA = new VideoWork(pictureBox1.Handle, 0, 0, pictureBox1.Width, pictureBox1.Height);           VideoWork   VideoB = new VideoWork(label1.Handle, 0, 0, label1.Width, label1.Height);            VideoA.Start();            VideoB.Start(1);                 

            }

     

     

    以上的代码是一个调用摄像头的类,去掉红色的字体部分,调用一个摄像头是没问题。我查阅了一些资料,有专家介绍说

    创建一个AVICap捕获窗口:

           使用capCreateCaptureWindow 函数可以创建一个AVICap的捕获窗口。这个函数返回一个窗口句柄,这个句柄就是捕获窗口的句柄,后面其他操作就是通过发送消息给该句柄来实现。你可以在一个程序中创建多个捕获窗口,并且每个窗口连接到不同的捕获设备上。

     

    建立捕获窗口到捕获设备的连接:

    你可以动态地连接或断开捕获窗口与设备间的链接。通过使用WM_CAP_DRIVR_CONNECT消息(或capDriverConnect宏),可以实现捕获窗体与设备驱动间的连接。当捕获窗体和捕获设备驱动连接后,你就可以发送针对设备的消息给该窗体了。

    如果你的系统安装了多个捕获设备,你可以通过在发送WM_CAP_DRIVER_CONNECT消息时,设置wPrarm参数(integer)。来指定捕获窗口与那个具体的视频捕获设备相连接。

    WPrarm参数是一个整数,它表示一个系统已经安装的视频捕获设备列表的索引(注册表中或这System.ini [drivers]中的信息)。该列表的索引从0开始。

           通过capGetDriverDescription函数可以获得安装的捕获驱动程序的名称和版本。你的应用程序可以使用这个函数列举除安装的所有捕获设备,让用户可以选择其中一个去与捕获窗口相联。

    通过发送WM_CAP_DRIVER_GET_NAME消息(capDriverGetName宏),可以获得与指定窗体连接的捕获设备的名称。通过发送WM_CAP_DRIVER_GET_VERSION消息(capDriverGetVersion宏),可以获得与指定窗体连接的捕获设备的版本。

    通过发送WM_CAP_DRIVER_DISCONNECT消息(capDriverGetDisconnect宏),可以断开连接。当捕获窗体销毁后,任何连接的视频捕获设备都将自动断开。

     

    本文来自博客,转载请标明出处:http://blog.csdn.net/suntaoznz/archive/2005/08/06/447067.aspx

     

     

    我按照上面的思路就在VideoWork类中加上了红色的代码,接上两个摄像头,试图调用两个摄像头。但是没有成功,并有如以上注解所示的错误。

    请高人帮我指点一下,我该如何解决这个问题。

     


    最新回复(0)