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 
版权声明:本文为博主原创文章,转载请附上博文链接!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值