当前位置: 移动技术网 > IT编程>开发语言>C/C++ > 利用c++实现数值坐标刻度生成,并利用GDI绘制

利用c++实现数值坐标刻度生成,并利用GDI绘制

2018年11月08日  | 移动技术网IT编程  | 我要评论

同洲电子招聘,董文华简历,江苏省青年管理干部学院

给定两个数值如(3001,5020),如何做到均匀地标注刻度?

研究matlab图形刻度会发现,在matlab中,图像无论如何缩放,坐标刻度间隔都是以1,2,5为基数,按照10倍或者0.1倍的幂进行放大或缩小也即,刻度间隔为:

…0.1 0.2 0.5 ; 12 5; 1020 50; 100200 500; 10002000 5000….

负刻度也类似:

…-0.1 -0.2 -0.5 ; -1-2 -5; -10 -20 -50; -100 -200 -500; -1000 -2000 -5000….

\

 

在matlab图像放大中,还会发现,坐标轴刻度个数都在4个到10个之间。当数值超过1000或小于0.001,则会采用科学计数法。

从上面的刻度看,无论正刻度还是负刻度,相邻刻度最大倍数为2.5。如果把绘制的刻度最小个数控制为4,则最大个数为4*2.5=10;这即是为什么matlab绘制的刻度个数为什么不会超出4个到10个这个范围。

根据上面的分析,回到最初的问题,如何计算(3001,5020)均匀刻度,让刻度符合matlab的刻度规律。

首先确定寻找的刻度范围,限制最小刻度数4个,则最大刻度数为10个:

(5020-3001)/4=504.75

(5020-3001)/10=201.9

因而,201.9-504.75之间只有500这个刻度值符合matlab规律。下面是c++实现的刻度生成器clabelgenerator类

labelgenerator.h:

#ifndef _labelgenerator_h
#define _labelgenerator_h
#pragma once

class clabelgenerator
{
public:
    clabelgenerator(void);
    ~clabelgenerator(void);
	bool generatelabel(float x1,float x2,int minlabelnum,int &reallabelnum,float *&label,cstringarray &labelarr,int &order,int _interal=0,int limitorder=3);     // 产生坐标刻度
    cstring stringcutzeros(cstring str);   //  对标注字符串进行去零处理
};
#endif

labelgenerator.cpp:

 

//****************************     labelgenerator.cpp     *****************************
// 包含功能:坐标刻度生成
//
// 作者:    jiangjp2812   1034378054@qq.com
// 单位:    中国地质大学(武汉)
// 日期:    2016/10/01
//*************************************************************************************

#include "stdafx.h"
#include "labelgenerator.h"
#include "math.h"

clabelgenerator::clabelgenerator(void)
{
}


clabelgenerator::~clabelgenerator(void)
{
}

