Sep 5, 2008

VC下的走势图绘制函数

对于某些网络股票软件
比如各大门户网上都有的股票查看功能
其中的价格走势图和成交量图的实时绘制是一大亮点
我在VC里实践了下,绘走势图的函数如下
(由于程序里只是读取链表,计算处理结点数据然后绘点连线,耗费CPU时间较少,所以没有用双缓冲方法
如果是绘制位图,一般都要采用双缓冲方法防止刷新时闪屏)


void CDrawRealLine::DrawRealLine()
{
/*----------------------------
*计算画图所需点
*Point[180]--存放所要画的点的数组
*struct bargaininfo_head---价格链表结构体,存放表长度
*struct bargaininfo---价格链表结点
*m_socket---全局通信socket
*-----------------------------*/
idBuffer = m_QueID;//m_QueID查询文本框关联的成员变量
for(int i = 0; i < 180; i++)//Point[180]数组初始化
{
Point[i].num = 0;
Point[i].totalPrice = 0;
Point[i].totalQuality = 0;
}

//接收单个商品价格链表
struct bargaininfo_head *bargaininfo_head = NULL;
bargaininfo_head = getbargainhead(m_socket);
for(i=0;inum;i++)//价格链表头结点保存链表长度信息
{
struct bargaininfo *pInfo = NULL;
pInfo = getbargainnode(m_socket);

strtok(pInfo->time," ");//解析时间,这里""中间是空格
char *tempHour = strtok(NULL,":");
int hour = atoi(tempHour);
char *tempMin = strtok(NULL, ":");
int min = atoi(tempMin);

/*-------------------------------
*有点偷懒了,这里我把时间轴给固定下来,从9:30到15:30,中间均匀分割
*-------------------------------*/
int index = (hour - 9)*30 +min/2-15;//记录点位置
if(index >= 0 && index < 180)
{
Point[index].num++;
Point[index].totalPrice += pInfo->price;
Point[index].totalQuality += pInfo->quality;
}
theApp.index=index;//保存所画点个数
delete(pInfo);
}

//开始画图
CDC *pDC = GetDC();
pDC->SetBkColor(RGB(0,0,5));
CPen yellowpen(PS_SOLID,1,RGB(240,240,0));
pDC->SelectObject(&yellowpen);

//画成交量图
int j;//i用来控制绘图x坐标位置,j用来表示绘图的点脚标
j = 1;
CRect rect;
GetClientRect(&rect);
CPoint client;
client.x=rect.right-240;
client.y=rect.bottom;
i = 40;
for(j = 0; j < 180; j++)
{
pDC->MoveTo(i,client.y-80);
if(Point[j].totalPrice != 0)
{
int temp = client.y-80-(client.y-120)*Point[j].totalQuality/3/60000;
pDC->LineTo(i,temp);
}
i = i + (client.x-80)/180;
}

CPen lightyellow(PS_SOLID,1,RGB(175,175,10));
pDC->SelectObject(&lightyellow);

//画均线图
//先画出第一条
float p1= Point[0].totalPrice/Point[0].num;
if(p1>=theApp.chartstartprice)
{
int m = (p1-theApp.chartstartprice)/theApp.chartstartprice/0.12*(client.y- 120)/3;//点必须是整型
pDC->MoveTo(40,client.y/3);//client.y/3是均线图中间坐标
pDC->LineTo(40+(client.x-80)/180,client.y/3-m);
}
else
{
int n = (p1-theApp.chartstartprice)/theApp.chartstartprice/0.12*(client.y-120)/3;
pDC->MoveTo(40,client.y/3);
pDC->LineTo(40+(client.x-80)/180,client.y/3-n);
}

//再画接下来的线,直接lineto
i=40+(client.x-80)/180;
for(j = 1;j < 180; j++)
{
float p = Point[j].totalPrice/Point[j].num;//要画的平均价格
if(Point[j].totalPrice != 0)
{
if(p>=theApp.chartstartprice)
{
int m = (p-theApp.chartstartprice)
/theApp.chartstartprice/0.12*(client.y-120)/3;
pDC->LineTo(i+(client.x-80)/180,client.y/3-m);
}
else
{
int n = (p-theApp.chartstartprice)
/theApp.chartstartprice/0.12*(client.y-120)/3;
pDC->LineTo(i+(client.x-80)/180,client.y/3-n);
}
}
i+=(client.x-80)/180;
}

pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(0,0,5));
pDC->TextOut(300,5,"正在查询,请稍候...");//坐标300,5处原来有一个红字的提示,上边画完图后直接用背景色盖掉提示。
}

画出来效果图和华西,大智慧等软件效果相当哦,呼呼···只是没有那么全的功能。数据库用的是 MSSQL2000(经不起折腾的数据库,哎),数据库处问题了,没法抓图咯,有兴趣的朋友可以自己去试下。哦,对了,平台是VC6哦。不过.net下也可编译通过吧(不负责任的一句话)

No comments:

Powered By Blogger