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;
/**/
///
/// 初始化显示图像
///
/// 控件的句柄
/// 开始显示的左边距
/// 开始显示的上边距
/// 要显示的宽度
/// 要显示的长度
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);
/**/
///
/// 开始显示图像
///
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;
}
/**/
///
/// 停止显示
///
public void Stop()
{
SendMessage(hWndC, WM_CAP_DRIVER_DISCONNECT, 0, 0);
bWorkStart = false;
}
/**/
///
/// 抓图
///
/// 要保存bmp文件的路径
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宏),可以断开连接。当捕获窗体销毁后,任何连接的视频捕获设备都将自动断开。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/suntaoznz/archive/2005/08/06/447067.aspx“
我按照上面的思路就在VideoWork类中加上了红色的代码,接上两个摄像头,试图调用两个摄像头。但是没有成功,并有如以上注解所示的错误。
请高人帮我指点一下,我该如何解决这个问题。