bool clabelgenerator::generatelabel(float x1,float x2,int minlabelnum,int &reallabelnum,
                  float *&label,cstringarray &labelarr,int &order,int _interal,int limitorder) 
                  //  生成坐标刻度
                  //  x1,x2 :需要计算刻度的数值范围,minlabelnum:最小刻度数目。reallabelnum:得到的刻度个数。
                  //  label:刻度的数值位置。labelarr:刻度字符串。order:刻度数值采用科学计数法的阶次
                  //  _interal:指定刻度间隔,默认采用计算值。limitorder:超过此阶次采用科学计数,默认为3
{
    labelarr.removeall();
    float labelinterval=0;                         //  标注间隔

    float leftx=(x2-x1)/((float)minlabelnum*2.5);  // 求标注间隔范围  

    if(leftx<0.000001)                             //  刻度产生失败
        return false;

    float rightx=leftx*2.5;

    int kx=0,ky=0;
    float a=0;

    float done=0;                         // 1,2,5 不断乘以10判断是否在标注间隔范围内,如果在则终止循环,
    float dtwo=0;
    float dfive=0;
    //----------------- 计算x方向大于1刻度 ----------------------------------------------------------------------
    while(a<=(x2-x1))                     // 如果没有找到合适的标度,当超出最大数也终止
    {
        done=1*pow((float)10,(float)kx);  // 1,2,5 不断乘以10判断是否在标注间隔范围内,如果在则终止循环,
        dtwo=2*pow((float)10,(float)kx);
        dfive=5*pow((float)10,(float)kx);
        if( done>=leftx  &&  done<=rightx)
        {
            labelinterval=done;
            break;
        }
        if(dtwo>=leftx && dtwo<=rightx)
        {
            labelinterval=dtwo;
            break;
        }
        if(dfive>=leftx && dfive<=rightx)
        {
            labelinterval=dfive;
            break;
        }
        kx++;
        a=dfive;                          // 每循环一次是1,2,5同时按倍数扩大,即判断的数扩大到a=done
    }
    //-----------  x方向如果没有大于1刻度则计算小于1刻度 --------------------------------------
    kx=0;
    a=1;
    if(labelinterval==0)
    {
        while(a>0.000001)                 // 如果没有找到合适的标度,当小于最小数也终止
        {
            done=1*pow((float)0.1,(float)kx);  // 1,2,5 不断乘以0.1判断是否在标注间隔范围内,如果在则终止循环,
            dtwo=2*pow((float)0.1,(float)kx);
            dfive=5*pow((float)0.1,(float)kx);
            if( done>=leftx  &&  done<=rightx)
            {
                labelinterval=done;
                break;
            }
            if(dtwo>=leftx && dtwo<=rightx)
            {
                labelinterval=dtwo;
                break;
            }
            if(dfive>=leftx && dfive<=rightx)
            {
                labelinterval=dfive;
                break;
            }
            kx++;
            a=done;                           // 每循环一次是1,2,5同时按倍数缩小,即判断的数扩大到a=done
        }	
    }
    //-----------------------------------------------------------------------------------
    if(labelinterval==0 ) return false;
    if(_interal!=0) labelinterval=_interal;  // 如果指定间隔,则使用指定的间隔

    float startx,endx;
    float temstartx/*,temendx*/;

    temstartx=x1/labelinterval-(int)(x1/labelinterval);
    if(temstartx==0)                //  如果x1正好位于刻度上,则其实点从x1开始
    {
        startx=labelinterval*(int)(x1/labelinterval);
    }
    else                            //  如果x1不位于刻度上,则起始点从x1之后某点开始
    {
        if(x1>=0)
            startx=labelinterval*((int)(x1/labelinterval)+1);
        else
            startx=labelinterval*((int)(x1/labelinterval)-1+1);    //  当出现负数时,取整向0靠拢,正半轴需加1,负半轴不需要
    }
    if(x2>=0)
        endx=labelinterval*(int)(x2/labelinterval);
    else 
        endx=labelinterval*((int)(x2/labelinterval)-1);            //  当出现负数时,取整向0靠拢,正半轴需加1,负半轴不需要

    reallabelnum=(endx-startx)/labelinterval+0.5+1; //  真实需要绘制的坐标刻度个数
    //  此处(endx-startx)/labelinterval计算得到的数值应为整数,但浮点型计算得不到精确值
    //  会略小于理论整数,因此需要加上0.5后再取整

    label=new float[reallabelnum];                  //  开辟坐标位置容器

    int valueorder=0,intervalorder=0;               //  采用科学计数法进行刻度标注,绝对值最大值阶数,标注间隔值阶数
    float loop1=labelinterval,loop2=abs(endx);

    if(labelinterval>=1)                            //  求取标注间隔阶次,间隔大于1,正阶
    {
        while(loop1>=10)
        {
            loop1=loop1/10;
            intervalorder++;
        }
    }else if(labelinterval<1)                       //  标注小于1,负阶
    {
        while(loop1<0.1)
        {
            loop1=loop1*10;
            intervalorder++;
        }
    }
    float valueabs=abs(startx)>abs(endx) ? abs(startx) : abs(endx) ;    //  获取最大值,求取阶数

    int limitvmax=pow(10.0,limitorder);
    float limitvmin=pow(10.0,limitorder*-1);
    if(valueabs>=limitvmax)                             //  求取最大刻度值大于1000的阶次,正阶
    {
        while(loop2>=10)
        {
            loop2=loop2/10;
            valueorder++;
        }
    }else if(valueabs<=limitvmin)                      //  求取最大刻度值小于0.001的阶次,负阶
    {
        while(loop2<=0.1)
        {
            loop2=loop2*10;
            valueorder++;
        }
    }

    for(int i=0;i=limitvmax)                   //  如果绝对值最大值阶次大于3,则除以对应阶数量级
        {
            str.format(_t("%.4f"),label[i]/pow(10.0,valueorder));
        }
        else if(valueabs<=limitvmin)                  //  如果绝对值最大值阶次小于-3,则除以对应阶数量级
        {
            str.format(_t("%.4f"),label[i]*pow(10.0,valueorder));
        }

        str=stringcutzeros(str);                  //  对标注字符串进行尾部去零
        labelarr.add(str);
    }

    if(valueorder==0)  order=0;                   //  输出阶次
    if(endx>=limitvmax)  order=valueorder;
    if(endx<=limitvmin) order=-valueorder;

    return true;
}

