刘文斌Windows编程大作业.docx
《刘文斌Windows编程大作业.docx》由会员分享,可在线阅读,更多相关《刘文斌Windows编程大作业.docx(18页珍藏版)》请在冰豆网上搜索。
刘文斌Windows编程大作业
武汉轻工大学
Windows编程大作业
题目:
基于MFC的图片浏览器的设计
姓名:
刘文斌。
院系:
数学与计算机学院。
班级:
软件工程1303班。
学号:
1305110050。
老师:
刘文涛。
2015.12.16
一、题目介绍
1、基本要去:
能显示常用图片格式
能实现基本图片操作功能,例如旋转,放大,缩小
界面布局合理、美观;
2、介绍:
基于MFC的图片浏览器,能够打开常用格式的图片,如BMP、JPG等格式文件,能够实现一些基本的操作,如旋转,放大,缩小等功能。
二、系统分析
1、技术分析:
本次的大作业就是利用MFC强大而全面的类库,结合ActiveX控件资源开发一款简单而实用的图片浏览器软件。
本次课程设计制作的图片浏览器是利用Windows系统自带的图片控件控件实现,可以分别通过按钮和菜单实现图片的浏览,放大、缩小、旋转等功能。
所要实现的功能,以及各个控件的功能特点设计软件的流程图。
2、开发工具:
工具:
VisualC++6.0;
3、开发环境:
环境:
Windows环境
4、
程序流程:
三、功能实现
1、基本界面:
2、功能说明:
2.1、打开位图功能;
2.1.1、建立一个单文档:
2.1.2、为单文档对话框添加位图控件:
2.1.3、添加打开位图按钮:
2.1.4:
为打开位图功能添加相应的函数和代码:
打开【MFCClassWizard】,在Classname下选择CShowPicDlg类,ObjectIDs下选择按钮控件的ID:
IDC_Open,在Message下选择BN_CLICKED,然后点击AddFunction按钮,在弹出的对话框内填写OnBtnOpenBmp(这个是函数名),点击OK,然后点击EditCode编辑函数
在打开的ShowPicDlg.cpp文件中OnBtnOpenBmp()位置添加以下代码:
CFileDialogdlg(TRUE,"bmp",".bmp",OFN_HIDEREADONLY,"BMPFiles(*.bmp)|*.bmp||");
if(dlg.DoModal()!
=IDOK)
{
return;
}
m_path=dlg.GetPathName();//获得图片路径
UpdateData(false);//更新路径公共变量
ShowPic();//调用显示图片函数
在头文件ShowPicDlg.h添加CShowPicDlg类需要的函数和成员变量声明
public:
voidCShowPicDlg:
:
ShowPic();
private:
CStringm_path;
RECTrect;
BITMAPbm;
HBITMAPhBitmap;
HDChSrcDC;
HDChDesDC;
CWnd*hwnd;
继续转回ShowPicDlg.cpp文件中,编写ShowPic()函数体,代码如下:
oidCShowPicDlg:
:
ShowPic()
{
if(m_path=="")//判断图片路径是否存在
{
return;
}
hwnd=GetDlgItem(IDC_ShowImg);
hDesDC=hwnd->GetDC()->m_hDC;
hSrcDC=CreateCompatibleDC(hDesDC);
hBitmap=(HBITMAP)LoadImage(AfxGetInstanceHandle(),m_path,IMAGE_BITMAP,0,0,
LR_LOADFROMFILE|LR_CREATEDIBSECTION);
GetObject(hBitmap,sizeof(BITMAP),&bm);
SelectObject(hSrcDC,hBitmap);
hwnd->GetClientRect(&rect);
:
:
SetStretchBltMode(hDesDC,COLORONCOLOR);
:
:
StretchBlt(hDesDC,rect.left,rect.top,rect.right,rect.bottom,hSrcDC,
0,0,bm.bmWidth,bm.bmHeight,+SRCCOPY);
UpdateData(false);
}
打开图片后效果如下:
2.2、对图片进行缩小;
2.2.1:
添加一个缩小图片的功能按钮:
2.2.2:
为缩小功能添加相对应的函数和代码:
Onpaint函数:
voidCShowPicDlg:
:
OnPaint()
{
if(IsIconic())
{
CPaintDCdc(this);//devicecontextforpainting
SendMessage(WM_ICONERASEBKGND,(WPARAM)dc.GetSafeHdc(),0);
//Centericoninclientrectangle
intcxIcon=GetSystemMetrics(SM_CXICON);
intcyIcon=GetSystemMetrics(SM_CYICON);
CRectrect;
GetClientRect(&rect);
intx=(rect.Width()-cxIcon+1)/2;
inty=(rect.Height()-cyIcon+1)/2;
//Drawtheicon
dc.DrawIcon(x,y,m_hIcon);
}
else
{
CDialog:
:
OnPaint();
//更新windows窗口,如果无这步调用,图片显示还会出现问题
CDialog:
:
UpdateWindow();
ShowPic();//重绘图片函数
}
}
显示图片函数;
voidCShowPicDlg:
:
ShowPic()
{
if(m_path=="")//判断图片路径是否存在
{
return;
}
hwnd=GetDlgItem(IDC_ShowImg);
hDesDC=hwnd->GetDC()->m_hDC;
hSrcDC=CreateCompatibleDC(hDesDC);
hBitmap=(HBITMAP)LoadImage(AfxGetInstanceHandle(),m_path,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
GetObject(hBitmap,sizeof(BITMAP),&bm);
SelectObject(hSrcDC,hBitmap);
hwnd->GetClientRect(&rect);
:
:
SetStretchBltMode(hDesDC,COLORONCOLOR);
:
:
StretchBlt(hDesDC,rect.left,rect.top,rect.right,rect.bottom,hSrcDC,0,0,bm.bmWidth,bm.bmHeight,+SRCCOPY);
UpdateData(false);
}
缩小图片函数:
voidCShowPicDlg:
:
Onnarrow()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
rect.left=rect.left+rect.right*0.01;
rect.top=rect.top+rect.bottom*0.01;
rect.right=rect.right*0.98;
rect.bottom=rect.bottom*0.98;
UpdateWindow();
StretchBlt(hDesDC,rect.left,rect.top,rect.right,rect.bottom,hSrcDC,0,0,bm.bmWidth,bm.bmHeight,+SRCCOPY);
}
缩小的核心在于,将位图的左上角的点,和右下角的点进行移动,以达到缩小的效果:
rect.left=rect.left+rect.right*0.01;
rect.top=rect.top+rect.bottom*0.01;
rect.right=rect.right*0.98;
rect.bottom=rect.bottom*0.98;
UpdateWindow();
StretchBlt(hDesDC,rect.left,rect.top,rect.right,rect.bottom,hSrcDC,0,0,bm.bmWidth,bm.bmHeight,+SRCCOPY);
2.3、对图片进行放大;
2.3.1:
添加一个放大图片按钮:
2.3.2:
为放大功能添加相对应的函数和代码:
Onpaint函数和显示图片函数与缩小函数一样;核心显示代码如下:
voidCShowPicDlg:
:
Onmagnify()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
rect.left=rect.left-rect.right*0.012;
rect.top=rect.top-rect.bottom*0.012;
rect.right=rect.right*1.028;
rect.bottom=rect.bottom*1.028;
UpdateWindow();
StretchBlt(hDesDC,rect.left,rect.top,rect.right,rect.bottom,hSrcDC,0,0,bm.bmWidth,bm.bmHeight,+SRCCOPY);
}
放大函数的核心,在于将图片的左上角和图片的右下角的坐标进行移动,以达到放大的效果。
//TODO:
Addyourcontrolnotificationhandlercodehere
rect.left=rect.left-rect.right*0.012;
rect.top=rect.top-rect.bottom*0.012;
rect.right=rect.right*1.028;
rect.bottom=rect.bottom*1.028;
2.4、对图片进行旋转;
2.4.1:
添加一个旋转按钮:
2.4.2:
为旋转功能添加相对应的函数和代码:
图像旋转的实现较为复杂,是本设计中的难点。
旋转有两种思路,一种是像缩放一样,借助于LanImage:
:
Draw()函数,按照旋转要求改变目标区域的水平坐标和垂直坐标,使其与源图像的坐标不同。
但是要使整幅图像都翻转过来,必须对图像的每个像素调用一次Draw()函数。
这样,如果是一幅640×480像素大小的图像,旋转一次就要调用640×480=307200次的Draw()函数,Draw()函数又是调用DrawDibDraw()实现的,而此函数因为涉及到非常复杂的函数调用关系,并不适合进行如此大量次数的调用,如果采用这种方法实现旋转,其执行速度是让人无法忍受的。
因此,要实现旋转,必须在内存中对图像数据的缓冲区先做好变换,然后一次性调用Draw()函数将其绘制在屏幕上。
但是,在内存中进行像素数据的变换,关键之处在于:
对每像素位数不同的图像,必须使用不同的操作。
例如,如果是8位的图片,那么每个像素正好是一个字节,变换时以字节为单位即可;如果是32位的图片,则是4字节一个像素,那么变换时应以4字节为单位;而如果是单色位图,那么8个像素才构成一个字节,此时就必须进行位操作。
下面以8位和32位的图像来说明旋转操作的算法,而需要进行位操作的图像的旋转方法在后面进行详细说明,这里不再赘述。
voidLanImage:
:
Rotate90Clockwise()
{
BYTE*pNewImage=NULL;
intiSrcWidth=m_nWidth;
intiSrcHeight=m_nHeight;
intiSrcRowBytes=m_nPitch;
//计算翻转后一行占用的字节数及数据区的大小
intiNewPitch=(iSrcHeight*m_nBitCount+31)/32*4;//4字节对齐
intiNewImgDataSize=iNewPitch*iSrcWidth;
//为翻转后的数据分配空间
pNewImage=newBYTE[iNewImgDataSize];
switch(m_nBitCount)
{
case8:
//8位图像的翻转
{
intOutPointer=0;
for(inty=0;y{
BYTE*pIn=GetLine(y);
for(intx=0;x{
//下面这两行看起来是做逆时针旋转,但由于DIB是由下到上存
//储图像的,故实际上是顺时针
intOutColumn=y;
intOutRow=iSrcWidth-x-1;
//而这两行注释掉的则正相反,是逆时针的
//intOutColumn=iSrcHeight-y-1;
//intOutRow=x;
OutPointer=OutRow*iNewPitch+OutColumn;
CopyMemory(&pNewImage[OutPointer],&pIn[x],1);
}
}
}
break;
case32:
{
intOutPointer=0;
for(inty=0;y{
BYTE*pIn=GetLine(y);
for(intx=0;x{
//32位时一个像素占四字节宽
intOutColumn=y*4;
intOutRow=iSrcWidth-x-1;
OutPointer=OutRow*iNewPitch+OutColumn;
CopyMemory(&pNewImage[OutPointer],&pIn[x*4],4);
}
}
}
break;
}
……
}
3、窗体设计:
3.1、软件基本页面:
3.2、软件功能页面:
3.3、位图显示区域
4、功能测试【每个功能测试结果,用截图形式】
1、打开位图功能
打开位图之后的效果:
2、缩小功能
缩小之后的效果;
3、放大功能
放大之后的效果:
4、旋转功能
旋转之后的效果:
5、总结
1、对于此次Windows编程大作业,我的题目是比较简单的,需要实现的功能比较简单,但在实现的过程中还是遇到了一些问题,通过此次的大作业,对于MFC编程有了更加深入的了解,对于这学期学习过的课程有了一个系统的回顾,在这过程收获很大。
2、虽然这个题目比较简单,能够实现基本的功能,但是这个图片浏览器小软件依然,存在一些问题,经过不断地优化,解决了一部分问题,但是仍然有些问题没有解决。
问题:
Ø在打开位图时,图片的格式,必须是由Windows输出的标准合适,不能通过直接改文件后缀名以改变文件的格式,这样在打开时会出现问题,不能显示图图片。
Ø由于图片格式的原因,实现的打开格式以BMP格式为主要格式,所有的功能围绕BMP格式进行,打开其他格式文件时,需要对代码进行小部分的修改。
Ø在旋转时,旋转之后的图片依然是位图的长宽比,并没有根据实际的大小显示。
这是一个比较严重的问题,多次修改,但没有达到预想效果。
6、参考文献
1、书籍:
ØvisualC++程序设计应用教程(马石安、魏文平主编)
Ø面向对象程序设计(C++)版
2、网页
Ø
Ø