使用基于对话框的MFC应用
一、准备部分
准备如下控件
一个图片控件(picture control),四个按钮,一个文本编辑框(属性设为只读)
为对话框类添加如下成员变量
二、选择图片按钮
在对话框类中的OnPaint函数中,添加如下代码,将图片框背景初始为白色。
//通过ID获取静态图片控件的所有信息
CWnd* pWnd = GetDlgItem(IDC_STATIC);
//targetRect用于选择一个矩形区域,记录了其坐标,长、宽等信息
CRect rect;
//获取句柄指向控件区域的Rect赋给rect
pWnd->GetClientRect(&rect);
//获取该控件的图像描述表,让其与CDC设备关联
CDC* pDc = pWnd->GetDC();
//绘制背景背板
//使用笔刷
CBrush brush(RGB(255, 255, 255));
//将笔刷设置给pDc
pDc->SelectObject(&brush);
//绘制矩形
pDc->Rectangle(rect);
//回收绘图设置所占用空间
ReleaseDC(pDc);
为文本编辑框添加值变量(我这里已经添加过了)
同时为对话框添加两个函数,其实现如下:
void CMFCApplication1Dlg::adjustImage(CWnd* pWnd, CImage image)
{
//targetRect用于选择一个矩形区域,记录了其坐标,长、宽等信息
CRect rect;
//获取句柄指向控件区域的Rect赋给rect
pWnd->GetClientRect(&rect);
//获取该控件的图像描述表,让其与CDC设备关联
CDC* pDc = pWnd->GetDC();
//绘制背景背板
CBrush brush(RGB(255,255,255));
pDc->SelectObject(&brush);
pDc->Rectangle(rect);
//设置对要绘图片缩放的方式
//窗口句柄,缩放方式
SetStretchBltMode(pDc->m_hDC, STRETCH_HALFTONE);
//记录要绘画的长与宽
int width = image.GetWidth();;
int height = image.GetHeight();
//如果图片长或宽大于控件区域,就需要调整
if (width > rect.Width() || height > rect.Width()) {
float xScale = (float)rect.Width() / (float)width;//x轴缩放倍数
float yScale = (float)rect.Height() / (float)height;//y轴缩放倍数
float ScaleIndex = (xScale <= yScale ? xScale : yScale);//谁更小用谁,以防备出界
width =(int)(image.GetWidth() * ScaleIndex);
height = (int)(image.GetHeight() * ScaleIndex);
}
//更新rect区域,为了尽量将区域确定在控件中间
rect = CRect(CPoint(rect.CenterPoint().x - width/2,rect.CenterPoint().y-height/2), CSize(width, height));
//用来放缩并绘制矩形
//若绘图已绘制会返回0
//此处使用的是让原图片拷贝到目标位图
//窗口句柄,绘图区域,缩放方式
image.StretchBlt(pDc->m_hDC, rect, SRCCOPY);
//回收绘图设置所占用空间
ReleaseDC(pDc);
}
void CMFCApplication1Dlg::splitAddress()
{
// TODO: 在此处添加实现代码
//倒着寻找相同的字符
int index = address.ReverseFind('\\');
//Right将address中字符从右侧开始数的括号中的x(最大个数)个字符赋给m_str
m_str = address.Right(address.GetLength() - index-1);
address = address.Left(index+1);
}
随后为“选择图片”按钮添加点击事件
void CMFCApplication1Dlg::OnBnClickedButton4()
{
// TODO: 在此添加控件通知处理程序代码
CImage image;//存储图片
//文件对话框
//基本设置 打开(true)/保存(false) 默认扩展名 默认文件名称 可操作类型 正则表达式配对(符合的才会显示) 父对话框 (一般只用得到这几个)
CFileDialog dlg(true, _T("*.bmp"), NULL, OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
_T("image files (*.bmp;*.jpg;*.png)|*.bmp;*.jpg;*.png|"), NULL);
//设置打开文件对话框的标题名
dlg.m_ofn.lpstrTitle = _T("open Image ");
//等待对话框的最后返回值,不是确认消息则结束
if (dlg.DoModal() != IDOK)
return;
//记录地址
address = dlg.GetPathName();
//切割地址
splitAddress();
//获取图片窗口
CWnd* pWnd = GetDlgItem(IDC_STATIC);
//载入图片到image
image.Load(dlg.GetPathName());
//调整图片并绘图
adjustImage(pWnd, image);
UpdateData(FALSE);
}
此时,导入功能就已经完成了。
三、“上一张”及“下一张”按钮
为对话框类再次添加如下函数
//获取当前目录下的所有图片名,此方法找出来的图片是按顺序排列的
void CMFCApplication1Dlg::findFIle()
{
// TODO: 在此处添加实现代码.
CFileFind find;
BOOL result = find.FindFile(address+_T("*.*"));
while (result) {
result = find.FindNextFile();
CString fileName = find.GetFileName();
int index = fileName.Find(_T("."));
CString suffix = fileName.Right(fileName.GetLength()-index-1);
if (suffix == _T("jpg") || suffix == _T("bmp") || suffix == _T("png") || suffix == _T("gif")) {
m_strs.Append(_T(",")+fileName);
}
}
}
现在再次在“选择图片”按钮的点击事件最后添加如下代码
//读取文件加下所有文件
findFIle();
为“上一张”及“下一张”按钮添加点击事件后,添加如下代码
//上一张
void CMFCApplication1Dlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
CString path;
if (address.IsEmpty()) {//没有图片时
MessageBox(_T("没有图片"));
return;
}
int index = m_strs.Find(_T(",")+m_str);
if ( index == 0) {//第一张
index = m_strs.ReverseFind(',');//找倒数第一个逗号
path = m_strs.Right(m_strs.GetLength() - index - 1);//逗号以右赋值
}
else {//不是第一张
path = m_strs.Left(index);//逗号以左赋值
index = path.ReverseFind(',');//找切割后的值的倒数第一的逗号
path = path.Right(path.GetLength() - index - 1);//逗号以右赋值
}
m_str = path;
path = address+path;
CImage image;
//获取图片窗口
CWnd* pWnd = GetDlgItem(IDC_STATIC);
//载入图片到image
image.Load(path);
//调整图片并绘图
adjustImage(pWnd, image);
UpdateData(FALSE);
}
//下一张
void CMFCApplication1Dlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
CString path;
if (address.IsEmpty()) {//没有图片时
MessageBox(_T("没有图片"));
return;
}
int index = m_strs.Find(_T(",")+m_str);
if (index == m_strs.ReverseFind(',')) {//最后一张
index = m_strs.Find(_T(","),1);//从第二为开始,找正数第二个逗号
if (index == -1)//只有一张图片
return;
path = m_strs.Left(index);//逗号以左赋值
path = path.Right(path.GetLength() - 1);//将切割后的值的第一个逗号以右赋值
}
else {//不是最后一张
path = m_strs.Right(m_strs.GetLength() - index-1);//逗号以右赋值
index = path.Find(_T(","));//找切割后的值的第一个逗号
path = path.Right(path.GetLength() - index - 1);//逗号以右赋值
index = path.Find(_T(","));//找切割后的值的第一个逗号
if (index != -1) {//不是倒数第二个
path = path.Left(index);//逗号以左赋值
}
}
m_str = path;
path = address + path;
CImage image;
//获取图片窗口
CWnd* pWnd = GetDlgItem(IDC_STATIC);
//载入图片到image
image.Load(path);
//调整图片并绘图
adjustImage(pWnd, image);
UpdateData(FALSE);
}
四、自动播放
在对话框类的初始化器,为判断是否自动播放变量初始化。
为上一张和下一张以及自动播放按钮添加控制变量
为自动播放添加点击事件,代码如下
void CMFCApplication1Dlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
if (address.IsEmpty()) {//没有图片时
MessageBox(_T("没有图片"));
return;
}
if (m_isAuto == false) {
//按钮变化
m_isAuto = true;
m_Pre.EnableWindow(FALSE);
m_Next.EnableWindow(FALSE);
m_Auto.SetWindowText(_T("暂停播放"));
//启动定时器
SetTimer(1, 1000, NULL);
}
else {
//按钮变化
m_isAuto = false;
m_Pre.EnableWindow(TRUE);
m_Next.EnableWindow(TRUE);
m_Auto.SetWindowText(_T("自动播放"));
//关闭定时器
KillTimer(1);
}
}
为对话框类添加定时器消息
void CMFCApplication1Dlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//调用“下一张”按钮的函数
OnBnClickedButton3();
CDialogEx::OnTimer(nIDEvent);
}
至此完成了一个图片查看器的基本功能。
注:至于重新调整大小会变白,是因为笔者将背景涂白的部分放入了OnPaint中,OnPaint在每一次窗口重新绘制时,都会调用。此外,本程序只读取了jpg,png,gif,bmp图片,若有需要请自己修改。