cstring clabelgenerator::stringcutzeros(cstring str)
        //  对标注字符串进行去零处理
{
    cstring finalstr;        
    finalstr.empty();
    int length=str.getlength();             // 字符串长度
    int pos=0;
    bool isdot=false;
    for(int i=0;i0)
    {
        if(isdot)
            finalstr=str.left(length-1-pos);
        else
            finalstr=str.left(length-1-(pos-1));
    }

    else
        finalstr=str;

    return finalstr;
}


 

类中有两个成员函数

boolgeneratelabel(float x1,float x2,int minlabelnum,int &reallabelnum,float*&label,cstringarray &labelarr,int &order,int _interal=0,intlimitorder=3); // 产生坐标刻度

cstringstringcutzeros(cstring str); // 对标注字符串进行去零处理

generaterlabel函数产生坐标刻度,其中x1,x2是输入的数值,minlabelnum是需要指定的最小刻度个数。如果生成matlab类似刻度则该数值为4,当然也可以设置其他值。reallabelnum是实际得到刻度个数(注意引用变量,通过引用变量把得到的数据输出),label是该处刻度的数值,labelarr是该处刻度对应的字符串,order是采用科学计数法输出的幂值,_interal是指定刻度值,给定初始值为0,即采用matlab相同刻度。如果不想采用此刻度,可以直接指定_interal值,则会采用指定的刻度生成标注值。limitorder是指定的科学计数法限制阶数,超过此阶数采用科学计数法。默认为3,即超过1000则采用科学计数法。

stringcutzeros是去除标注字符串尾部的0。因为生成的标注可能尾部有0,如0.3000或1.0。在matlab中就不会出现这样的显示方式。

函数调用:

int xlabelnum;
float *pxlabel;
cstringarray xlabelarr;
int orderx;
clabelgenerator labelgenerator;3001,5020
bool sucx=labelgenerator.generatelabel(3001,5020,4,xlabelnum,pxlabel,xlabelarr,orderx);   //  产生x刻度和值刻度
if(pxlabel!=null)              //  清空数组
    {
        delete m_pxlabel;
        pxlabel=null;
    }
bool sucy=labelgenerator.generatelabel(200001,5340000,5,xlabelnum,pxlabel,xlabelarr,orderx,0,4);
坐标绘制采用gdi编写,被封装成clabeldrawer类

labeldrawer.h

 

#ifndef labeldrawer_h
#define labeldrawer_h
#pragma once
class clabeldrawer
{
public:
    clabeldrawer(void);
    ~clabeldrawer(void);
public:
    bool drawlabelhor(cdc *pdc,
        int xlabelnum,float *pxlabel,cstringarray &xlabelarr,int xorder,
        float desx1,float desx2,float desy1,float x1,float x2,cstring xtitle,
        bool isupper=true,colorref rgb=rgb(0,0,0));
    bool drawlabelver(cdc *pdc,
        int ylabelnum,float *pylabel,cstringarray &ylabelarr,int yorder,
        float desy1,float desy2,float desx1,float y1,float y2,cstring ytitle,
        bool isleft=true,colorref rgb=rgb(0,0,0));
};
#endif

labeldrawer.cpp

 

 

//****************************     labeldrawer.cpp     *****************************
// 包含功能:坐标刻度绘制(配合clabelgenerator类)
//
// 作者:    jiangjp2812   1034378054@qq.com
// 单位:    中国地质大学(武汉)
// 日期:    2016/10/01
//**********************************************************************************

#include "stdafx.h"
#include "labeldrawer.h"
#include  

clabeldrawer::clabeldrawer(void)
{
}


clabeldrawer::~clabeldrawer(void)
{
}

