C++ MFC
作者:DONG_LIN_2019
来源:CSDN
原文:https://blog.csdn.net/weixin_41275726/article/details/84995723
版权声明:本文为博主原创文章,转载请附上博文链接!
目录
MFC——窗口静态显示
MFC——定时器:窗口动态显示
MFC——【X】退出菜单缓存清除
MFC——警告弹窗MessageBox
MFC——相机单帧采集
MFC——问题:non-unicode character set is deprdeprecated
MFC——多线程:
MFC——纯ALT读取图(静态和动态)
MFC——字符、字符串、数值等之间的转换
MFC——改变控件大小
MFC——窗口静态显示
利用Opencv库进行窗口显示
需要材料:CvvImage.h和CvvImage.cpp
步骤:第一步:头文件、第二步:声明、第三步:使用
/*
功能;画入指定IDC
第一步:头文件:在当前的类的的头文件代码区头包含:#include "CvvImage.h"
第二步:将函数在当前所在的类的头文件声明:void CMFC_CalibrationDlg::drawToDC(IplImage* image, UINT ID)
第三步:使用
IplImage img = src;
drawToDC(&img, 自己指定IDC窗口); //显示
*/
void C自己MFC的Dlg::drawToDC(IplImage* image, UINT ID)//画到指定ID(默认IDC_STATIC)在头文件声明函数
{
CDC* pDC = GetDlgItem(ID)->GetDC();
HDC pHdc = pDC->GetSafeHdc();
CRect rect;
GetDlgItem(ID)->GetClientRect(&rect);
CvvImage cimg;
cimg.CopyOf(image);
cimg.DrawToHDC(pHdc, rect);
ReleaseDC(pDC);
}
MFC——定时器:窗口动态显示
/*
// 窗口定时事件
窗口类向导——》消息——》WMTimer——》OnTimer双击——》编辑代码
使用:
SetTimer(1, 10, NULL);//开启定时器1
KillTimer(1); //关闭定时器防止缓存滞留
*/
void CdahengDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
switch (nIDEvent)
{
case 1://Timer(1)
{ //objImageDataPtr获取相机缓存
my_camera.objImageDataPtr = my_camera.ObjStreamPtr->GetImage(100);//超时时间使用500ms,用户可以自行设定
if (my_camera.objImageDataPtr->GetStatus() == GX_FRAME_STATUS_SUCCESS)
{
my_camera.ImageFlag = true; //图片采集成功
//假设原始数据是BayerRG8图像,则 GX_BIT_0_7
void* pRGB24Buffer = NULL;
pRGB24Buffer = my_camera.objImageDataPtr->ConvertToRGB24(GX_BIT_0_7, GX_RAW2RGB_NEIGHBOUR, true);
Mat test;
test.create(my_camera.objImageDataPtr->GetHeight(), my_camera.objImageDataPtr->GetWidth(), CV_8UC3);
memcpy(test.data, pRGB24Buffer, my_camera.objImageDataPtr->GetPayloadSize() * 3);
if (test.data){
IplImage image;
image = test;
drawToDC(&image, IDC_STATIC_SHOW);
}
}
else
{
KillTimer(1); //关闭定时器防止缓存滞留
if (MessageBox(_T("请连接相机"), _T("相机事件"), MB_YESNO | MB_ICONWARNING) == IDNO)
{
//关闭定时刷新
break;
}
}
break;
}
case 2://Timer(2)
{
// 用户程序
break;
}
}
CDialogEx::OnTimer(nIDEvent);
}
MFC——【X】退出菜单缓存清除
/*
//窗口关闭【X】的事件
窗口类向导——》消息——》WMClose双击——》OnClose程序块——》添加代码
使用:
直接在此程序块进行操作
*/
void CdahengDlg::OnClose()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
// 关闭相机
if (my_camera.DeviceFlag == true)
{
my_camera.DeviceFlag = false;
my_camera.ImageFlag = false;
my_camera.OpenFlag = true;//初始化重启
KillTimer(1); //关闭定时器防止缓存滞留
//发送停采命令
my_camera.ObjFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
my_camera.ObjStreamPtr->StopGrab();
//释放资源
my_camera.ObjStreamPtr->Close();
my_camera.ObjDevicePtr->Close();
//反初始化库
MessageBox(_T("相机【确定】关闭"), _T("相机事件..."));
IGXFactory::GetInstance().Uninit();
}
CDialogEx::OnClose();
}
MFC——警告弹窗MessageBox
// 更多功能查找其他说明书
MessageBox(_T("相机【确定】关闭"), _T("相机事件..."));
MFC——相机单帧采集
/*利用按钮进行标志位,然后定时器里面进行赋值命令*/
// 图像处理
void CdahengDlg::OnBnClickedButtonPro()
{
// TODO: 在此添加控件通知处理程序代码
if (my_camera.OpenFlag == true)
{
MessageBox(_T("请打开相机"));
return;
}
if (my_camera.ImageFlag == true)
{
my_camera.ImageClo = true;//相片结束标志
}
}
// 采集命令
if (my_camera.ImageClo == true)//相片处理按钮标志
{
test.copyTo(my_camera.src);
if (my_camera.src.data)
{
IplImage image;
image = my_camera.src;
drawToDC(&image, IDC_STATIC_SHOWPRO);
my_camera.ImageClo = false;//相片结束标志
}
}
项目链接
MFC——问题:non-unicode character set is deprdeprecated
“错误 1 error MSB8031: Building an MFC project for a non-Unicode character set is deprecated. You must change the project property to Unicode or download an additional library. See http://go.microsoft.com/fwlink/p/?LinkId=286820 for more information. C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Microsoft.CppBuild.targets 369 5 Signal
”
下载xian相应的支持包:http://go.microsoft.com/fwlink/p/?LinkId=286820
MFC——多线程:
//创建实例:
CWinThread* XXXXX;
//线程函数:
UINT ChildThread1(LPVOID Param);/*重点:CMFC_CZDlg* pDlg = (CMFC_CZDlg*)Param; //参数传入*/
//开启:
XXXXX = AfxBeginThread(ChildThread1, (LPVOID)this, THREAD_PRIORITY_NORMAL);//开启子线程1
//暂停(挂起):
XXXXX ->SuspendThread(); //暂停
//继续:
XXXXX ->ResumeThread(); //继续
//执行完毕再终止:
DWORD dwRetVal = WaitForSingleObject(mythread->m_hThread, INFINITE);
//终止:
TerminateThread(XXXXX->m_hThread, 0); //停止线程、
XXXXX = NULL;//清除缓存
// 线程ChildThread1
UINT ChildThread1(LPVOID Param)
{
//子线程1
CMFC_CZDlg* pDlg = (CMFC_CZDlg*)Param; //参数传入
CButton* pButton;
pButton = (CButton*)(pDlg->GetDlgItem(IDC_CHECK_COLOR));
int flage_color = pButton->GetCheck();
pButton = (CButton*)(pDlg->GetDlgItem(IDC_CHECK_SHAPE));
int flage_shape = pButton->GetCheck();
pButton = (CButton*)(pDlg->GetDlgItem(IDC_CHECK_GRAIN));
int flage_grain = pButton->GetCheck();
/*图片个数检索、图资源PIC_x + IO_x的参数*/
vector<CImage> VecPIC_x = { pDlg->PIC_1, pDlg->PIC_2, pDlg->PIC_3, pDlg->PIC_4, pDlg->PIC_5, pDlg->PIC_6, pDlg->PIC_7, pDlg->PIC_8 }; //图
vector<int> VecIO_x = { pDlg->IO_1, pDlg->IO_2, pDlg->IO_3, pDlg->IO_4, pDlg->IO_5, pDlg->IO_6, pDlg->IO_7, pDlg->IO_8 }; //IO出口
int label = 0; //分类标签
int num = 0;
for (size_t i = 0; i < 8; i++)
{
if (!VecPIC_x[i].IsNull() && VecIO_x[i] != 0)
{
num++;
label = num;
}
else
{
break;
}
}
CString NUM;
NUM.Format(_T("%d"), label);
pDlg->MessageBox(NUM, _T("图片_IO的个数,即为多少类别"));
/*
图片有了,
检索方式选择
【
输入图VecPIC_x[i] ——CImage、
输入标签号label(i个)——int、
输入出口VecIO_x[i] ——int
返回分类模型
】
*/
if (label > 0)
{
// 线程开启
pDlg->flag_thresh == true;
// 按钮不能再碰
pDlg->DISABLE_IO(IDC_BUTTON_11, IDC_BUTTON_18);
pDlg->DISABLE_IO(IDC_BUTTON_21, IDC_BUTTON_28);
pDlg->DISABLE_IO(IDC_BUTTON_31, IDC_BUTTON_38);
pDlg->DISABLE_IO(IDC_BUTTON_41, IDC_BUTTON_48);
pDlg->DISABLE_IO(IDC_BUTTON_51, IDC_BUTTON_58);
pDlg->DISABLE_IO(IDC_BUTTON_61, IDC_BUTTON_68);
pDlg->DISABLE_IO(IDC_BUTTON_71, IDC_BUTTON_78);
pDlg->DISABLE_IO(IDC_BUTTON_81, IDC_BUTTON_88);
pDlg->GetDlgItem(IDC_BUTTON_1_Open_CAMERA)->EnableWindow(FALSE);
pDlg->GetDlgItem(IDC_BUTTON_2_COLOCT)->EnableWindow(FALSE);
pDlg->GetDlgItem(IDC_BUTTON_3_IO_SETTING)->EnableWindow(FALSE);
pDlg->GetDlgItem(IDC_CHECK_COLOR)->EnableWindow(FALSE);
pDlg->GetDlgItem(IDC_CHECK_SHAPE)->EnableWindow(FALSE);
pDlg->GetDlgItem(IDC_CHECK_GRAIN)->EnableWindow(FALSE);
pDlg->GetDlgItem(IDC_BUTTON_7_RESET_ALL)->EnableWindow(FALSE);
pDlg->GetDlgItem(IDC_BUTTON_5_START)->EnableWindow(FALSE);
for (size_t i = IDC_BUTTON_RESET_1; i <= IDC_BUTTON_RESET_8; i++)
{
pDlg->GetDlgItem(i)->EnableWindow(FALSE);
}
for (size_t i = 0; i < 5; i++)
{
Sleep(2000);
pDlg->MessageBox(_T("循环中"));
}
if (flage_color && flage_shape && flage_grain || !flage_color && !flage_shape && !flage_grain)
{
pDlg->MessageBox(_T("111"), _T("检索方式"));
/*
图像识别子程序
如果已经有图片库,从图片库读取图 + 标签 + IO,如果没有就采集图片
是否重新训练模型的判断
*/
/*——————————*/
}
else if (flage_color && flage_shape && !flage_grain)
{
pDlg->MessageBox(_T("110"), _T("检索方式"));
}
else if (flage_color && !flage_shape && flage_grain)
{
pDlg->MessageBox(_T("101"), _T("检索方式"));
}
else if (flage_color && !flage_shape && !flage_grain)
{
pDlg->MessageBox(_T("100"), _T("检索方式"));
}
else if (!flage_color && flage_shape && flage_grain)
{
pDlg->MessageBox(_T("011"), _T("检索方式"));
}
else if (!flage_color && flage_shape && !flage_grain)
{
pDlg->MessageBox(_T("010"), _T("检索方式"));
}
else if (!flage_color && !flage_shape && flage_grain)
{
pDlg->MessageBox(_T("001"), _T("检索方式"));
}
}
else
{
pDlg->MessageBox(_T("【没有图片资源】、【检查是否设置IO出口】"));
return 0;
}
return 1;
}
MFC——为按钮添加图片(资源位图、开关指示灯颜色等)
方法:
直接调用SetBitmap; CButton pButton->SetBitmap(hBitmap);
使用CButtonST控件;
使用CDC;
使用CBitmapButton;
CBitmapButton作为MFC的控件类,具体使用如下:
首先添加按钮控件,将属性Owner Draw设为True,按钮ID: IDC_BUTTON1
添加位图资源ID: IDB_BITMAP_CLOSE 和 IDB_BITMAP_RED(资源添加bitmap自己定义名字和ID)
在对话框类中添加private成员变量: CBitmapButton m_button; bool LedFlag;
在初始化函数OnInitDialog里添加图片加载:
第一步:使用CBitmapButton::LoadBitmaps装载各种状态的图片
第二步:再用SubclassDlgItem关联到想要的按钮,
第三步:使用CBitmapButton::SizeToContent函数使按钮适合图片大小。注意Loadbitmaps一定要在关联到按钮之前进行!
为按钮控件添加单击事件处理函数,输入如下代码:
按理来说,写上m_ctrlButton.LoadBitmaps(图片ID);就可以了,可是这样做之后,发现按键了没反应。无意中将对话框最小化再还原,发现图片变了。所以实际上是没有进行刷新导致的。在后面加上m_button.Invalidate()就可以了。
运行程序
MFC——纯ALT读取图(静态和动态)
//静态————————————————————方法一(综合):
/*CImage读取静态图*/
//【第一步:CImage加载图片】
CImage Image;
Image.Load(_T("test.jpg"));
if (Image.IsNull())
{
MessageBox(_T("没加载成功"));
}
//【第二步:CRect获取控件范围】
CRect rect;//定义矩形类
GetDlgItem(IDC_STATIC_CAMERA_SHOW)->GetClientRect(&rect);//将窗口矩形选中到picture控件上
//【第三步:CDC】
/*
利用StretchBlt缩小图片时有时会出现颜色失真。解决步骤如下:
1、先把目标DC (也就是 HDC(或CDC) hDestDC) ::SetStretchBltMode (hDestDC, HALFTONE); //调整图片缩放平均颜色
2、调用一下 ::SetBrushOrgEx(hDestDC, 0, 0, NULL); //设置刷子起始点(可用可不用)
3、最后调用 CImage 的 StretchBlt //Image.Draw(pDC->m_hDC, rect);
*/
CDC *pDC = GetDC();//获取对话框控件
pDC = GetDlgItem(IDC_STATIC_CAMERA_SHOW)->GetDC(); // 获取picture控件DC
SetStretchBltMode(pDC->m_hDC, HALFTONE);//调整图片缩放平均颜色
//SetBrushOrgEx(pDC->m_hDC, 0, 0, NULL);//设置刷子起始点(可用可不用)
Image.Draw(pDC->m_hDC, rect);
//静态——————————————————————————方法二
//从资源中加载图片(不调整大小)
CBitmap bitmap;
//加载指定位图资源 Bmp图片ID
bitmap.LoadBitmap(IDB_BITMAP2);
//获取对话框上的句柄 图片控件ID
CStatic *p = (CStatic *)GetDlgItem(IDC_STATIC_CAMERA_SHOW);
//设置静态控件窗口风格为位图居中显示
p->ModifyStyle(0xf, SS_BITMAP | SS_CENTERIMAGE);
//将图片设置到Picture控件上
p->SetBitmap(bitmap);
//动态————————————————————-————
(只读取bmp图(为了增加对bmp格式的理解),else读取bmp\jpg等)加载动态图步骤:
1.先定义打开文件对话框, 通过它获取bmp图片, 其中dlg.DoMal() == IDOK表示按下确认按钮, 实现后面操作.如果你学过C#就会发现它的OpenFileDialog控件与这个有些类似.
2.然后, 获取读取文件的路径和后缀, 确保其为bmp时执行读取图片信息,
在"https://wenku.baidu.com/view/c955d0fdfab069dc50220147.html"中, 我曾详细讲述过如何读取bmp图片,
这里也是二进制读取文件, 读取其文件头(BITMAPFILEHEADER)、信息头(BITMAPINFOHEADER)、获取其位图数据.
3.最后显示图像到Picture控件中, 并通过GetClientRect函数获取矩形区域, 显示图像.
代码:
//打开文件 定义四种格式的文件bmp gif jpg tiff
CString filter;
filter = "所有文件(*.bmp,*.jpg,*.gif,*tiff)|*.bmp;*.jpg;*.gif;*.tiff| BMP(*.bmp)|*.bmp| JPG(*.jpg)|*.jpg| GIF(*.gif)|*.gif| TIFF(*.tiff)|*.tiff||";
CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, filter, NULL);
//按下确定按钮 dlg.DoModal() 函数显示对话框
if (dlg.DoModal() == IDOK)
{
//打开对话框获取图像信息
CString BmpName = dlg.GetPathName(); //获取文件路径名 如D:\pic\abc.bmp
CString EntName = dlg.GetFileExt(); //获取文件扩展名
EntName.MakeLower(); //将文件扩展名转换为一个小写字符
if (EntName.Compare(_T("bmp")) == 0)
{
//定义变量存储图片信息
BITMAPINFO *pBmpInfo; //记录图像细节
BYTE *pBmpData; //图像数据
BITMAPFILEHEADER bmpHeader; //文件头
BITMAPINFOHEADER bmpInfo; //信息头
CFile bmpFile; //记录打开文件
//以只读的方式打开文件 读取bmp图片各部分 bmp文件头 信息 数据
if (!bmpFile.Open(BmpName, CFile::modeRead | CFile::typeBinary))
return;
if (bmpFile.Read(&bmpHeader, sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER))
return;
if (bmpFile.Read(&bmpInfo, sizeof(BITMAPINFOHEADER)) != sizeof(BITMAPINFOHEADER))
return;
pBmpInfo = (BITMAPINFO *)new char[sizeof(BITMAPINFOHEADER)];
//为图像数据申请空间
memcpy(pBmpInfo, &bmpInfo, sizeof(BITMAPINFOHEADER));
DWORD dataBytes = bmpHeader.bfSize - bmpHeader.bfOffBits;
pBmpData = (BYTE*)new char[dataBytes];
bmpFile.Read(pBmpData, dataBytes);
bmpFile.Close();
//显示图像
CWnd *pWnd = GetDlgItem(IDC_STATIC_CAMERA_SHOW); //获得pictrue控件窗口的句柄
CRect rect;
pWnd->GetClientRect(&rect); //获得pictrue控件所在的矩形区域
CDC *pDC = pWnd->GetDC(); //获得pictrue控件的DC
pDC->SetStretchBltMode(COLORONCOLOR);
StretchDIBits(pDC->GetSafeHdc(), 0, 0, rect.Width(), rect.Height(), 0, 0,
bmpInfo.biWidth, bmpInfo.biHeight, pBmpData, pBmpInfo, DIB_RGB_COLORS, SRCCOPY);
}
else
{
//MessageBox(BmpName);
//【第一步:CImage加载图片】
CImage Image;
Image.Load((BmpName));
if (Image.IsNull())
{
MessageBox(_T("没加载成功"));
}
//【第二步:CRect获取控件范围】
CRect rect;//定义矩形类
GetDlgItem(IDC_STATIC_CAMERA_SHOW)->GetClientRect(&rect);//将窗口矩形选中到picture控件上
//【第三步:CDC】
/*
利用StretchBlt缩小图片时有时会出现颜色失真。解决步骤如下:
1、先把目标DC (也就是 HDC(或CDC) hDestDC) ::SetStretchBltMode (hDestDC, HALFTONE); //调整图片缩放平均颜色
2、调用一下 ::SetBrushOrgEx(hDestDC, 0, 0, NULL); //设置刷子起始点(可用可不用)
3、最后调用 CImage 的 StretchBlt //Image.Draw(pDC->m_hDC, rect);
*/
CDC *pDC = GetDC();//获取对话框控件
pDC = GetDlgItem(IDC_STATIC_CAMERA_SHOW)->GetDC(); // 获取picture控件DC
SetStretchBltMode(pDC->m_hDC, HALFTONE);//调整图片缩放平均颜色
//SetBrushOrgEx(pDC->m_hDC, 0, 0, NULL);//设置刷子起始点(可用可不用)
Image.Draw(pDC->m_hDC, rect);
}
}
MFC——字符、字符串、数值等之间的转换
int转CString:
CString str;
int a = 1;
str.Format(_T("%d"), a);
MFC——改变控件大小
/*
对话框的控件尺寸调整
第一步:WM_size消息生成OnSize函数-在函数中添加Invalidate(TRUE);刷新防止原有边缘的残留
第二步:构建全局变量CRect m_rect;
第三步:构建并再当前类的头文件声明子函数void CMFC_MutipleDlg::ChangeSize(int x, int y, UINT nID)
第四步:OnSize函数调用子函数ChangeSize
*/
//尺寸调整m_rect
CRect m_rect;
void CMFC_MutipleDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
if (nType == 1) return; //如果是窗体最小化则什么都不做
//对每个控件进行调整(dj)
//对每一个控件依次做调整//IDC_OpenCamera
ChangeSize(cx, cy, IDC_STATIC);
ChangeSize(cx, cy, IDC_STATIC1);
ChangeSize(cx, cy, IDC_STATIC2);
ChangeSize(cx, cy, IDC_OpenCamera);
GetClientRect(&m_rect);//将变化后的对话框大小设为旧大小
Invalidate(TRUE);//必须有,放置窗口有残留痕迹
}
//改变控件的子函数(改变大小和位置)
void CMFC_MutipleDlg::ChangeSize(int x, int y, UINT nID) //nID为控件ID,x,y分别为对话框的当前长和宽
{
CWnd *pWnd;
pWnd = GetDlgItem(nID);
if (pWnd != NULL) //判断是否为空,因为在窗口创建的时候也会调用OnSize函数,但是此时各个控件还没有创建,Pwnd为空
{
CRect rec;
pWnd->GetWindowRect(&rec); //获取控件变化前的大小
ScreenToClient(&rec); //将控件大小装换位在对话框中的区域坐标
rec.left = rec.left*x / m_rect.Width(); //按照比例调整空间的新位置
rec.top = rec.top*y / m_rect.Height();
rec.bottom = rec.bottom*y / m_rect.Height();
rec.right = rec.right*x / m_rect.Width();
pWnd->MoveWindow(rec); //伸缩控件
}
}
---------------------
作者:DONG_LIN_2019
来源:CSDN
原文:https://blog.csdn.net/weixin_41275726/article/details/84995723
版权声明:本文为博主原创文章,转载请附上博文链接!