C#调用avicap32.dll实现摄像头拍照与二维码识别
在C#开发中,若需在WinForms桌面应用中调用本地摄像头进行图像采集或二维码识别,可以使用系统底层的 avicap32.dll 库。本文将详细拆解如何初始化摄像头、获取预览、保存截屏以及使用 ZXing 库解码二维码的完整流程。
核心逻辑说明
该方案主要包含三个部分:一是通过 Windows 媒体控制接口连接摄像头并显示预览;二是截取当前视频帧保存为 BMP 文件;三是读取该文件利用 ZXing.Net 库解析二维码文本。需要注意的是,avicap32 是较老的API,通常用于传统的WinForms控件宿主环境,不直接支持现代浏览器端或无界面(Headless)服务器环境。
1. 初始化与声明
首先需要在类中声明外部 DLL 函数及相关的常量。这一步定义了摄像头窗口的创建参数和视频消息的控制指令。
// 定义必要的常量
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;
// ... 其他 WM_CAP_ 相关常量 ...
// 引入外部动态链接库
[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("User32.dll")]
private static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, long lParam);
2. 启动摄像头预览
创建一个控制类 Pick,在 Start() 方法中建立与摄像头的连接。此过程会创建一个子窗口用于实时显示摄像头画面。
public void Start()
{
if (bStat) return;
bStat = 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_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_PREVIEW, 1, 0);
}
}
3. 执行抓拍与录像操作
抓取图像的核心是将当前视频缓冲区的数据保存为磁盘上的 BMP 文件。这是后续二维码识别的基础步骤。
/// <summary>
/// 抓图保存到指定路径
/// </summary>
public void GrabImage(string path)
{
IntPtr hBmp = Marshal.StringToHGlobalAnsi(path);
SendMessage(hWndC, WM_CAP_SAVEDIB, 0, hBmp.ToInt64());
}
4. 完整集成示例与二维码解码
以下代码展示了如何在 WinForms 页面中实例化摄像头控制对象,抓取一张图片,并使用 ZXing.Net 库读取其中的二维码信息。请确保项目中已安装 ZXing.Net NuGet 包。
using System;
using System.Windows.Forms;
using System.Drawing;
using ZXing;
public partial class FormCamera : Form
{
public class Pick
{
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_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_SET_OVERLAY = WM_CAP_START + 51;
private const int WM_CAP_SET_PREVIEW = WM_CAP_START + 50;
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 bool bStat = false;
private IntPtr mControlPtr;
private int mWidth, mHeight, mLeft, mTop;
public Pick(IntPtr handle, int left, int top, int width, int height)
{
mControlPtr = handle; mWidth = width; mHeight = height;
mLeft = left; mTop = top;
}
[System.Runtime.InteropServices.DllImport("avicap32.dll")]
private static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, long lParam);
public void Start()
{
if (bStat) return;
bStat = 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_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_PREVIEW, 1, 0);
}
}
public void Stop()
{
SendMessage(hWndC, WM_CAP_DRIVER_DISCONNECT, 0, 0);
bStat = false;
}
public void GrabImage(string path)
{
IntPtr hBmp = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(path);
SendMessage(hWndC, WM_CAP_SAVEDIB, 0, hBmp.ToInt64());
}
}
private void btnCapture_Click(object sender, EventArgs e)
{
try
{
// 1. 准备UI容器
using (var frm = new Form())
using (var panel = new PictureBox { Height = 300, Width = 300, Visible = true, BackgroundImageLayout = ImageLayout.None })
{
frm.Controls.Add(panel);
frm.TopMost = true;
// 2. 初始化并启动摄像头
var pick = new Pick(panel.Handle, 0, 0, 300, 300);
pick.Start();
// 3. 执行抓拍
string savePath = System.IO.Path.Combine(Application.StartupPath, "capture.bmp");
pick.GrabImage(savePath);
// 4. 停止资源
pick.Stop();
}
// 5. 使用 ZXing 解码
if (System.IO.File.Exists(savePath))
{
Bitmap bmp = new Bitmap(savePath);
var reader = new BarcodeReader();
var result = reader.Decode(bmp);
if (result != null)
{
MessageBox.Show("识别结果: " + result.Text);
}
else
{
MessageBox.Show("未检测到有效二维码");
}
bmp.Dispose();
}
}
catch (Exception ex)
{
MessageBox.Show("发生错误: " + ex.Message);
}
}
}
关键注意事项
- 运行环境:
avicap32依赖于 Windows 系统的摄像头驱动框架,且必须在具有 GUI 线程模型的进程中运行(如 WinForms/WPF),无法在无头服务中直接使用。 - 依赖库: 本例使用了
ZXing.Net进行条码解析,请在 NuGet 管理器中搜索安装该库。 - 权限与安全: 调用摄像头通常需要用户确认,首次运行时可能会弹出隐私授权提示。
以上就是C#利用avicap32库调用摄像头拍照并结合ZXing进行二维码识别的详细内容,更多关于C#硬件交互控制的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









