应用绘图


说句吧,刚学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.csdn.net/stephen1315/article/details/7476236

打开CFileDialog类的定义,对关键字explicit的功能见http://www.jb51.net/article/41526.htm

另外一个见http://blog.csdn.net/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” 只写打开或建立一个文本文件,只允许写数据
//打开文件一定要加后缀名
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值