主要描述:
用VC2019+MFC 创建一个DLL封装MD工业相机库,再建一个EXE调用这个相机库采图并且显示。
先创建库工程:
新建一个库工程,
创建完成,添加一个DllFunction.h头文件,一个DllFunction.cpp 源文件
拷贝相关SDK文件到对应的目录下
(略,自行拷贝到相应位置,路径加进工程)
源码如下
DllFunction.h
#pragma once
extern "C" __declspec(dllexport) int InitCamera(int indexCam = 0);
extern "C" __declspec(dllexport) int GetImage();
extern "C" __declspec(dllexport) int Reconnect();
extern "C" __declspec(dllexport) int UninitCamera();
DllFunction.cpp
#pragma once
#include <Windows.h>
//引用相机的SDK包,lib文件的路径根据您的开发环境修改。
#include "CameraApi.h"
#include "CameraGrabber.h"
#ifdef _WIN64
#pragma comment(lib, "..\\MVCAMSDK_X64.lib")
#else
#pragma comment(lib, "..\\MVCAMSDK.lib")
#endif
tSdkCameraCapbility m_sCameraInfo; //相机特性描述
UINT m_threadID;//图像抓取线程的ID
HANDLE m_hDispThread;//图像抓取线程的句柄
BOOL m_bExit;//用来通知图像抓取线程结束
BOOL m_bTrigger;
double m_fExpTime;//当前的帧曝光时间,单位为us
double m_fExpLineTime;//当前的行曝光时间,单位为us
INT m_iAnalogGain;//当前的信号模拟增益值,步进值为m_fAnalogGainStep
BYTE* m_pFrameBuffer;//用于将原始图像数据转换为RGB的缓冲区(采集线程中)
BYTE* pOutBuffer;
BOOL m_bPause;//是否暂停图像
CameraHandle m_hCamera; //相机的设备句柄|the handle of the camera we use
tSdkFrameHead m_sFrInfo;//用于保存当前图像帧的帧头信息
//功能:初始化相机,进行相机的初始化操作
extern "C" __declspec(dllexport) int InitCamera(int indexCam = 0)
{
if (m_hCamera != 0)
{
if (NULL != m_hDispThread)
{
m_bExit = TRUE;
::WaitForSingleObject(m_hDispThread, INFINITE);
CloseHandle(m_hDispThread);
m_hDispThread = NULL;
}
CameraStop(m_hCamera);
CameraUnInit(m_hCamera);
}
CameraSetCallbackFunction(m_hCamera, NULL, (PVOID)0, NULL);
tSdkCameraDevInfo sCameraList[10];
INT iCameraNums;
CameraSdkStatus status;
CameraSdkInit(1);
void* m_Grabber;
tSdkCameraDevInfo m_DevInfo;
status = CameraGrabber_CreateFromDevicePage(&m_Grabber);
if (status != CAMERA_STATUS_SUCCESS)
{
return -1;
}
CameraGrabber_GetCameraDevInfo(m_Grabber, &m_DevInfo);
CameraGrabber_GetCameraHandle(m_Grabber, &m_hCamera);
CameraGetCapability(m_hCamera, &m_sCameraInfo);
m_pFrameBuffer = CameraAlignMalloc(m_sCameraInfo.sResolutionRange.iWidthMax * 200000, 16); //20万行线扫
BOOL m_bMonoSensor = m_sCameraInfo.sIspCapacity.bMonoSensor;
if (m_sCameraInfo.sIspCapacity.bMonoSensor)
{
CameraSetIspOutFormat(m_hCamera, CAMERA_MEDIA_TYPE_MONO8);
}
CameraSetTriggerMode(m_hCamera, 1);
CameraPlay(m_hCamera);
return 0;
}
extern "C" __declspec(dllexport) int GetImage()
{
tSdkFrameHead sFrameInfo;
BYTE* pbyBuffer;
CameraSdkStatus status;
CameraSoftTrigger(m_hCamera);
status = CameraGetImageBuffer(m_hCamera, &sFrameInfo, &pbyBuffer, 10000);
if (status == CAMERA_STATUS_SUCCESS)
{
status = CameraImageProcess(m_hCamera, pbyBuffer, m_pFrameBuffer, &sFrameInfo);
status = CameraSaveImage(m_hCamera, (char*)"H:\\test.bmp", m_pFrameBuffer, &sFrameInfo, FILE_BMP, 100); //no -22
CameraReleaseImageBuffer(m_hCamera, pbyBuffer);
}
return status;
}
extern "C" __declspec(dllexport) int Reconnect()
{
CameraSdkStatus status = CameraReConnect(m_hCamera);
return status;
}
extern "C" __declspec(dllexport) int UninitCamera()
{
CameraSdkStatus status = CameraUnInit(m_hCamera);
CameraAlignFree(m_pFrameBuffer);
return status;
}
再创建一个exe程序,用来调用创建的dll文件 。
创建,下一步选择基于对话框的项目,下一步后的打印相关的、COM相关的全部不用选择,其他的默认就可以。
拖拉一些控件到对话框窗口上,最终如下图
文件源码如下
MindVisionCallDlg.h: 头文件
#pragma once
// CMindVisionCallDlg 对话框
class CMindVisionCallDlg : public CDialogEx
{
// 构造
public:
CMindVisionCallDlg(CWnd* pParent = nullptr); // 标准构造函数
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_MINDVISIONCALL_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedBtnInit();
afx_msg void OnBnClickedBtnReconn();
afx_msg void OnBnClickedBtnGrab();
afx_msg void OnClose();
CStatic m_cPreview;
};
MindVisionCallDlg.cpp: 实现文件
#include "pch.h"
#include "framework.h"
#include "MindVisionCall.h"
#include "MindVisionCallDlg.h"
#include "afxdialogex.h"
#include "DllFunction.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CMindVisionCallDlg::CMindVisionCallDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_MINDVISIONCALL_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMindVisionCallDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_STATIC_PREVIEW, m_cPreview);
}
BEGIN_MESSAGE_MAP(CMindVisionCallDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_INIT, &CMindVisionCallDlg::OnBnClickedBtnInit)
ON_BN_CLICKED(IDC_BTN_RECONN, &CMindVisionCallDlg::OnBnClickedBtnReconn)
ON_BN_CLICKED(IDC_BTN_GRAB, &CMindVisionCallDlg::OnBnClickedBtnGrab)
ON_WM_CLOSE()
END_MESSAGE_MAP()
BOOL CMindVisionCallDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CMindVisionCallDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this);
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
HCURSOR CMindVisionCallDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CMindVisionCallDlg::OnBnClickedBtnInit()
{
int code = InitCamera(1);
if (code)
{
}
CString Info;
Info.Format(_T("Result = %d"), code);
SetDlgItemText(IDC_STC_INFO, Info);
}
void CMindVisionCallDlg::OnBnClickedBtnReconn()
{
int code = Reconnect();
if (code)
{
}
CString Info;
Info.Format(_T("Result = %d"), code);
SetDlgItemText(IDC_STC_INFO, Info);
}
void CMindVisionCallDlg::OnBnClickedBtnGrab()
{
int code = GetImage();
if (0 == code)
{
CClientDC dc(this);
CDC* mdc = new CDC;
mdc->CreateCompatibleDC(&dc);
CBitmap bitmap;
bitmap.m_hObject = (HBITMAP)::LoadImageA(AfxGetInstanceHandle(), (char*)"H:\\test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
mdc->SelectObject(bitmap);
CRect rect;
::GetWindowRect(m_cPreview.GetSafeHwnd(), &rect);
ScreenToClient(&rect);
BITMAP sBitMap;
bitmap.GetBitmap(&sBitMap);
dc.StretchBlt(rect.left, rect.top, rect.Width(), rect.Height(), mdc, 0, 0, sBitMap.bmWidth, sBitMap.bmHeight, SRCCOPY);
delete mdc;
}
CString Info;
Info.Format(_T("Result = %d"), code);
SetDlgItemText(IDC_STC_INFO, Info);
}
void CMindVisionCallDlg::OnClose()
{
int code = UninitCamera();
if (code)
{
}
CDialogEx::OnClose();
}
两个工程保存在同一个方案,然后建立项目依赖,如此就两个工程一起编译。
最后运行效果,
(本节结束)