2013-08-21 25 views
0

我写了一个c#程序,使用.net框架2.0摄像头拍照。我试图使用avicap32.dll来调用摄像头。只有一次调用avicap32 c#

问题是我可以打电话给我的网络摄像头一次,如果我断开网络摄像头并通过一些按钮重新启动它,那么图片箱将显示一张黑色照片,并且无法再次调用网络摄像头。如果我再次重新启动程序,它将在图片框中保持黑色。只有当我重新启动我的电脑。 W.T.F.任何人都可以解决这个问题?

我把源代码放在下面。试着弄清楚发生了什么事。另一个瑕疵是图片框中的照片不能设置图片的中心。

这里的Form1.cs的

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Text; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 
using System.Threading; 

namespace AutoCam 
{ 
    public partial class form1 : Form 
    { 

     public form1() 
     { 
      InitializeComponent(); 
     } 
     Camera camera; 

     #region InitializeComponent 

     #region btn_openCamera #endregion 
     private void button1_Click(object sender, EventArgs e) 
     { 

      this.btn_openCamera.Enabled = false; 
      this.btn_closeCam.Enabled = true; 
      this.btn_cameraPic.Enabled = true; 
      camera = new Camera(this.pic_camera.Handle, this.pic_camera.Width, this.pic_camera.Height); 
      camera.StartWebCam(); 
     } 
     #endregion 

     #region btn_closeCam_Click 
     private void btn_closeCam_Click(object sender, EventArgs e) 
     { 
      this.btn_openCamera.Enabled = true; 
      this.btn_closeCam.Enabled = false; 
      this.btn_cameraPic.Enabled = false; 
      camera.CloseWebcam(); 
     } 
     #endregion 

     #region btn_cameraPic_Click 
     private void btn_cameraPic_Click(object sender, EventArgs e) 
     { 
      camera.GrabImage(this.pic_camera.Handle, "guying.bmp"); 
     } 
     #endregion 

     private void quit_Click(object sender, EventArgs e) 
     { 
      this.Close(); 
     } 
    } 
} 

这里的camera.cs

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Threading; 
using System.Runtime.InteropServices; 
using System.IO; 
using System.Windows; 

namespace AutoCam 
{ 

    class Camera 
    { 
    private IntPtr lwndC; 
     private IntPtr mControlPtr; 
     private int mWidth; 
     private int mHeight; 

     public Camera(IntPtr handel, int width, int height) 
     { 
      mControlPtr = handel; //handle of video dom 
      mWidth = width; //video width 
      mHeight = height; //video height 
     } 

     public void StartWebCam() 
     { 
      byte[] lpszName = new byte[100]; 
      byte[] lpszVer = new byte[100]; 
      CameraAPI.capGetDriverDescriptionA(0, lpszName,100, lpszVer, 0); 
      this.lwndC = CameraAPI.capCreateCaptureWindowA(lpszName, CameraAPI.WS_CHILD | CameraAPI.WS_VISIBLE, 0, 0, mWidth, mHeight, mControlPtr, 0); 
      if (CameraAPI.SendMessage(lwndC, CameraAPI.WM_CAP_DRIVER_CONNECT, 0, 0)) 
      { 
       CameraAPI.SendMessage(lwndC, CameraAPI.WM_CAP_SET_PREVIEWRATE, 100, 0); 
       CameraAPI.SendMessage(lwndC, CameraAPI.WM_CAP_SET_PREVIEW, true, 0); 
      } 
     } 

     public void CloseWebcam() 
     { 
      CameraAPI.SendMessage(lwndC, CameraAPI.WM_CAP_DRIVER_DISCONNECT, 0, 0); 
     } 

     public void GrabImage(IntPtr hWndC, string path) 
     { 
      IntPtr hBmp = Marshal.StringToHGlobalAnsi(path); 
      CameraAPI.SendMessage(lwndC, CameraAPI.WM_CAP_SAVEDIB, 0, hBmp.ToInt32()); 
     } 

    } 

} 

这里的cameraAPI.cs

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Text; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 
using System.Threading; 

namespace AutoCam 
{ 
    class CameraAPI 
    { 
     [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 const int WM_USER = 0x400; 
     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_DRIVER_CONNECT = WM_USER + 10; 
     public const int WM_CAP_DRIVER_DISCONNECT = WM_USER +11; 
     public const int WM_CAP_SET_CALLBACK_FRAME = WM_USER +5; 
     public const int WM_CAP_SET_PREVIEW = WM_USER+50; 
     public const int WM_CAP_SET_PREVIEWFORMAT = WM_USER + 45; 
     public const int WM_CAP_SET_PREVIEWRATE = WM_USER + 52; 
     public const int WM_CAP_START = WM_USER; 
     public const int WM_CAP_SAVEDIB = WM_CAP_START + 25; 

    } 
} 

回答

0

您可以参考这个blog,并修改码。我已经尝试了代码,它运行良好。 点击停止:

  bStopped = true; 
      this.timer.Stop(); 

      Application.DoEvents(); 

      SendMessage(m_CapHwnd, WM_CAP_DISCONNECT, 0, 0); 

      CloseClipboard(); 

点击开始:

 stop(); 

     m_CapHwnd = capCreateCaptureWindowA("WebCap", 0, 0, 0, m_Width, m_Height, this.Handle.ToInt32(), 0); 

     Application.DoEvents(); 

     SendMessage(m_CapHwnd, WM_CAP_CONNECT, 0, 0); 

     this.timer.Interval = 1; 

     bStopped = false; 
     this.timer.Start(); 

计时器回调:

 this.timer.Stop(); 

     SendMessage(m_CapHwnd, WM_CAP_GT_FRAME, 0, 0); 

     SendMessage(m_CapHwnd, WM_CAP_COPY, 0, 0); 

     OpenClipboard(m_CapHwnd); 

     CloseClipboard(); 

     IDataObject dataObj = Clipboard.GetDataObject(); 
     Image img = (System.Drawing.Bitmap)dataObj.GetData(DataFormats.Bitmap); 
     //img.Save("e:\\test_" + DateTime.UtcNow.Ticks + ".jpg"); 
     pictureBox.Image = img; 

     pictureBox.Refresh(); 

     Application.DoEvents(); 

     if (!bStopped) 
     { 
      this.timer.Start(); 
     }