《VC++高级编程》课程 综合作业说明书
成绩 |
---|
电子与信息工程学院
《VC++高级编程》课程*
*综合作业说明书*
题 目 | VC++综合项目 |
---|---|
班 级 | |
学 号 | |
学生姓名 |
2023年6月
一、程序功能与设计思路
整体设计目标:含有文字处理、绘图、图像、音频视频四部分内容各3种以上功能,自己设计一个标志,放在窗口界面上,带动画效果
1、主界面
1. 1主界面实现功能说明如下:
-
菜单项包括文字处理、绘图、图像、音频视频,点击进入各个功能界面
-
动画显示个人信息
1.2界面效果显示:
1.3 主界面设计思路:
首先创建一个基于对话框的对话框的MFC应用程序,然后在资源里添 加五个菜单栏和四个对话框并将其对应连接起来,在主对话框菜单栏中 添加四个菜单选项与四个子对话框链接,以实现点击菜单项跳出对应的 对话框。然后在主对话框中添加一个shockwaveflash控件以实现在主 界面播放设计好的flash动画。
其功能结构如下:
2、文字处理
2.1 文字实现功能说明如下:
-
菜单项包括文字镂空、文字旋转、颜色渐变、倾斜文字,点击菜单项将显示各个功能。
-
文字镂空:在对话框中显示一串字符,字符中间镂空显示。
-
文字旋转:在对话框中显示一串字符,字符循环旋转,并实现空间。视觉效果,且当前字符显示红色,其余字符显示蓝色。
-
颜色渐变:在对话框中显示一串字符,并整体实现颜色渐变。
-
倾斜文字:在对话框中旋转循环显示字体,每个字符串角度相差15度,围成一个圈。
2.2 界面效果显示:
2.3 文字处理功能结构图:
3、绘图工具
3. 1绘图工具实现功能如下:
-
画点
-
画线
-
画椭圆
-
画矩形,矩形内部用渐变颜色填充
-
涂鸦
-
设置画图的线型、线宽
-
设置画图线条的颜色
3. 2功能界而效果显示
3.3 绘图工具功能结构图:
4、图像处理
4. 1图像处理实现功能如下:
-
从本地磁盘打开.bmp文件
-
图片去色
-
浮雕效果
-
颜色拾取
-
轮廓识别
-
对称变换
-
颜色取反
4.2功能界面效果显示
4. 3 图像处理功能结构图:
5、音视频播放
5. 1 音频视频功能实现:
-
从本地磁盘添加音频视频文件
-
双击播放音频视频文件
-
点击播放按钮播放文件
-
点击上一个、下一个选择当前文件的上一个、下一个文件
5. 2 功能界面显示
5.3 音频视频播放功能结构图:
二、相关原理知识介绍
1 、文字处理
1.1文字处理的基本知识
Windows使用了两种主要字体:一种是等宽字体,一种是可变宽字体。同时Windows又定义了三种不同类型的字体:光栅字体(设备相关的点阵图字体)、矢量字体(设备无关的由一系列线段构成的字体)、TrueType字体(设备无关的用线条和样条曲线来定义轮廓的字体),其中TrueType字体可以在进行任何限度的缩放后,而仍然保持良好的字体质量。此外,还有OpenType字体,它也是设备无关的,可以用来定义 手写字体。无论哪种字体,在Windows系统中都是使用TEXTMERIC和LOGFONT两个结构 来进行描述的。在应用中通过这两个结构来获取字体信息,定义显示文字所需要的字体。
1.2文本输出函数
函数名 | 功能 |
---|---|
TextOut | 用当前字体在指定位置处写一个字符串 |
ExTextOut | 用当前字体在矩形区域内写一个字符串 |
TabbedTextOut | 在指定位置写一个字符串 |
DrawText | 在指定矩形中绘制格式化的文本 |
1.3 文字处理的基本步骤
1) 获取设备环境(CDC* pDC)
2) 设置系统字体
——默认字体
——得到当前的字体(部分)信息,以该信息输出
——创建自定义字体,选入设备环境
3) 输出文本(文本输出函数)
1.4 、 设置系统字体的步骤
1) 创建字体对象:CFont font; // font为字体对象
2) 创建字体
CreateFont ()
CreatePointFont
CreateFontlndirect()
CreateFontFontIndirect()
3) 调用成员函数SelectObject将字体选入设备环境:SelectObject (&font);
1.5 、 控制文本的背景色
在设备描述中有两项可以影响背景,一个是背景色,另一个是背景模式。 背景模式可以为透明的(Transparent)或不透明的(Opaque)。缺省为不透明的。 背景模式可用函数SetBkMode来设置,它设置当前的背景模式并返回原来的背景模 式。
函数原型为:int SetBkMode (int nBkMode);
参数nBkMode指定背景模式,其值可以是OPAQUE或者TRANSPARENT;如果值为 OPAQUE,则显示时背景都改为当前背景颜色。如果值为TRANSPARENT,则不改变背景 颜色,此时,任何SetBkColor函数调用都无效
2、简单绘图工具
2.1 绘图的基本方法
实现简单图形的绘制,绘图功能中,有绘制直线、矩形、椭圆、涂鸦等。用到的方法如下:
CPoint MoveTo(int x,int y); //直线起点
CPoint LineTo(int x,int y); //直线终点
BOOL Rectangle(int xl,int yl,int x2,int y2); //绘制矩形
BOOL Ellipse(int xl,int yl,int x2,int y2); //绘制椭圆
涂鸦部分,以鼠标移动的轨迹画线。
同样要用到MouseMove()函数。使起点为鼠标前一个位置,终点为鼠标当前位置,以画直线的方式完成。
对于线型、线宽、颜色的设置,通过使用颜色通用对话框完成。
2.2 绘图时需要用到的设备环境类介绍
设备环境类CDC提供了绘制和打印的全部函数。为了能让用户使用一些特殊的设备 环境,CDC 还派生了 CPaintDC、CClientDC、CWindowDC 和 CMetaFileDC 类。
(l)CPaintDC比较特殊,它的构造函数和析构函数都是针对OnPaint进行的,但 用户一旦获得相关的CDC指针,就可以将它当成任何设备环境(包括屏幕、打印机)指针 来使用。CPaintDC类的构造函数会自动调用BeginPaint,而它的析构函数则会自动调用 EndPainto
(2)CClientDCn能在窗口的客户区(不包括边框、标题栏、菜单栏以及状态栏)中 进行绘图,点(0,0)通常指的是客户区的左上角。而CWindowDC允许在窗口的任意位置中 进行绘图,点(0,0)指整个窗口的左上角。CWindowDC和CClicntDC构造函数分别调用 GetWindowDC和GetDC,但它们的析构函数都是调用ReleaseDC函数
2.3 CRect类常用的成员函数
成员函数 | 功能说明 |
---|---|
int Width() const; | 返回矩形的宽度 |
int Height)) const; | 返回矩形的高度 |
CSize Size() const; | 返回矩形的大小,CSize中的cx和cy成员分别表示矩 形的宽度和高度 |
CPoint& TopLeft(); | 返回矩形左下角的点坐标 |
CPoint& BottomRight(); | 返回矩形右下角的点坐标 |
CPoint CenterPoint() const; | 返回CRect的中点坐标 |
BOOL IsRectEmpty() const; | 如果一个矩形的宽度或高度是0或负值,则称这个矩形 为空,返回TRUE |
BOOL IsRectNull() const; | 如果一个矩形的上、左、下和右边的值都等于0,则返 回 TRUE |
BOOL PtInRect( POINT point) const; | 如果点point位于矩形中(包括点在矩形的边上),则返 回 TRUE |
void SetRect( int x1, int y1, int x2, int y2 ); | 将矩形的各边设为指定的值,左上角点为(x1,y1),右下 角点为(x2,y2) |
void SetRectEmpty(); | 将矩形的所有坐标设置为零 |
void NornializeRect(); | 使矩形符合规范 |
void OffsetRect( int x, int y );void OffsetRect( POINT point);void OffsetRect( SIZE size ); | 移动矩形,水平和垂直移动量分别由x、y或point、size 的两个成员来指定 |
2.4、画笔和画刷
画笔是Windows应用程序中用来绘制各种直线和曲线的一种图形工具,它可分为 修饰画笔和几何画笔两种类型。在这两种类型中,几何画笔的定义最复杂,它不但有修 饰画笔的属性,而且还跟画刷的样式、阴影线类型有关,通常用在对绘图有较高要求的 场合。而修饰画笔只有简单的几种属性,通常用在简单的直线和曲线等场合。
一个修饰画笔通常具有宽度、风格和颜色三种属性。画笔的宽度用来确定所画的 线条宽度,它是用设备单位表示的。默认的画笔宽度是一个像素单位。画笔的颜色确定 了所画的线条颜色。画笔的风格确定了所绘图形的线型,它通常有实线、虚线、点线、 点划线、双点划线、不可见线和内框线等七种风格。
画刷用于指定填充的特性,许多窗口、控件以及其他区域都需要用画刷进行填充 绘制,它比画笔的内容更加丰富。
画刷的属性通常包括填充色、填充图案和填充样式三种。画刷的填充色和画笔颜 色一样,都是使用COLORREF颜色类型,画刷的填充图案通常是用户定义的8 x 8位图, 而填充样式往往是CDC内部定义的一些特性,它们都是以HS_为前缀的标识。
3、图像处理
3.1 、 使用的CDC类的位图函数来输岀图像。
BOOL StretchBit(int x,int y,int nWidth,int nHeight,CDC* pSrcDC,int xSrc,int ySrc,int nSrcWidth,int nSrcHeight,DWORD dwRop);
x, y :表示目标矩必区域左上角的x,y坐标点;
nWidth, nlleight:表示目标设备中绘制位图的宽度和高度;
pSrcDC :表示源设备上下文对象指针;
xSrc, ySrc:表示源设备上下文的起点x, y轴坐标;
nSrcWidth, nSrclIeight:表示需要复制的位图宽度和高度;
dwRop:表示光栅操作代码。
COLORREF GetPixel( int x, int y) const; //返回坐标点的颜色值。
COLORREF SetPixel( int x, int y, COLORREF crColor); //设置的颜色值
BYTE GetRValue(DWORD rgb ); //获取一个疏色值的RGB各个分量:
BYTE GetGValue(DWORD rgb);
BYTE GetBWlue(DWORD rgb);
3.2 、 获取鼠标位置的颜色值
获取某一点的颜色只要得到当前鼠标的设备环境CDC类对象即可,因为调用CDC类的GetPixel方法可获取某一点的颜色值。
VC提供了三个宏,用于获取某一颜色的红、绿、蓝三基色。
1)GetRValue 宏 该宏用于获取指定颜色的红颜色值。
2)GetGValue 宏 该宏用于获取指定颜色的绿颜色值。
3)GetBValue 宏 该宏用于获取指定颜色的蓝颜色值。
BYTE GetRValue (DWORD rgb ) ;rgb标识一个颜色值。返回值:指定颜色的红色值。
BYTE GetGValue (DWORD rgb ) ;rgb标识一个颜色值。返回值:指定颜色的绿色值。
BYTE GetBValue (DWORD rgb ) ;rgb标识一个颜色值。返回值:指定颜色的蓝色值。
3.3 GetPixel 和 SetPixel 介绍
1)GetPixel 方法
该方法用于获取某一点的颜色值。
语法:COLORREF GetPixel ( int x, int y ) const;
COLORREF GetPixel( POINT point ) const;
参数:x、y> point标识坐标点。
返回值:坐标点的颜色值。
2)SetPixel 方法
该方法用于设置某一点的颜色值。
语法:COLORREF SetPixel ( int x, int y, COLORREF crColor );
COLORREF SetPixel( POINT point, COLORREF crColor );
参数:x、y、point标识坐标点。crColor标识设置的颜色值。
返回值:坐标点实际显示的颜色值。
3.4、与位图相关的方法
表1 位gCBitmap类的主要方法
方法 | 描述 |
---|---|
LoadBitmap | 从应用程序的可执行文件中加载指定文件名或ID的位图资源 |
LoadOEMBitmap | 加载一个Windows预定义位图 |
LoadMappedBitmap | 建立一个映射的位图 |
CreateBitmap | 用指定的宽度、高度和位模式初始化依赖于设备的内存位图 |
CreateBitmapIndirect | 用IpBitmap向的结构中指定的寛度、高度和位模式初始化位图 |
CreateCompatibleBitmap | 初始化一个与pDC指定的设备上下文兼容的位图 |
CreateDiscardableBitmap | 用一个可丢弃、与指定设备兼容的位图初始化对象 |
SetBitmapBits | 用IpBits指定的位置设置位图的位值 |
GetBitmapBits | 得到位图的位值 |
SetBitmapDimension | 设置位图的高度和宽度并且返回前一个位图的维数 |
GetBitmapDimension | 获取位图的宽度和高度 |
4、音频视频播放
需要使用WMP控件来完成播放音频视频文件的功能。对话框中还要使用到列表框。列表框的部分函数如下:
int AddString(LPCTSTR Ipszltem); //添加列表项
int DeleteString(UINT nlndex); //删除列表项
void GetText(int nIndex,CString& rString) const;//获取某列表项字符串
int GetCount(); //获取列表项总数
参数Ipszltem表示添加的字符串,nlndex表示索引值。添加与删除两个函数成功调用时返回列表项在列表框中的索引,错误时返回LB_ERR。参数rString用来存放列表项的文本。
三、设计方法及步骤
1、首先启动VS2010创建一个基于对话框的应用程序。
然后在资源中添加四个菜单栏,分别将ID号改为IDR_MANUMAIN、IDR_MANUWORD、IDR_MANUDRAW、IDR_MANUIMG、IDR_MANUWMP,并将住对话框与IDR_MANUMAIN连接起来,在菜单栏里添加文字处理、简单绘图、图像处理、音频/视频播放四个菜单项。接着添加四个对话框,标题分别改为文字处理、简单绘图、图像处理、音频视频播放,将ID号对应设为IDD_WORDDLG、IDD_DRAWDLG、IDD_IMGDLG、IDD_WMPDLG,并将其与对应的菜单项连接起来。然后将给四个对话框添加对话框类,给主菜单的四个子菜单添加消息响应函数,并调用对应的对话框,将四个子对话框设为无模式对话框,使点击主菜单的四个子菜单弹出对应的对话框。
对话框的ID号及对应的菜单栏如下:
ID | 标题 | MENU 的 ID |
---|---|---|
IDD_ZHJ_DIALOG | ZHJ | IDR_MANUMAIN |
IDD_WORDDLG | 文字处理 | IDR_MANUWORD |
IDD_DRAWDLG | 简单绘图 | IDR_MANUDRAW |
IDD_JMGDLG | 图像处理 | IDR_MANUIMG |
IDD_WMPDLG | 音频视频播放 | IDR_MANUWMP |
给对话框添加类:选中对话框点击右键,选择添加类,然后进入如下对话框,填入相应的类名,点击“完成”。
添加代码如下:
首先在中添加四个对话框类的头文件
点击查看代码
#include "DrawDlg.h"
#include "ImagDlg.h"
#include "WmpDlg.h"
#include "WordDlg.h"
然后给主对话框的子菜单添加对应的消息响应函数,代码如下:
点击查看代码
void CZHJDlg::OnWord()
{
// TODO: 在此添加命令处理程序代码
CWordDlg *pDlg=new CWordDlg;
pDlg->Create( IDD_WORDDLG);
pDlg->ShowWindow(SW_NORMAL);
}
void CZHJDlg::OnDraw()
{
// TODO: 在此添加命令处理程序代码
CDrawDlg *pDlg=new CDrawDlg;
pDlg->Create(IDD_DRAWDLG);
pDlg->ShowWindow(SW_NORMAL);
// DrawDlg dig;
// dlg.DoModal();
}
void CZHJDlg::OnImg()
{
// TODO: 在此添加命令处理程序代码
CImagDlg *pDlg=new CImagDlg;
pDlg->Create(IDD_IMGDLG);
pDlg->ShowWindow(SW_NORMAL);
}
void CZHJDlg::OnWmp()
{
// TODO: 在此添加命令处理程序代码
CWmpDlg *pDlg=new CWmpDlg;
pDlg->Create(IDD_WMPDLG);
pDlg->ShowWindow(SW_NORMAL);
}
2、利用flash制作一个flash动画,
打开主对话框,点击右键选择添加ActiveX控件,选择ShockwaveFlashObject控件,点击确定。如下图
然后右击控件,添加变量,弹出对话框如下,添加变量名点击确定即可;
系统将自动为其添加一个CShockwaveflash类,接着在:CZHJApp的OnInitDialog()函数中添加如下代码:
点击查看代码
CString str=_T("res\\LOGO.swf);//此处路径为相对路径,素材要提前放在此路径下的文件夹中
flasher. LoadMovie(0,str);
flasher.Play();
点击运行即可显示是界面LOG的动画效果。
3、文字处理
首先进入资源视图,添加个位图资源如下图所示,点击导入;
代码如下:
点击查看代码
BOOL CWordDlg::OnEraseBkgnd(CDC* pDC)
{
//TODO:在此添加消息处理程序代码和/或调用默认值
CBitmap bitmap;//构建位图对象
bitmap.LoadBitmap(IDB_BITMAP2);//加载位图
CDC dcCompatible;//创建和前DC兼容的DC
dcCompatible.CreateCompatibleDC(pDC);
BITMAP bmp;
bitmap.GetBitmap(&bmp);
dcCompatible.SelectObject(&bitmap);
CRect rect;
GetClientRect(&rect);
//pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY);
pDC->StretchBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
return TRUE;
//return CDialogEx::OnEraseBkgnd(pDC);
}
然后添加四个菜单项,修改其对应的ID值,如下.:
名称 | *ID* |
---|---|
文字镂空 | ID_Loukong |
文字旋转 | ID_Xuanzhuan |
颜色渐变 | ID_Jianbian |
倾斜文字 | ID_Qingxie |
然后给各个菜单项添加对应的消息映射函数,代码如下:
点击查看代码
// WordDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "ZHJ.h"
#include "WordDlg.h"
#include "afxdialogex.h"
#include <math.h>
int m;
bool bdraw=true;
int fontsize[10];
DWORD col[10],m_nRed,m_nGreen,m_nBlue;
int posx[10];
float Alpha,Cosine,Taille=40,Midx=100,Alpha1,I_Alpha,Decal=0.5;
//double ;
void CWordDlg::OnLoukong()
{
m=0;
Invalidate();
}
void CWordDlg::OnXuanzhuan()
{
m=1;
SetTimer(1,50,NULL);
Invalidate();
}
void CWordDlg::OnJianbian()
{
m=2;
Invalidate();
}
void CWordDlg::OnQingxie()
{
m=3;
Invalidate();
}
在CWordDIg::OnPaint()函数中添加一个Switch选择语句,根据m的值选择执行相应的消息响应程序。然后给CWordDlg类添加消息响应函数CWordDlg::OnTimer(UINT_PTR nIDEvent) {}在函数中添加代码,使m=l或m=2时调用此函数实现定时刷新重绘屏幕以实现颜色渐变及空间旋转地效果。相应代码如下:
void CWordDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CDialog::OnPaint()
CDC *pDC=GetDC();
switch(m)
{
case 0:
{
CFont mFont;
VERIFY(mFont.CreateFont(
45, // nHeight
30, // nWidth
0, // nEscapement
0, // nOrientation
FW_HEAVY, // nWeight
FALSE, // bItalic
FALSE, // bUnderline
0, // cStrikeOut
ANSI_CHARSET, // nCharSet
OUT_DEFAULT_PRECIS, // nOutPrecision
CLIP_DEFAULT_PRECIS, // nClipPrecision
DEFAULT_QUALITY, // nQuality
DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily
_T("宋体"))); // lpszFacename
CPen pen(PS_SOLID,2,RGB(255,0,0));
pDC->SelectObject(&pen);
pDC->BeginPath();
CFont* pOldFont=pDC->SelectObject(&mFont);
pDC->TextOut(100,100,L"计算机学号姓名000");
pDC->EndPath();
pDC->StrokePath();
mFont.DeleteObject();
pDC->SelectObject(pOldFont);
}
break;
case 1:
{
CString str[10]={L"计",L"算",L"机",L"学",L"号",L"姓",L"名"};
pDC->SelectStockObject(NULL_BRUSH);
pDC->SetBkMode(TRANSPARENT);
CFont font;
CBrush brush;
CPen pen;
Alpha=5;
I_Alpha=0.05;
if(bdraw)
{
for(int i=0;i<10;i++)
{
font.CreatePointFont(fontsize[i],L"宋体");
CFont* oldfont=pDC->SelectObject(&font);
pDC->SetTextColor(col[i]);
pDC->TextOut(posx[i],posx[i],str[i]);
pDC->SelectObject(oldfont);
font.Detach();
}
}
}
break;
case 2:
{
SetTimer(0,300,NULL);
CFont font;
font.CreatePointFont(500,L"黑体",pDC);
CFont* pOldFont=pDC->SelectObject(&font);
//创建输出字符串.
CString str(L"222计算机学号姓名!222");
//设置字体颜色
pDC->SetTextColor(RGB(m_nRed,m_nGreen,m_nBlue));
//输岀字体
pDC->TextOut(50,100,str);
pDC->SelectObject(pOldFont);
ReleaseDC(pDC);
}
break;
case 3:
{
CRect rcClient;
GetClientRect (rcClient);
//创建输出字符串.
CString str (_T ("333"));
//输出透明红色字体
pDC->SetBkMode (TRANSPARENT);
pDC->SetTextColor(RGB (255,0,0));
CFont font;
LOGFONT stFont; //字体定义结构
//设置字体格式
memset(&stFont, 0, sizeof(LOGFONT));
stFont.lfHeight=MulDiv(14, -pDC->GetDeviceCaps(LOGPIXELSY), 72);
stFont.lfWeight=FW_NORMAL;
stFont.lfClipPrecision=CLIP_LH_ANGLES;
wcscpy_s(stFont.lfFaceName,L"宋体");
//每隔15度输出字符串
for (int nAngle=0; nAngle<3600; nAngle+=150)
{
//设定新的旋转角度
stFont.lfEscapement=nAngle;
//创建字体并选进设备场景
font.CreateFontIndirect(&stFont);
CFont* pOldFont=pDC ->SelectObject(&font);
//输出字体
pDC->TextOut(rcClient.left + rcClient.Width()/2,rcClient.top + rcClient.Height()/2,str);
//原来字体
pDC->SelectObject(pOldFont);
font.DeleteObject();
}
//CDC* pDC = GetDC(); //获得设备上下文
//CFont m_font;
////pDC->SetBkMode(TRANSPARENT); //设置背景透明
//CRect m_rect;
//GetClientRect(m_rect); //获得客户区域
//pDC->FillRect(m_rect,NULL); //填充区域
//pDC->SetViewportOrg(m_rect.Width()/2,m_rect.Height()/2); //设置圆点
//for (int i = 1;i< 360;i+=18)
//{
// m_font.CreateFont(-14,-10,i*10,0,600,0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_ROMAN,L"宋体"); //创建字体
// pDC->SelectObject(&m_font); //选入字体
// pDC->SetTextColor(RGB(255-i,i*50,i)); //设置文本颜色
// pDC->TextOut(0,0,L"计算机学号姓名!");//输出文本
// m_font.DeleteObject();
//}
break;
}
}
}
点击查看代码
void CWordDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if(m==2)
{
if(m_nRed<=255)
m_nRed+=20;
else if(m_nRed == 255)
m_nRed = 0;
else
m_nRed= 255;
if(m_nGreen>=255)
m_nGreen -= 20;
else if(m_nGreen == 0)
m_nGreen = 255;
else
m_nGreen = 0;
if(m_nBlue<=255)
m_nBlue += 20;
else if(m_nBlue==255)
{m_nBlue = 0;}
else
{m_nBlue = 255;}
Invalidate();//重画文字
}
else if(m==1)
{
//KillTimer(1);
//Alpha=5;
//I_Alpha=0.05;
//Alpha=Alpha-I_Alpha;
for(int i=0;i<10;i++)
{
Alpha+=10;
if(Alpha>=360)
Alpha=Alpha-360;//转满一圈角度归零
Alpha1=Alpha+Decal*i;
Cosine=cos(Alpha1);
fontsize[i]=(Taille+3*Cosine)*9;
posx[i]=Midx+100*sin(Alpha1)+100;
col[i]=RGB((127+Cosine*80+50),0,(127+Cosine*10+50));
}
bdraw=TRUE;
Invalidate();
//SetTimer(1,500,NULL);
}
else
{
KillTimer(0);
KillTimer(1);
}
CDialog::OnTimer(nIDEvent);//改变文字的rgb值
}
4、简单绘图工具
首先给绘图的菜单栏中添加两个主菜单“绘图”和“设置”,然后在其对应的子菜单中添加菜单项如下图,更改其ID号如表所示。
名称 | *ID* |
---|---|
点 | ID_DOT |
直线 | ID_LINE |
矩形 | ID_RECTANGLE |
椭圆 | ID_ELLIPSE |
涂鸦 | ID_TUYA |
直线 | ID_Xuanzhuan |
线宽/线型 | ID_LINEWIDTH |
颜色 | ID_COLOR |
给对应的菜单项添加消息响应函数,代码如下:
void CDrawDlg::OnDot()
{
// TODO: 在此添加命令处理程序代码
m_nDrawType=1;
}
void CDrawDlg::OnLine()
{
// TODO: 在此添加命令处理程序代码
m_nDrawType=2;
}
void CDrawDlg::OnRectangle()
{
// TODO: 在此添加命令处理程序代码
m_nDrawType=3;
}
void CDrawDlg::OnEllipse()
{
// TODO: 在此添加命令处理程序代码
m_nDrawType=4;
}
void CDrawDlg::OnTuya()
{
// TODO: 在此添加命令处理程序代码
m_nDrawType=5;
}
添加消息响应函数OnMouseMove().OnLButtonDown(),Onl.ButtonUp(),在头文件中添加需要用到的变量,在OnMouseMove()、OnLButtonUp()和OnLButtonUp()。函数中添加相应的代码,以实现简单的点、线、椭圆、矩形、涂鸦以及矩形内部填充色的颜色渐变功能。
代码如下:
1)头文件DrawDlg. h中
#pragma once
#include "atltypes.h"
// CDrawDlg 对话框
class CDrawDlg : public CDialog
{
DECLARE_DYNAMIC(CDrawDlg)
public:
CDrawDlg(CWnd* pParent = NULL); // 标准构造函数
virtual ~CDrawDlg();
// 对话框数据
enum { IDD = IDD_DRAWDLG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnDot();
afx_msg void OnLine();
afx_msg void OnRectangle();
afx_msg void OnEllipse();
afx_msg void OnTuya();
afx_msg void OnLinewidth();
afx_msg void OnColor();
private:
unsigned int m_nDrawType;
CPoint m_ptOrigin;
unsigned int m_nLineWidth;
int m_nLineStyle;
COLORREF m_clr;
protected:
HCURSOR m_Hcursor;
CPoint m_pOld;
bool m_bDraw;
public:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseHover(UINT nFlags, CPoint point);
};
- DrawDlg.cpp 中
void CDrawDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_ptOrigin=point;
if (m_nDrawType==5)
{
SetCursor(m_Hcursor);
m_bDraw=TRUE;
m_pOld=point;
SetCapture();
CRect rect;
GetClientRect(&rect);
ClientToScreen(&rect);
ClipCursor(rect);
}
CDialog::OnLButtonDown(nFlags, point);
}
void CDrawDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CClientDC dc(this);
CPen pen(m_nLineStyle,m_nLineWidth,m_clr);//设置画笔
dc.SelectObject(&pen);//选择画笔
CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));//NULL_BRUSH 调 用 GetStockObject函数创建透明画刷
dc.SelectObject(pBrush);
switch(m_nDrawType)
{
case 1:
dc.SetPixel(point,m_clr);
break;
case 2:
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
break;
case 3:
{
int m=(point.x-m_ptOrigin.x)/20;
int n=(point.y-m_ptOrigin.y)/20;
for(int i=20;i>=0;i--)
{
for(int j=20;j>=0;j--)
{
CBrush brush;
point.y=m_ptOrigin.y+n*j;
point.x=m_ptOrigin.x+m*i;
brush.CreateSolidBrush(RGB(i* 12,j* 12,255));
dc.FillRect(CRect(m_ptOrigin.x,m_ptOrigin.y,point.x,point.y),&brush);
brush. DeleteObject();
dc.Rectangle(CRect(m_ptOrigin,point));
}
}
}
break;
case 4:
dc.Ellipse(CRect(m_ptOrigin,point));
break;
case 5:
{
m_bDraw=FALSE;
ReleaseCapture();
ClipCursor(NULL);
}
break;
}
CDialog::OnLButtonUp(nFlags, point);
}
//捕获鼠标移动的动作,以进行绘图
void CDrawDlg::OnMouseHover(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if(m_bDraw)
{
CClientDC dc(this);
CPen pen(m_nLineStyle,m_nLineWidth,m_clr);// 设置画笔;
dc.SelectObject(&pen);
dc.MoveTo(m_pOld);
dc.LineTo(point);
m_pOld=point;
}
CDialog::OnMouseHover(nFlags, point);
}
接着利用MFC提供的CColorDialog类创建一个颜色对话框实现画笔颜色的选择,添加消息响应函数OnColor(),并在其中添加如下代码:
void CDrawDlg::OnColor()
{
// TODO: 在此添加命令处理程序代码
CColorDialog dlg;
dlg.m_cc.Flags|=CC_RGBINIT|CC_FULLOPEN;
if(IDOK==dlg.DoModal())
{ m_clr=dlg.m_cc.rgbResult ;}
}
最后类似主对话框与子对话框的连接方式添加一个对话框与菜单项“线型/线宽”连接,并设置为模式对话框。在对话框中添加一个静态文本控件,Caption属性设为“线宽”接着添加一个编辑框,让用户输入设定的线宽,将其ID设置为:IDC_LINE_WIDTH。然后添加一个组框,并将其Caption设置为“线型”,使用默认ID号。接着,在此组框内设置三个单选按钮,保持他们默认的ID值不变,将他们的名称分别设为:实线、虚线、点线。这时对话框资源如图所示。然后将三个按钮设为一组。此时,设置子菜单的线型线宽菜单的消息响应函数中添加如下代码:
DrawDlg.cpp文件前面要加上
#include "SettingDlg.h"
MFC使用类向导为控件关联变量:给编辑框添加变量m_nLineWidth,给单选框添加变量m_nLineStyle。
void CDrawDlg::OnLinewidth()
{
// TODO: 在此添加命令处理程序代码
CSettingDlg dlg;
dlg.m_nLineWidth=m_nLineWidth;
dlg.m_nLineStyle=m_nLineStyle;
if(IDOK==dlg.DoModal())
{
m_nLineWidth=dlg.m_nLineWidth;
m_nLineStyle=dlg.m_nLineStyle;
}
}
运行即可实现用户对线型线宽的设置。
5、图像处理
在对话框中添加两个Picture Control控件,修改ID号为:IDC_PIC、IDC_TEST;然后,添加三个静态文本框,将Caption改为:红、绿、蓝;添加三个编辑框ID号保持不变。
在对话框对应的MENU栏中添加四个菜单项,并给对应的菜单项添加消息响应函数。
Caption | ID | 消息响应函数 | |
---|---|---|---|
浏览 | 打开 | IDOpen | ClmagDlg: :OnOpen() |
特效 | 去色 | ID_QUSE | CImagDlg::OnQuse() |
浮雕 | ID_FUDIAO | ClmagDlg: :OnFudiao() | |
颜色 | 轮廓拾取 | ID_COLOR | ClmagDlg: :OnColor() |
轮廓识别 | ID_LUNKUO | CImagDlg::OnLunkuo() | |
图像变换 | 对称变换 | ID_DUICHEN | CImagDlg::OnDuichen() |
颜色取反 | ID_QUFAN | CImagDlg::OnQufan() |
在头文件ImagDlg. h中添加如下变量:
#pragma once
#include "afxwin.h"
// CImagDlg 对话框
class CImagDlg : public CDialog
{
DECLARE_DYNAMIC(CImagDlg)
public:
CImagDlg(CWnd* pParent = NULL); // 标准构造函数
virtual ~CImagDlg();
// 对话框数据
enum { IDD = IDD_IMGDLG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
public:
CEdit m_red;
CEdit m_green;
CEdit m_blue;
HBITMAP m_Bitmap;
int n;
CStatic m_HBitmap;
CStatic m_test;
afx_msg void OnOpen();
afx_msg void OnQuse();
afx_msg void OnFudiao();
afx_msg void OnColor();
afx_msg void OnLunkuo();
afx_msg void OnDuichen();
afx_msg void OnQufan();
};
在ImagDlg. cpp文件的相对应的消息响应函数中添加代码以实现对应的功能,代码添加如下:
void CImagDlg::OnOpen()
{
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_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);
}
}
}
void CImagDlg::OnQuse()
{
// TODO: 在此添加命令处理程序代码
//显示图像
CWnd *pWnd=GetDlgItem(IDC_PIC); //获得pictrue控件窗口的句柄
CRect rect;
pWnd->GetClientRect(&rect); //获得pictrue控件所在的矩形区域
CDC *pDC=pWnd->GetDC(); //获得pictrue控件的DC
COLORREF m_color;
BYTE r,g,b;
DWORD m_gray;
for(int i=0;i<rect.Width();i++)
{
for(int j=0;j<rect.Height();j++)
{
m_color=pDC->GetPixel(i,j); //获得颜色
r=GetRValue(m_color);
g=GetGValue(m_color);
b=GetBValue(m_color);
m_gray=(int)(0.38*r+0.49*g+0.1*b);//设置灰度颜色值
m_color=RGB(m_gray,m_gray,m_gray);
pDC->SetPixel(i,j,m_color); //用灰度颜色画点
}
InvalidateRect(NULL);
}
}
void CImagDlg::OnFudiao()
{
// TODO: 在此添加命令处理程序代码
CWnd *pWnd=GetDlgItem(IDC_PIC); //获得pictrue控件窗口的句柄
CRect rect;
pWnd->GetClientRect(&rect); //获得pictrue控件所在的矩形区域
CDC *pDC=pWnd->GetDC(); //获得pictrue控件的DC
COLORREF color,nextcolor;
BYTE rl,gl,bl,r2,g2,b2;
for (int i = 1 ;i<rect.Width();i++)
{
for (int j = 1; j< rect.bottom+1;j++)
{
color = pDC->GetPixel(i,j);
nextcolor = pDC->GetPixel(i+1,j+1);
rl = GetRValue(color);
gl = GetGValue(color);
bl = GetBValue(color);
r2 = GetRValue(nextcolor);
g2 = GetGValue(nextcolor);
b2 = GetBValue(nextcolor);
rl=rl-r2+128;
gl=gl-g2+128;
bl=bl-b2+128;
if(rl>255)
rl =255;
else if(rl<0)
rl =0;
if(gl>255)
gl =255;
else if(gl<0)
gl =0;
if(bl>255)
bl =255;
else if(bl<0)
bl =0;
color=RGB(rl,gl,bl);
pDC->SetPixel(i,j,color);
}
}
}
void CImagDlg::OnColor()
{
// TODO: 在此添加命令处理程序代码
n=1;
}
还要准备给IDC_TEST添加变量m_test
void CImagDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CDialog::OnMouseMove(nFlags, point);
if(n==1)
{
CRect rect;
CWnd *pWnd = GetDlgItem(IDC_STATIC);
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); //写入坐标值
SetDlgItemInt(IDC_EDIT2, 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_EDIT1, r); //写入
SetDlgItemInt(IDC_EDIT2, g); //写入
SetDlgItemInt(IDC_EDIT3, b); //写入
CRect m_rect;
CWnd *pWnd1 = GetDlgItem(IDC_TEST);
pWnd1->GetClientRect(&m_rect);
CDC* dc= pWnd1->GetDC();
CBrush m_brush(RGB(r,g,b));
FillRect(m_test.GetDC()->GetSafeHdc(),&m_rect,m_brush);
}
CDialog::OnMouseMove(nFlags, point);
}
void CImagDlg::OnLunkuo()
{
// TODO: 在此添加命令处理程序代码
CWnd* pWnd=GetDlgItem(IDC_PIC);
CDC* pDC=pWnd->GetDC();
pWnd->UpdateWindow();
CRect m_rect;
pWnd->GetClientRect(m_rect);
int nWidth=m_rect.Width();
int nHeight=m_rect.Height();
int x,y;
for(x=0;x<nWidth;x++)
{
for (y=0;y<nHeight;y++)
{
COLORREF m_colorl,m_color2;
m_colorl= pDC->GetPixel(x,y);
m_color2= pDC->GetPixel(x+1 ,y+1);
int rl,gl,b1;
rl = GetRValue(m_colorl);
gl = GetGValue(m_colorl);
b1 = GetBValue(m_colorl);
int r2,g2,b2;
r2 = GetRValue(m_color2);
g2 = GetGValue(m_color2);
b2 = GetBValue(m_color2);
if(rl-r2>50||gl-g2>50||b1-b2>50||r2-rl>50||g2-gl>50||b2-b1>50)
{
pDC->SetPixel(x,y,m_colorl);
}
else
{
pDC->SetPixel(x,y,RGB(255,255,255));
}
}
}
}
void CImagDlg::OnDuichen()
{
// TODO: 在此添加命令处理程序代码
CWnd* pWnd=GetDlgItem(IDC_PIC);
CDC* pDC=pWnd->GetDC();
pWnd->UpdateWindow();
CRect m_rect;
pWnd->GetClientRect(m_rect);
int nWidth=m_rect.Width();
int nHeight=m_rect.Height();
int x,y;
for (y=0;y<nHeight;y++)
{
for (x =0;x<nWidth/2;x++)
{
COLORREF m_colorl,m_color2;
m_colorl= pDC->GetPixel(x,y);
m_color2= pDC->GetPixel(nWidth-x,y);
pDC->SetPixel(x,y,m_color2);
pDC->SetPixel(nWidth-x,y,m_colorl);
}
}
}
void CImagDlg::OnQufan()
{
// TODO: 在此添加命令处理程序代码
CWnd* pWnd=GetDlgItem(IDC_PIC);
CDC* pDC=pWnd->GetDC();
pWnd->UpdateWindow();
CRect m_rect;
pWnd->GetClientRect(m_rect);
int nWidth=m_rect.Width();
int nHeight=m_rect.Height();
int x,y;
for (x=0;x<nWidth;x++)
{
for(y=0;y<nHeight;y++)
{
COLORREF m_color;
m_color= pDC->GetPixel(x,y);
int r,g,b;
r = GetRValue(m_color);
g = GetGValue(m_color);
b = GetBValue(m_color);
r=256-r;
g=256-g;
b=256-b;
pDC->SetPixel(x,y,RGB(r,g,b));
}
}
}
6、音频视频播放
首先在音频视频对话框中添加一个WindowMediaPlay控件和一个ListBox控件,分别用来实现文件列表的添加显示和音频视频媒体的播放。然后添加四个按钮,Caption值分别设为:添加、播放、下一个和上一个。其对应的ID值和消息响应函数名如下:
Caption | ID | 消息响应函数 |
---|---|---|
添加 | IDC_OPEN | CWmpDlg::OnBnClickedOpen() |
播放 | IDC_PLAY | CWmpDlg::OnBnClickedPlay() |
下一个 | IDC_NEXT | CWmpDlg::OnBnClickedNext() |
上一个 | IDC_LAST | CWmpDlg::OnBnClickedLast() |
分别给ListBox和WindowsMediaPlay添加一个变量,如下图所示:
系统将自动生成一个COcxl类
在源文件COcxl.cpp文件中添加如下代码:
#include ”ocxl.h“
IMPLEMENT_DYNCREATE(COcx1, CWnd)
然后在对话框源文件的对应消息响应函数中添加如下代码,以实现从本地添加个媒体文件,并在ListBox中列表显示,双击则播放文件,单击选中点击播放按钮则播放媒体文件,点击上一个或下一个则选中当前媒体文件的上一个或下一个文件。
对应代码如下:
void CWmpDlg::OnBnClickedOpen()
{
// TODO: 在此添加控件通知处理程序代码
CString filter;
filter="所有文件 |*.*||";
CFileDialog flDlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,filter,NULL);
//CFileDialog flDlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"所有文件 |*.*||",this);
if(flDlg.DoModal()==IDOK) //判断用户是否单击OK按钮
{
POSITION pos=flDlg.GetStartPosition();
while(pos!=NULL)
{
m_List.AddString(flDlg.GetNextPathName(pos));
}
}
}
void CWmpDlg::OnLbnDblclkList1()
{
// TODO: 在此添加控件通知处理程序代码
int selIndex = m_List.GetCurSel();//获取当前选择的列表项索引
if(selIndex != LB_ERR) //判断是否有项日被选中
{
//定义一个字符串对象
CString str;
//根据索引获取当前项目的字符串
m_List.GetText(selIndex,str);
m_Avi.put_URL(str);
}
}
void CWmpDlg::OnBnClickedNext()
{
// TODO: 在此添加控件通知处理程序代码
int selIndex = m_List.GetCurSel();//获取当前选择的列表项索引
if(selIndex != LB_ERR) //判断是否有项日被选中
{
//定义一个字符串对象
CString str;
//根据索引获取当前项目的字符串
int index=selIndex+1;
if(index=m_List.GetCount())
index=0;
m_List.GetText(index,str);
m_List.SetCurSel(index);
m_Avi.put_URL(str);
}
}
void CWmpDlg::OnBnClickedLast()
{
// TODO: 在此添加控件通知处理程序代码
int selIndex = m_List.GetCurSel();//获取当前选择的列表项索引
if(selIndex != LB_ERR) //判断是否有项日被选中
{
//定义一个字符串对象
CString str;
//根据索引获取当前项目的字符串
int index=selIndex-1;
if(index=-1)
index=m_List.GetCount()-1;
m_List.GetText(index,str);
m_List.SetCurSel(index);
m_Avi.put_URL(str);
}
}
三、总结及收获体会
通过这次多媒体软件设计,我对文字显示、绘图、图像处理与媒体播放的只是有了进一步的理解和掌握。能够熟练地应用VS2010设计MFC应用程序,并实现其内部各种控件与工具的应用。对MFC提供的各种设备环境类有了进一步的认识,并能熟练应用一些常用的类与内置函数。
然而在设计的过程中我遇到了很多的问题,通过翻阅资料、请教老师和同学最终将一个个问题成功击破。在解决问题的过程中我学到了很多知识,而且增加了很多常识性知识的储备,是我的今后的编程中能够很好的避免一些常识性错误。编程的开始阶段需要添加对话框并设置为无模式对话框,然而在根据所学的只是一步步操作后却在运行的时候出现了问题,百度之后原来是VS2010软件配置的问题,在设计之前首先需要关闭连接器的启用增量链接,否则将会出现栈的溢出导致内存不足的错误。音频视频媒体播放的设计过程中正常添加了WindowsMediaPlay控件,运行后却不能显示,播放文件却可以正常播放,经过反复推敲,和同学讨论发现在设计的时候添加了一个空的Onpain()函数,程序运行后对话框自动重绘,是控件丢失显示。解决方案是删除Onpain()函数。在绘图设计过程中在实现矩形填充颜色的渐变效果的时候,运行结果是边上出现了白色边缘。经过对算法的反复推敲演算后发现在循环体中错误的多执行了一个循环,问题解决后完美的展现了渐变效果。
实验过程中,在发现问题和解决问题的过程中我收获了很多。通过这次设计我的编程能力也得到了很大的提升。在今后的学习中我将更加注重学以致用,学会灵活的应用所学知识实现自己新颖的设计思路,已达到设计能力的进一步提升,成为一个真正的成功的软件工程师!
教师评语: |
---|
教师签名: |
日 期: |