bool clabeldrawer::drawlabelhor(cdc *pdc,
    int xlabelnum,float *pxlabel,cstringarray &xlabelarr,int xorder,
    float desx1,float desx2,float desy1,float x1,float x2,cstring xtitle,
    bool isupper,colorref rgb)
    //  绘制水平刻度
    //  pdc: 绘图句柄。xlabelnum: 刻度数目。pxlabel:刻度真实数值。xlabelarr:刻度数值对应的字符串。
    //  xorder: 采用科学计数法阶次。desx1,desx2:标注绘制在窗口中的横坐标。desy1:水平刻度在窗口中的纵坐标。
    //  xtitle: 坐标轴名称字符串。isupper:若为true,刻度位于刻度线上方,否则位于刻度线下方
    //  rgb:刻度颜色。
{	
    if(abs(desx2-desx1) <0.0001) return false;
    if(pxlabel==null) return false;

    pdc->setbkmode(transparent);
    pdc->settextcolor(rgb);
    cfont font,fontunit,*oldfont;                   //  创建times new roman字体
    font.createpointfont(100,_t("times new roman"),pdc);
    fontunit.createpointfont(120,_t("times new roman"),pdc);

    cpen pen(0,1,rgb),*oldpen;
    oldpen=pdc->selectobject(&pen);
    float posx,posy;
    oldfont=pdc->selectobject(&font);
    textmetric tm;
    pdc->gettextmetrics(&tm);
    long tw=tm.tmavecharwidth;             // 获取输出字符信息,主要是为了使得短线标注对准字符串中间位置
    long th=tm.tmheight;                   // 用于计算字符相对短线输出位置

    double k=(desx2-desx1)/(x2-x1);
    if(isupper==true)                      //  标注在上边
    {
        pdc->selectobject(&font);
        pdc->settextalign(ta_center | ta_bottom);
        for(int i=0;imoveto(posx,desy1);
            pdc->lineto(posx,desy1-tw);
            pdc->textoutw(posx,desy1-tw-1,xlabelarr.getat(i));
        }

        posx=k*((x1+x2)/2.0-x1)+desx1;
        pdc->selectobject(&fontunit);
        pdc->textoutw(posx,desy1-tw-th,xtitle);    // 绘制x方向坐标单位
    }
    else{                                  //  标注在下边
        pdc->selectobject(&font);
        pdc->settextalign(ta_center | ta_top);
        for(int i=0;imoveto(posx,desy1);
            pdc->lineto(posx,desy1+tw);
            pdc->textoutw(posx,desy1+tw+1,xlabelarr.getat(i));
        }

        posx=k*((x1+x2)/2.0-x1)+desx1;
        pdc->selectobject(&fontunit);
        pdc->textoutw(posx,desy1+tw+th,xtitle);  // 绘制x方向坐标单位
    }

    if(xorder!=0)                               // 绘制x方向阶次
    {
        cfont font1,font2;                            
        font1.createpointfont(100,_t("times new roman"),pdc);
        font2.createpointfont(70,_t("times new roman"),pdc);
        float fontrate=100.0/70.0;
        cstring tenstr("×10"),orderstr;         // ×10字符和阶次字符
        orderstr.format(_t("%d"),xorder);

        if(isupper==true)
        {		
            pdc->selectobject(&font1);	
            pdc->settextalign(ta_bottom | ta_right);	
            pdc->textoutw(desx2-tw/fontrate*2,desy1-tw-th,tenstr);		
            pdc->selectobject(&font2);
            pdc->settextalign(ta_bottom | ta_left);
            pdc->textoutw(desx2-tw/fontrate*2,desy1-tw-th-th/2.0,orderstr);  
        }
        else
        {
            pdc->selectobject(&font1);	
            pdc->settextalign(ta_top | ta_right);	
            pdc->textoutw(desx2-tw/fontrate*2,desy1+tw+th+th/2.0,tenstr);		
            pdc->selectobject(&font2);
            pdc->settextalign(ta_top | ta_left);
            pdc->textoutw(desx2-tw/fontrate*2,desy1+tw+th,orderstr);  
        }
    }
    pdc->selectobject(oldfont);
    pdc->selectobject(oldpen);
    return true;
}

