MFC 自定义截图功能

之前做的老项目了,摸索了几个小时才搞出来的。

代码资源地址:MFC源代码

按照惯例,先上效果图得意,下图是我的女神詹姆斯的照片,精致的面部轮廓,真心好看,咳咳,扯远了。。。。


使用流程,点击确定,导入女神;选择;点击ROI1或者ROI2,被选择的区域就会另外显示出来。

实现:

简单的MFC项目建立方法,图片的导入与显示不再赘述,相信点进来看本文的都有一定的基础,那就直接捡干货说。

1)绿色选择框的实现  OnLButtonDown消息 OnMouseMove鼠标移动消息 OnLButtonUp消息

绿色选择框的大小实时调整使用橡皮筋实现。

//written by Z_Benny @2018.2.4
void CpictureROIDlg::OnLButtonDown(UINT nFlags, CPoint point)
{

        // TODO:  在此添加消息处理程序代码和/或调用默认值
	CRect cwrect;
	GetDlgItem(IDC_PIC_STATIC)->GetWindowRect(&cwrect); //获取窗体中控件的区域
	ScreenToClient(&cwrect); //转换为相对区域的CRect  
	if(point.x>cwrect.left && point.y>cwrect.top )   //确保按下的坐标在控件区域内   && point.x
	{
		if (m_RectTracker.HitTest(point) < 0)     //如果未击中矩形选择框,重新画选择框
		{
			m_RectTracker.TrackRubberBand(this, point, TRUE);
			m_RectTracker.m_rect.NormalizeRect();   //正规化矩形(关于正规化矩形下面有介绍)

		}
		else           //如果击中矩形选择框
		{
			m_RectTracker.Track(this, point, TRUE);
			m_RectTracker.m_rect.NormalizeRect();   //正规化矩形
			//SendMessage(WM_LBUTTONUP,NULL,NULL);
		}
		//Invalidate(TRUE);   //刷新窗口区域,使得CrectTracker对象重绘到窗口上

	}

	flag = true;
	m_ptOld = m_ptOrigin = point;
//
	//point点的初始原点是程序客户区左上角
	strtPoint = point;

	CString strtPx, strtPy;

	int x = point.x;
	int y = point.y;

	strtPx.Format(_T("%d"), x);
	strtPy.Format(_T("%d"), y);

	m_startPX.SetWindowText(strtPx);
	m_startPY.SetWindowText(strtPy);
	
	//CDialogEx::OnLButtonDown(nFlags, point);
}
void CpictureROIDlg::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO:  在此添加消息处理程序代码和/或调用默认值

	CString strtPx, strtPy;

	int x = point.x;
	int y = point.y;

	strtPx.Format(_T("%d"), x);
	strtPy.Format(_T("%d"), y);

	m_startPX.SetWindowText(strtPx);
	m_startPY.SetWindowText(strtPy);

	if (flag) {
		CDC* pdcpic = m_picture.GetDC();   // 获得DC   
		HDC m_hdc = pdcpic->m_hDC;

		CRect rc2;
		CWnd* pwnd2 = GetDlgItem(IDC_PIC_STATIC);
		pwnd2->GetClientRect(&rc2);   // 获得IDC_ICTURE控件的客户区大小  
		pwnd2->MapWindowPoints(this, &rc2);  // 将坐标转换为对话框窗口的坐标  

		int oldRop = ::SetROP2(m_hdc, R2_NOT);
		// 画线  
		::MoveToEx(m_hdc, strtPoint.x - rc2.left, strtPoint.y - rc2.top, NULL);
		::LineTo(m_hdc, point.x - rc2.left, point.y - rc2.top);
		::MoveToEx(m_hdc, strtPoint.x - rc2.left, strtPoint.y - rc2.top, NULL);
		::LineTo(m_hdc, point.x - rc2.left, point.y - rc2.top);
		
		
		terminatePoint = point;

	
		CvPoint strt;
		CvPoint last;

		strt.x = strtPoint.x ;
		strt.y = strtPoint.y ;

		last.x = terminatePoint.x;
		last.y = terminatePoint.y;

		
		rectangle(srcImage, strt, last, cvScalar(0, 255, 0), 1);

		showImage(srcImage);

		flag = FALSE;

		CDialogEx::OnMouseMove(nFlags, point);
	}

}
void CpictureROIDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO:  在此添加消息处理程序代码和/或调用默认值	
	
	CDialogEx::OnLButtonUp(nFlags, point);
}

2)其中,子函数showImage的实现

void CpictureROIDlg::showImage(Mat img)
{
	int width = img.cols;
	int height = img.rows;

	Mat showImage;
	img.copyTo(showImage);
	CRect rect;
	GetDlgItem(IDC_PIC_STATIC)->GetClientRect(&rect);
	resize(showImage, showImage, Size(rect.Width(), rect.Height()));

	unsigned int displayWidth = rect.Width();
	unsigned int displayHeight = rect.Height();
	unsigned int displayRadio = displayWidth / displayHeight;

	switch (showImage.channels())
	{
	case 1:
		cvtColor(showImage, showImage, CV_GRAY2BGRA);
		break;
	case 3:
		cvtColor(showImage, showImage, CV_BGR2BGRA);
		break;
	default:
		break;
	}
	int pixBytes = showImage.channels()*(showImage.depth() + 1);
	//制作数据头
	BITMAPINFO bitInfo;
	bitInfo.bmiHeader.biBitCount = 8 * pixBytes;
	bitInfo.bmiHeader.biWidth = showImage.cols;
	bitInfo.bmiHeader.biHeight = -showImage.rows;
	bitInfo.bmiHeader.biPlanes = 1;
	bitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bitInfo.bmiHeader.biCompression = BI_RGB;
	bitInfo.bmiHeader.biClrImportant = 0;
	bitInfo.bmiHeader.biClrUsed = 0;
	bitInfo.bmiHeader.biSizeImage = 0;
	bitInfo.bmiHeader.biXPelsPerMeter = 0;
	bitInfo.bmiHeader.biYPelsPerMeter = 0;

	CDC *pDC = GetDlgItem(IDC_PIC_STATIC)->GetDC();
	::StretchDIBits(pDC->GetSafeHdc(), 0, 0,
		rect.Width(), rect.Height(), 0, 0, rect.Width(), rect.Height(),
		showImage.data, &bitInfo, DIB_RGB_COLORS, SRCCOPY);
	ReleaseDC(pDC);
}
Fightting !!!!


  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值