⑵ 准备数据
取数据的方法与第一讲取数据的方法是类似的,不同之处主要是:这里的 GetData方法返回一个DataTable对象。
首先,由于引用了SQLDataAdapter类,以及使用ConfigurationManager类从应用程序配置文件 app.config中取连接字符串,在DrawingForm.h文件中添加以下“using namespace”声明,以获得访问这两个类的权限:
using namespace System::Configuration;
using namespace System::Data::SqlClient;
然后,编写GetData方法。代码如下:
public: DataTable^ GetData(String^ selectCommand)
{
try
{
// 指定一个连接字符串。这好比选择路径的方向,如果方向不对,则无法
// 建立通路。对于不同数据库,其连接字符串设置也不同。
String^ connectionString = ConfigurationSettings::AppSettings["ConnectionString"];
// 生成一个基于特定查询、特定数据连接的SqlDataAdapter实例。
SqlDataAdapter^ dataAdapter;
dataAdapter = gcnew SqlDataAdapter(selectCommand, connectionString);
// 实例化 SqlCommandBuilder 来产生SQL更新、插入和删除命令。
gcnew SqlCommandBuilder(dataAdapter);
// 组装一个数据表并绑定到 BindingSource组件。
DataTable^ table = gcnew DataTable();
dataAdapter->Fill(table);
return table;
}
catch (SqlException^)
{
MessageBox::Show("为了运行实例程序, 用一个对于你的系统是有效的连接字符串" + "代替connectionString变量的值。");
this->Close();
}
}
⒉ 取数据
在绘图之前,调用GetData方法从数据库中取绘图所需的数据。在pictureBox1控件的Paint事件中编写以下代码:
// 构造SQL select语句。
String^ selectCommand="select convert(varchar(10),日期,120) as '日期',开盘价,收盘价,成交量,最高价,最低价 from StockList";
// 调用GetData方法返回包含个股(指数)数据的数据表。
DataTable^ table = GetData(selectCommand);
⒊ 绘图形外框
画面分为上下两部分,上方画K线图,下方画条形图。在窗体的上方和下方分别画一个矩形框来容纳K线图和条形图。
由于每一个交易日的K线图和条形图在横向位置应保持一致,因此两个图形外框左上角的横坐标相同,宽度也相同。
在pictureBox1控件的Paint事件处理方法中添加以下代码:
// 为PictureBox控件生成一个Graphics 对象。
Graphics^ formGraphics = e->Graphics;
// 为(股价或指数)K线图画一个矩形框。
System::Drawing::Pen^ penRgn =
gcnew System::Drawing::Pen(System::Drawing::Color::Gray); // 准备画笔。
float rgnk_x=60.0f; // 矩形框:左上角横坐标。
float rgnk_y=60.0f; // 左上角纵坐标。
float rgnk_w=400.0f; // 宽度。
float rgnk_h=160.0f; // 高度。
formGraphics->DrawRectangle(penRgn, Rectangle(rgnk_x,
rgnk_y, rgnk_w, rgnk_h)); //画K线图矩形框。
// 在K线图矩形框下方为(成交量)条形图画一个矩形框。
int sp=20; // 距上方K线图矩形框间隔。
float rgnb_y=rgnk_y+rgnk_h+sp; //矩形框:左上角纵坐标。
float hp=0.6F; // 设置条形图矩形框高度占K线图矩形框高度的比例。
float rgnb_h=rgnk_h*hp; //条形图矩形框高度。
formGraphics->DrawRectangle(penRgn, Rectangle(rgnk_x,
rgnb_y, rgnk_w, rgnb_h)); //画条形图矩形框。
画矩形框时,需要确定矩形的位置和大小。为了便于程序调试、功能扩展和系统维护,它们的值应该用变量来保存。画其他图形或文本也一样。
⒋ 绘标题
在K线图矩形框上方绘标题“上证指数日K线图(2002-04-02 – 2002-06-28)”,其中括号中的起止日期是随画图所用的实际数据的日期动态变化的。在条形图矩形框左上方绘标题“成交量”,如图3所示。
K线图标题在矩形框水平方向应该居中。标题的起始横坐标由下式计算:
标题的起始横坐标=矩形框左上角横坐标+(矩形框宽度-标题宽度)/2

图3 图形外框及标题
代码如下:
// 绘制K线图标题。
int dayCount=table->Rows->Count; // 数据表记录(交易日)数。
String^ topDate=table->Rows[0][0]
->ToString()->Trim(); // 第一条记录的日期。
String^ endDate=table->Rows[dayCount-1][0]
->ToString()->Trim(); // 最后一条记录的日期。
String^ ttlString = "上证指数日K线图"+"("+
topDate+" - "+endDate+")"; // 标题文字。
int fn=14; // 设置标题字号。
System::Drawing::Font^ ttlFont =
gcnew System::Drawing::Font("Arial", fn,
GraphicsUnit::Pixel); // 设置标题字体。
System::Drawing::SolidBrush^ ttlBrush = gcnew
System::Drawing::SolidBrush(System::Drawing::
Color::Black); // 准备标题的实心画笔。
SizeF ttlSize = formGraphics->MeasureString(
ttlString, ttlFont);
float ttlWidth= ttlSize.Width; // 获取标题宽度(像素个数)。
float ttl_x =rgnk_x+(rgnk_w-
ttlWidth)/2; // 为使标题在矩形框水平方向居中,
// 计算标题的起始横坐标。
float ttl_y=rgnk_y-25; // 标题的起始纵坐标。
formGraphics->DrawString( ttlString,ttlFont,
ttlBrush ,ttl_x,ttl_y); // 画标题。
// 绘制条形图标题。
String^ qnttString = "成交量";
float fp_q=0.9F; // 条形图标题字号与K线图标题字号的比例。
System::Drawing::Font^ qnttFont =
gcnew System::Drawing::Font("Arial", fn*fp_q,
GraphicsUnit::Pixel); // 设置字体。
SizeF qnttSize = formGraphics->MeasureString(
qnttString, qnttFont);
float qnttWidth= qnttSize.Width; // 获取标题宽度(像素个数)。
float qntt_x =rgnk_x-qnttWidth; // 标题的起始横坐标。
formGraphics->DrawString( qnttString,qnttFont,
ttlBrush ,qntt_x,rgnb_y); // 画标题。
|