bool clabeldrawer::drawlabelver(cdc *pdc,
    int ylabelnum,float *pylabel,cstringarray &ylabelarr,int yorder,
    float desy1,float desy2,float desx1,float y1,float y2,cstring ytitle,
    bool isleft,colorref rgb)
    //  绘制垂直刻度
    //  pdc: 绘图句柄。ylabelnum: 刻度数目。pylabel:刻度真实数值。ylabelarr:刻度数值对应的字符串。
    //  yorder: 采用科学计数法阶次。desy1,desy2:标注绘制在窗口中的纵坐标。desx1:垂直刻度在窗口中的横坐标。
    //  ytitle: 坐标轴名称字符串。isleft:若为true,刻度位于刻度线左边,否则位于刻度线右边
    //  rgb:刻度颜色。
{
    if(abs(desy2-desy1)<0.0001) return false;
    if(pylabel==null) return false;

    pdc->setbkmode(transparent);
    pdc->settextcolor(rgb);
    cfont font,fontunit,*oldfont;                   //  创建times new roman字体
    font.createpointfont(100,_t("times new roman"),pdc);
    fontunit.createpointfont(120,_t("times new roman"),pdc);

    cpen pen(0,1,rgb),*oldpen;
    oldpen=pdc->selectobject(&pen);
    float posx,posy;
    oldfont=pdc->selectobject(&font);
    textmetric tm;
    pdc->gettextmetrics(&tm);
    long tw=tm.tmavecharwidth;             // 获取输出字符信息,主要是为了使得短线标注对准字符串中间位置
    long th=tm.tmheight;                   // 用于计算字符相对短线输出位置

    int charlength=0;
    for(int i=0;icharlength) charlength=ylabelarr.getat(i).getlength();
    }	

    charlength=charlength+1;

    double k=(desy2-desy1)/(y2-y1);

    if(isleft==true)                      //  标注左边
    {
        pdc->selectobject(&font);
        pdc->settextalign(ta_bottom | ta_right);
        for(int i=0;imoveto(desx1,posy);
            pdc->lineto(desx1-tw,posy);
            pdc->textoutw(desx1-tw-1,posy+th/2.0,ylabelarr.getat(i));
        }

        pdc->settextalign(ta_bottom | ta_center);    //  纵向字体按纵向的bottom和left设置,即和横向颠倒
        posy=k*((y1+y2)/2.0-y1)+desy1;

        logfont logfont;
        fontunit.getlogfont(&logfont);
        logfont.lfescapement =900;
        cfont fontemp;
        fontemp.createfontindirect(&logfont); 
        pdc->selectobject(&fontemp);

        pdc->textoutw(desx1-tw*charlength-tw,posy,ytitle);
    }
    else{

        pdc->selectobject(&font);
        pdc->settextalign(ta_bottom | ta_left);
        for(int i=0;imoveto(desx1,posy);
            pdc->lineto(desx1+tw,posy);
            pdc->textoutw(desx1+tw+1,posy+th/2.0,ylabelarr.getat(i));
        }

        pdc->settextalign(ta_top | ta_center); 
        posy=k*((y1+y2)/2.0-y1)+desy1;

        logfont logfont;
        fontunit.getlogfont(&logfont);
        logfont.lfescapement =900;
        cfont fontemp;
        fontemp.createfontindirect(&logfont); 
        pdc->selectobject(&fontemp);
        pdc->textoutw(desx1+tw*charlength+tw,posy,ytitle);
    }

    if(yorder!=0)
    {
        cfont font1,font2;                             //  创建times new roman字体
        font1.createpointfont(100,_t("times new roman"),pdc);
        font2.createpointfont(70,_t("times new roman"),pdc);
        float fontrate=100.0/70.0;
        cstring tenstr("×10"),orderstr;
        orderstr.format(_t("%d"),yorder);

        if(isleft==true)
        {	
            pdc->selectobject(&font1);	   
            pdc->settextalign(ta_bottom | ta_right);				
            pdc->textoutw(desx1-charlength*tw-tw-tw/fontrate*2,desy2,tenstr);
            pdc->selectobject(&font2);
            pdc->settextalign(ta_bottom | ta_left);
            pdc->textoutw(desx1-charlength*tw-tw-tw/fontrate*2,desy2-th/2.0,orderstr);

        }
        else
        {
            pdc->selectobject(&font1);	   
            pdc->settextalign(ta_bottom | ta_left);				
            pdc->textoutw(desx1+charlength*tw+tw,desy2,tenstr);
            pdc->selectobject(&font2);
            pdc->settextalign(ta_bottom | ta_left);
            pdc->textoutw(desx1+charlength*tw+tw+(tenstr.getlength()+1)*tw,desy2-th/2.0,orderstr);
        }
    }

    pdc->selectobject(oldfont);
    pdc->selectobject(oldpen);
    return true;
}

 

