说句吧,刚学C++,也看过不少帖子。MFC庞大而又功能齐全的窗口界面开发将C++应用的淋漓尽致,刚入门是要多下功夫,下面就一点一滴记录这些撸代码的寂寞岁月吧。
本教程摘自:Tigers Works张卫华等编著的《Visual C++程序设计实战演练》.
————————————————————致敬上述编著作者.
一.简单直方图程序.
void CmysdiView::OnDraw(CDC* pDC)
{
CmysdiDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
const int x0=20,y0=10,x1=500,y1=370;
const int N=12,dx=(x1-x0)/N;
int a[N]={172,33,81,266,158,338,67,205,76,205,116,219};
CBrush br;
int i,x;
srand((unsigned)time(NULL)); //随机初始化函数,初始化随机数
pDC->Rectangle(x0,y0,x1,y1); //先用一个白色矩形的方法达到清屏的目的
for(i=0,x=x0;i<N;++i,x+=dx)
{
br.CreateHatchBrush(rand()%6,RGB(rand()%200,rand()%200,rand()%200));
//每个条图采用随机的网纹样式,每个条图的颜色也是随机的。
pDC->SelectObject(&br);
pDC->Rectangle(x,y1-a[i],x+dx,y1);
pDC->SelectStockObject(WHITE_BRUSH);
br.DeleteObject();
}
// TODO: 在此处为本机数据添加绘制代码
}
说明:
1.
HBRUSH CreateHatchBrush(int fnStyle, COLORREF clrref);
//该函数可以创建一个具有指定阴影模式和颜色的逻辑刷子
/*******************************************************************
fnStyle可取:
HS_BDIAGONAL:表示45度向上,从左至右的阴影(/);
HS_CROSS:水平和垂直交叉阴影(+++++);
HS_DIAGCROSS:45度交叉阴影(XXXXX);
HS_FDIAGONAL:45度向下,自左至右阴影(\\\\\\);
HS_HORIZONTAL:水平阴影(-----);
HS_VERTICAL:垂直阴影(|||||)。
cirref:指定用于阴影的刷子的前景色。
*******************************************************************/
//rand()%6的意思是用rand()产生一个随机数在对10取余,得到0-9中间的数
2.
virtual CGdiObject* SelectStockObject( int nIndex )
//把缺省(库存)对象带入设备环境
/************************************************************************
nIndex可取:
BLACK_BRUSH Black brush.
DKGRAY_BRUSH Dark gray brush.
GRAY_BRUSH Gray brush.
HOLLOW_BRUSH Hollow brush.
LTGRAY_BRUSH Light gray brush.
NULL_BRUSH Null brush.
WHITE_BRUSH White brush.
************************************************************************/
// SelectStockObject选择的是系统预定义的GDI对象
// SelectObject选择你自己自定义的的GDI对象,用完记得删除
二.画三维直方图,只不过在矩形条的顶部和右侧各画一个平行四边形,即可产生立体效果。并添加X轴和Y轴的标注。
void CmysdiView::OnDraw(CDC* pDC)
{
CmysdiDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
const int x0=60,y0=60,x1=600,y1=450;
const int N=12,dx=(x1-x0)/N,h=dx/4; //dx为条图宽度,dy为等高线的间隔高度
const int M=10,dy=30;
int a[N]={172,33,81,266,158,338,67,205,76,205,116,219}; //条形图高度数据
CPoint v[4]; //定义CPoint对象数组v来存放平行四边形四个端点的数据
CBrush br;
CString s;
CPen pen(PS_SOLID,2,RGB(0,0,0)),*p_pen; //建立纯黑色画笔
int i,x,y;
#define R rand()%56+200 //所用的灰度值>=200,不至于太暗
BYTE r,g,b;
srand((unsigned)time(NULL));
pDC->Rectangle(x0,y0,x1+h,y1); //选中矩形区域
pDC->MoveTo(x0,y1);
pDC->LineTo(x=x1+3*dx,y1);
pDC->MoveTo(x,y1);
pDC->LineTo(x-20,y1-10);
pDC->MoveTo(x,y1);
pDC->LineTo(x-20,y1+10); //画X轴和Y轴,带俩尖儿
pDC->MoveTo(x0,y0);
pDC->LineTo(x0,y=y0-dx);
pDC->MoveTo(x0,y);
pDC->LineTo(x0-10,y+20);
pDC->MoveTo(x0,y);
pDC->LineTo(x0+10,y+20);
p_pen=pDC->SelectObject(&pen); //用定义的画笔来描绘(加粗)边界
for(i=0,x=x0;i<N;++i,x+=dx)
{
br.CreateHatchBrush(rand()%6,RGB(rand()%200,rand()%200,rand()%200));
pDC->SelectObject(&br);
//这里从左至右画出,后面的图形可以将前面的图形覆盖。
//先画矩形,再画上边的平行四边形,再画右侧的平行四边形
pDC->Rectangle(x,y1-a[i],x+dx,y1);
v[0].x=x+dx;v[0].y=y1-a[i];
v[1].x=v[0].x+h;v[1].y=v[0].y-h;
v[2].x=v[1].x-dx;v[2].y=v[1].y;
v[3].x=v[2].x-h;v[3].y=v[2].y+h;
pDC->Polygon(v,4);
v[2].x=v[1].x;v[2].y=v[1].y+a[i];
v[3].x=x+dx;v[3].y=y1;
//右侧平行四边形有两个端点数据跟上边的相同。
pDC->Polygon(v,4);
pDC->SelectStockObject(WHITE_BRUSH);
br.DeleteObject();
}
pDC->SelectObject(p_pen);
pen.DeleteObject();
pen.CreatePen(PS_DOT,1,RGB(100,100,100)); //水平等高线采用点虚线
p_pen=pDC->SelectObject(&pen);
pDC->SetROP2(R2_MASKPEN);
for(y=y1,i=0;y>y0;++i,y-=dy) //画水平等高线
{
if(y!=y0&&y!=y1)
{
pDC->MoveTo(x0,y);
pDC->LineTo(x1,y);
}
s.Format(_T("%3d"),dy*i);
pDC->TextOutW(10,y-8,s);
}
pDC->SelectObject(p_pen);
pen.DeleteObject();
for(i=0;i<N;++i) //标注Y轴
{
s.Format(_T("%d"),a[i]);
pDC->TextOutW(x0+i*dx+(dx-s.GetLength()*8)/2,y1+4,s);
}
}
1.
/************************************************************************
Format();
//CString类的一个成员函数,它通过格式操作使任意类型的数据转换成一个字符串,格式与printf()相同.
CTring str;
str.Format("%d",value);
//作用是将value转化成10进制类型的数据放于str这个对象中
若编译报错:Initellisense没有与参数列表匹配的重载参数
需改成str.Format(_T("%d"),value);
因为字符串有两种类型:char(*) 型,多用于多字符字节.wchar(*)型,用于unicode字符(默认)
************************************************************************/
2.
BOOL TextOut(
HDC hdc, // 设备描述表句柄
int nXStart, // 字符串的开始位置 x坐标
int nYStart, // 字符串的开始位置 y坐标
LPCTSTR lpString, // 字符串
int cbString // 字符串中字符的个数
);
//该函数用当前选择的字体、背景颜色和正文颜色将一个字符串写到指定位置。
/************************************************************************
* TextOutW()是TextOut()的Unicode版本
* 如果程序中定义了 _UNICODE 编译的时候编译器会自动链接TextOutW()
当Format()没有使用_T()时,注:_T("")是一个宏,定义于tchar.h文件中。作用是将字符串转换为Unicode编码。
而后者是双字节方式,方便处理双字节字符。
pDC->TextOut(0,0,"Hello World!");会有问题,
应该对应pDC->TextOut(0,0,_T("Hello World!"));
************************************************************************/
3.
virtual DWORD GetLength( ) const;
//返回值:返回字符串中的字节计数。
/************************************************************************
此成员函数用来获取这个CString对象中的字节计数。这个计数不包括结尾的空字符。
对于多字节字符集(MBCS),GetLength按每一个8位字符计数;即,在一个多字节字符中的开始和结尾字节被算作两个字节。
************************************************************************/
三.从文件中打开
CFileDialog ofn(TRUE,NULL,NULL,OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST,\
"Chart Files (*.xlcx)|*.xlcx|Worksheet Files (*.xlsx)|*.xlsx|Data Files (*.xlcx;*.xlsx)|*.xlcx");
ofn.DoModal();
FILE *fp=fopen(ofn.GetPathName(),"rt");
int N,*a;
int i,x,y;
CString s;
for(fscanf(fp,"%d",&N),a=new int[N],i=0;i<N;++i);
{
fscanf(fp,"%d",&a[i]);
}
fclose(fp);
1.
CFileDialog::CFileDialog(
BOOL bOpenFileDialog,
LPCTSTR lpszDefExt = NULL,
LPCTSTR lpszFileName = NULL,
DWORD dwFlags = OFN_HIDEREADONLY |OFN_OVERWRITEPROMPT,
LPCTSTR lpszFilter = NULL,
//其他参数省略...
//文件打开和文件存盘对话框
/************************************************************************
bOpenFileDialog:TRUE为打开文件对话框;FALSE为保存文件对话框
lpszDefExt:缺省的扩展名
lpszFileName:缺省显示在文件名组合框的编辑框的文件名,一般可选NULL
dwFlags:对话框风格类型,分别有:
OFN_HIDEREADONLY:隐藏只读选项
OFN_OVERWRITEPROMPT:覆盖已有文件前提
OFN_ALLOWMULTISELECT:允许选择多个文件
OFN_CREATEPROMPT:如果输入的文件名不存在,则对话框返回询问用户是否根据次文件名创建文件的消息框
OFN_FILEMUSTEXIST:只能输入已存在的文件名
lpszFilter:文件筛选类型,它指明可供选择的文件类型和相应的扩展名。参数格式如:
"Chart Files (*.xlc)|*.xlc|Worksheet Files (*.xls)|*.xls|Data Files (*.xlc;*.xls)|*.xlc; *.xls|All Files (*.*)|*.*||";文件类型说明和扩展名间用 | 分隔,同种类型文件的扩展名间可以用 ; 分割,每种文件类型间用 | 分隔,末尾用 || 指明。
************************************************************************/
系统报错
解决1.如果是在解决方案管理器窗口内,右击你的项目“项目”,然后选“属性”(最后一项),再点“配置属性”,是个“+”号,把它展开,然后选“常规”选项卡,倒数第三项“字符集”,选择“使用多字节字符集”。再编译应该就可以了。选自百度百科—-kja910
见http://blog.youkuaiyun.com/stephen1315/article/details/7476236
打开CFileDialog类的定义,对关键字explicit的功能见http://www.jb51.net/article/41526.htm
另外一个见http://blog.youkuaiyun.com/eva1988725/article/details/6300154
出现this function may be unsafe…..etc
见http://jingyan.baidu.com/article/ce436649fd61543773afd32e.html
加上一句话即可
2.
CPropertySheet::DoModal virtual int DoModal();
返回值:如果函数成功则返回IDOK或IDCANCEL;否则返回0或-1。如果此属性表是作为一个向导(参见SetWizardMode)建立的,DoModal返回ID_WIZFINISH或IDCANCEL。
此成员函数用来显示一个模态对话框。其返回值对应于用来关闭对话框的控件的ID。此函数返回后,Windows响应这个对话框,所有的属性页都会被销毁。
而这些对象本身仍然存在。通常,你将在DoModal返回IDOK之后从CPropertyPage对象检取数据。
3.
CString CFileDialog::GetPathName( ) 得到完整的文件名,包括目录名和扩展名如:c:/test/test1.txt
CString CFileDialog::GetFileName( ) 得到完整的文件名,包括扩展名如:test1.txt
4.
FILE *fp= fopen(const char * path,const char * mode);
返回值:文件顺利打开后,指向该流的文件指针就会被返回。如果文件打开失败则返回NULL,并把错误代码存在errno中
mode有下列几种形态字符串:
“r” 以只读方式打开文件,该文件必须存在。
“r+” 以可读写方式打开文件,该文件必须存在。
“w” 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。
“w+” 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
“rt” 只读打开一个文本文件,只允许读数据
“wt” 只写打开或建立一个文本文件,只允许写数据
//打开文件一定要加后缀名