(一)MFC读取并显示一幅位图图像,并获取鼠标点击位置的像素坐标和灰度值(接上篇博客)

    上篇博客简要介绍了如何利用MFC读取并显示一幅位图图像,并获取鼠标点击位置的像素坐标和灰度值信息,主要包含了对话框的创建和添加程序,代码也在上一页中给了大家,但是并没有详细说明功能,所以在这一节当中主要介绍代码的含义。

一、打开并显示位图图片

(一)程序清单

void Cwj_zuoyeDlg::OnBnClickedOpen()
{
	// TODO: 在此添加控件通知处理程序代码
	//打开文件 
	CString filter = (CString)"图像文件(*.bmp)|*.bmp;*.BMP||";//指明可供选择的文件类型和相应的扩展名
	CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, filter, NULL);  //打开文件

//按下确定按钮 dlg.DoModal() 函数显示对话框
	if (dlg.DoModal() == IDOK)
	{
		//打开对话框获取图像信息
		CString BmpName = dlg.GetPathName();     //获取文件路径名   
		CString EntName = dlg.GetFileExt();      //获取文件扩展名
		EntName.MakeLower();                     //将文件扩展名转换为一个小写字符

		if (EntName.Compare(_T("bmp")) == 0)  //如果是bmp图片则打开显示
		{
			//定义变量存储图片信息
			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();

			//显示图像
			CStatic *pwnd = (CStatic*)GetDlgItem(IDC_STATIC);  //里面的参数是图片控件的ID
			//pwnd->SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
			pwnd->ModifyStyle(0xf, SS_BITMAP);
			pwnd->SetBitmap((HBITMAP)::LoadImage(GetModuleHandle(NULL), BmpName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE));//打开图片


		}
	}
}

(二)函数含义

CString filter = (CString)"图像文件(*.bmp)|*.bmp;*.BMP||";//指明可供选择的文件类型和相应的扩展名
CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, filter, NULL);  //打开文件

其中CFileDialog是MFC当中的一个类,它的构造函数如下:

explicit CFileDialog(BOOL bOpenFileDialog, //TRUE则显示打开对话框,为FALSE则显示保存对话文件对
                                                   话框。
		LPCTSTR lpszDefExt = NULL,      //指定默认的文件扩展名。
		LPCTSTR lpszFileName = NULL,    //指定默认的文件名, 可带上完整的文件路径
		DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,  
                                                // 指明一些特定风格
		LPCTSTR lpszFilter = NULL,      //指明可供选择的文件类型和相应的扩展名。
		CWnd* pParentWnd = NULL,        //为父窗口指针。
		DWORD dwSize = 0,               //OPENFILENAME结构体的大小。
		BOOL bVistaStyle = TRUE         //指定文件对话框的风格,设为TRUE则使用Vista风格的文件对
                                        //话框,否则使用旧版本的文件对话框。
           );

所以上面代码的意思就是打开一个对话框,寻找bmp类型的文件并打开(参数不完整时后面的为默认形式)

相关的链接是https://www.cnblogs.com/kex1n/p/3595800.htmlhttps://blog.csdn.net/grllery/article/details/76234863

//显示图像
CStatic *pwnd = (CStatic*)GetDlgItem(IDC_STATIC);  //里面的参数是图片控件的ID
//pwnd->SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
pwnd->ModifyStyle(0xf, SS_BITMAP);
pwnd->SetBitmap((HBITMAP)::LoadImage(GetModuleHandle(NULL), BmpName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE));//打开图片

SetWindowPos函数的含义如下

BOOL SetWindowPos(const CWnd* pWndInsertAfter,  //窗口的 Z 顺序
                    int x, int y,                 //窗口位置
				    int cx, int cy,                //窗口大小
                    UINT nFlags);                  //选项

参考链接https://www.cnblogs.com/findumars/p/3948315.html

显示部分主要参考https://blog.csdn.net/sundy_2004/article/details/7183600

还有另一种显示方法,这种显示方法会把整个图片框都填充满,也就是说可能拉伸或者收缩图像的大小,图像很可能失去原来的形状,主要用法如下

//显示图像			
CWnd *pWnd=GetDlgItem(IDC_STATIC_PIC); //获得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);

参考程序https://blog.csdn.net/lynn1258/article/details/54376311

该函数具体用法如https://blog.csdn.net/hnu_zxc/article/details/7491366

二、显示像素坐标和灰度值

(一)程序清单

void Cwj_zuoyeDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CRect rect;
	CWnd *pWnd = GetDlgItem(IDC_STATIC);  //图像控件框的ID
	pWnd->GetWindowRect(&rect);
	ScreenToClient(&rect);

	//先获取鼠标相对于屏幕的绝对坐标
	GetCursorPos(&point);
	int temp_x = point.x;   //为了获取灰度值使用
	int temp_y = point.y;
	//然后得到static控件的rect坐标
	CRect pRect;
	pWnd->GetClientRect(&pRect);
	//最后把当前鼠标的坐标转化为相对于rect的坐标(相对坐标)
	pWnd->ScreenToClient(&point);
	int x = point.x;     //相对坐标
	int y = point.y;
	SetDlgItemInt(IDC_EDIT1, x);     //写入坐标值x
	SetDlgItemInt(IDC_EDIT2, y);     //写入坐标值y

	HDC hDC = ::GetDC(NULL);

	COLORREF rgb = ::GetPixel(hDC, temp_x, temp_y);  //后两个参数是屏幕绝对坐标,如果用相对坐标则获取错误的灰度值
	int r = GetRValue(rgb);     //获得灰度分量
	int g = GetGValue(rgb);
	int b = GetBValue(rgb);
	SetDlgItemInt(IDC_EDIT3, r);     //写入灰度分量R
	SetDlgItemInt(IDC_EDIT4, g);     //写入灰度分量G
	SetDlgItemInt(IDC_EDIT5, b);     //写入灰度分量B

	CDialogEx::OnLButtonDown(nFlags, point);
}

(二)程序简述

GetCursorPos()的用法 通常是  :

CPoint cp;

GetCursorPos(&cp);

它获取的是 鼠标相对屏幕的左上角的距离,单位是像素。而对于一个窗口来说,它的消息响应函数的输入参数通常是相对于客户区左上角的距离。

比如说OnLButtonDown(UINT nFlags, CPoint point)的 point参数,就是相对于客户区的左上角而言的。想要把从GetCursorPos()获得的坐标转化成相对于客户区的坐标,要调用ScreenToClient()函数。

主要参考https://www.cnblogs.com/SnailProgramer/p/4175561.html

关于MFC编辑框的读写参考https://blog.csdn.net/c_gyl/article/details/66972310

这基本把主要部分介绍完了,资料整理不易,所以我就以链接的方式包含起来了,否则长篇大论读者可能不喜欢。

关于这部分内容就介绍到这里,后续还有更新请留意

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页