clabeldrawer类中有两个成员函数,drawlabelhor用于绘制水平刻度,drawlabelver用于绘制垂直刻度。函数参数在代码中有说明,这个类必须配合上边的clabelgenerator类使用。下面是使用实例。

首先利用vs生成一个mfc单文档程序,为了方便说明,直接把数据放在了ondraw函数中:

 

void clabeltestview::ondraw(cdc* pdc)
{
	clabeltestdoc* pdoc = getdocument();
	assert_valid(pdoc);
	if (!pdoc)
		return;

	// todo: 在此处为本机数据添加绘制代码

    int labelnum;
    float *plabel=null;
    cstringarray labelarr;
    int order;

    float v1=-0.0005,v2=-0.0003;
    float desx1=100,desx2=500,desy1=100,desy2=500;
    // 生成数值(-0.0005 -0.0003)范围
    clabelgenerator labelgen;
    labelgen.generatelabel(v1,v2,4,labelnum,plabel,labelarr,order);

    clabeldrawer labeldraw;
    // 绘制数值(-0.0005 -0.0003)范围上刻度
    labeldraw.drawlabelhor(pdc,labelnum,plabel,labelarr,order,desx1,desx2,desy1,v1,v2,_t("upper label"));
    // 绘制数值(-0.0005 -0.0003)范围下刻度
    labeldraw.drawlabelhor(pdc,labelnum,plabel,labelarr,order,desx1,desx2,desy2,v1,v2,_t("lower label"),false,rgb(0,0,255));
    // 绘制数值(-0.0005 -0.0003)范围左刻度
    labeldraw.drawlabelver(pdc,labelnum,plabel,labelarr,order,desy1,desy2,desx1,v1,v2,_t("left label"));
    // 绘制数值(-0.0005 -0.0003)范围右刻度
    labeldraw.drawlabelver(pdc,labelnum,plabel,labelarr,order,desy1,desy2,desx2,v1,v2,_t("right label"),false,rgb(255,0,0));
    //  绘制矩形框
    pdc->selectstockobject(null_brush);
    pdc->rectangle(desx1,desy1,desx2,desy2);
 
    v1=30; v2=803;
    desx1=650;desx2=950;desy1=100;desy2=500;
    if(plabel!=null)  delete plabel;
    // 绘制数值(30 803)范围刻度
    labelgen.generatelabel(v1,v2,5,labelnum,plabel,labelarr,order);       
    // 绘制数值(30 803)范围水平上刻度
    labeldraw.drawlabelhor(pdc,labelnum,plabel,labelarr,order,desx1,desx2,desy1,v1,v2,_t("hor axis"),true,rgb(0,0,255));
    pdc->moveto(desx1,desy1); pdc->lineto(desx2,desy1);  
    // 绘制数值(30 803)范围水平上逆向刻度
    labeldraw.drawlabelhor(pdc,labelnum,plabel,labelarr,order,desx2,desx1,desy1+50,v1,v2,_t("reverse hor axis"),true,rgb(0,0,255));
    pdc->moveto(desx1,desy1+50); pdc->lineto(desx2,desy1+50);  

    desx1=700;desx2=1000;desy1=200;desy2=550;   
    // 绘制数值(30 803)范围垂直左刻度
    labeldraw.drawlabelver(pdc,labelnum,plabel,labelarr,order,desy1,desy2,desx1,v1,v2,_t("ver axis"),true,rgb(255,0,255));
    pdc->moveto(desx1,desy1); pdc->lineto(desx1,desy2);  
    // 绘制数值(30 803)范围垂直左逆向刻度
    labeldraw.drawlabelver(pdc,labelnum,plabel,labelarr,order,desy2,desy1,desx1+100,v1,v2,_t("reverse ver axis"),true,rgb(255,0,255));
    pdc->moveto(desx1+100,desy1); pdc->lineto(desx1+100,desy2);  
}
生成的效果如图

\
 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网