////////////////////////////////////////////////////////////////////////////
//折れ線グラフ作成クラス
//VC6 VC.net2002 にて動作確認
//-------------------------------------------------------
//1024本のグラフ線を引くことができます。
//グラフのサイズ(コントロールの大きさ)を動的に変更できます。
//ダブルバッファリングによりちらつきが起こりません。
//各々の線の色を指定できます。
//バックカラー、バックラインの色を指定できます。
//縦、横、共に0以上の値を入れることにより描画します。
//配列の値により縦の目盛り線を引くことができます。(VLINEで縦の線、NONLINEで線を引かない)
//配列の値に連続したひとつの値を入れることにより、横の目盛り線を引くことができます。
//
//指定されたコントロールIDの描画メソッドを使い、
//2次元配列に入った値でグラフを描画します。
//-------------------------------------------------------
//クラス名 Graph
// Graph(CDialog*pDialog,UINT nID) コンストラクタ
// void SetBackColor(COLORREF BkColor) 背景色の指定
// void SetBaseLineColor(COLORREF BaseLineColor) 背景のラインカラーの指定
// void SetLineColor(int iLineNo,COLORREF LineColor) グラフの色の指定
// void SetData(long HightLimit,long WidthCount,long**lDataBuf,int LineCount) //値の範囲は、縦は0からHightLimitまで、横は0からWidthCountまでです。
// void push_back(int iLineNo,long data) 配列の最後尾に値を追加
// void OnDrow(void) 描画します。
//-------------------------------------------------------
//使いかた
//3本のラインを持つグラフを作成します。その中の1本は縦の目盛り線です。
//このファイルをヘッダーファイル Graph.h として取り込みます。
//
//ダイアログにStaticコントロールを貼り付けます。
//IDがIDC_STATICとします。
//
//○ヘッダーを取り込みます。
//
//#include "Graph.h"
//
//○グローバルなどの領域に次の変数を宣言します。///////////
//
//const int iScale = 1000;//横の分解能です
//const int iMaxlimit = 1000;//縦の最大値です。
//long *w[3];//二次元配列変数
//Graph *g;
//
//○OnInitDialogなどで初期設定を行います。////////////////
//
//w[0]=new long[iScale];//2次元配列の作成
//w[1]=new long[iScale];
//w[2]=new long[iScale];
//g = new Graph(this,IDC_STATIC);//グラフオブジェクトの作成
//
//g->SetBackColor(RGB(255,255,200));//背景色の設定
//g->SetBaseLineColor(RGB(0,0,255));//背景の線の色の設定
//g->SetLineColor(0,RGB(255,0,0));//配列 0 番のラインの色の設定
//g->SetLineColor(1,RGB(0,255,0));//配列 1 番のラインの色の設定
//g->SetLineColor(2,RGB(0,255,255));//配列 2 番のラインの色の設定
//for(int pos=0;pos<iScale;pos++){//2次元配列の初期化
// w[0][pos] = 0;
// w[1][pos] = 0;
// w[2][pos] = NONLINE;//NONLINE:描画しない VLINE:縦の目盛り線を引く
//}
//
//g->SetData(iMaxlimit,iScale,(long**)w,3);//SetData(縦の最大値、横の分解能、値の配列、描画する線の数)
//
//○配列の値を変化させてOnDrowを読み出すとグラフが描画されます。もしくは、
//以下のようにタイマーを使って、流れるグラフも作成できます。
//
//int CGDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
//{
// if (CDialog::OnCreate(lpCreateStruct) == -1)
// return -1;
//
// SetTimer(1015, 500, NULL);//タイマーの作成
// return 0;
//}
//
//
//long p=0;
//long p1=0;
//long step=1;
//long step1=1;
//long LineCount=0;
//void CGDlg::OnTimer(UINT nIDEvent)
//{
// if (nIDEvent == 1015)
// {
// KillTimer(1015);//停止
//
// if(p==0) step=10;
// if(p==1000) step=-10;
// p=p+step;
// g->push_back(0,p);//配列 0 の最後の値に p を追加し、描画する。
//
// if(p1==250) step1=10;
// if(p1==500) step1=-10;
// p1=p1+step1;
// g->push_back(1,p1); //配列 1 の最後の値に p を追加し、描画する。
//
// if(LineCount == 100){
// LineCount=0;
// g->push_back(2,VLINE);//縦ラインを引く
// }else{
// LineCount++;
// g->push_back(2,NONLINE);//描画しない
// }
//
// SetTimer(1015, 10, NULL);;//開始
// }
// CDialog::OnTimer(nIDEvent);
//}
///////////////////////////////////////////////////////////////////////////////////
#define MAXLINE 1024
#define VLINE -1
#define NONLINE -2
class Graph{
private:
CDialog*pDlg;
CWnd* pWnd;
long lHlimit;
long lWCount;
long **lWData;
int iLineCount;
COLORREF cBkColor;
COLORREF cBaseLineColor;
COLORREF cLineColor[MAXLINE];
protected:
POINT GetSize(void){
RECT zRect;
pWnd->GetClientRect( &zRect );
POINT p;
p.x=zRect.right - zRect.left;
p.y=zRect.bottom - zRect.top;
return p;
}
POINT Revers(POINT P){
POINT pO=GetSize();
P.y = pO.y - P.y;
return P;
}
void DrowGraph(CDC*pMDC){
POINT p=GetSize();
int iHight=p.x;
int iWidth=p.y;
float lXStep=(float)iHight/(float)lWCount;
float lYStep=(float)iWidth/(float)lHlimit;
for(int i=0;i<iLineCount;i++){
CPen Pen;
CPen *pTmpPen;
Pen.CreatePen(PS_SOLID,1,cLineColor[i]); //ペンの作成
pTmpPen = pMDC->SelectObject(&Pen);
for(long pos=0;pos<lWCount;pos++){
if(lWData[i][pos]>=0){//配列の値が0以上の場合にはグラフを書く
POINT pS,pE;
pS.x= (long)((float)pos * lXStep);
pS.y= (long)((float)lWData[i][pos] * lYStep);
if(pS.y==0) pS.y=1;
pE.x= (long)((float)(pos+1) * lXStep);
pE.y= (long)((float)lWData[i][pos+1] * lYStep);
if(pE.y==0) pE.y=1;
pMDC->MoveTo(Revers(pS));
pMDC->LineTo(Revers(pE));
}else{
if(lWData[i][pos]==VLINE){//配列の値がVLINEの場合には、縦線を描画
POINT pS,pE;
pS.x= (long)((float)pos * lXStep);
pS.y= 0;
if(pS.y==0) pS.y=1;
pE.x= (long)((float)pos * lXStep);
pE.y= iHight;
if(pE.y==0) pE.y=1;
pMDC->MoveTo(Revers(pS));
pMDC->LineTo(Revers(pE));
}
}
}
pMDC->SelectObject(pTmpPen); //ペンを戻す
Pen.DeleteObject();
}
}
public:
Graph(CDialog*pDialog,UINT nID){
pDlg=pDialog;
pWnd=pDlg->GetDlgItem(nID);
cBkColor=RGB(255,255,255);
cBaseLineColor=RGB(0,0,0);
for(int pos=0;pos<MAXLINE;pos++) cLineColor[pos] = RGB(0,0,0);
}
void SetBackColor(COLORREF BkColor){cBkColor = BkColor;}
void SetBaseLineColor(COLORREF BaseLineColor){cBaseLineColor = BaseLineColor;}
void SetLineColor(int iLineNo,COLORREF LineColor){cLineColor[iLineNo] = LineColor;}
void SetData(long HightLimit,long WidthCount,long**lDataBuf,int LineCount);
long**GetData(void);
void push_back(int iLineNo,long data);
void OnDrow(void){
pWnd->SetRedraw(true);//描画の開始
POINT p=GetSize();
int iHight=p.x;
int iWidth=p.y;
CDC* pDC=pWnd->GetDC();//CDCを取得
//描画処理
CBitmap pBitmap;
CClientDC dcScreen(pDlg);
pBitmap.CreateCompatibleBitmap(&dcScreen,iHight,iWidth);//ビットマップを作成
CDC pMDC;
pMDC.CreateCompatibleDC(pDC);// 窓と同じ属性のメモリー領域を確保して
//pB.LoadBitmap(IDB_BITMAP1); // IDB_BITMAP1を選択して
pMDC.SelectObject(&pBitmap);
//ブラシの作成
CBrush Brush;
CBrush *pTmpBrush;
Brush.CreateSolidBrush(cBkColor);
pTmpBrush = pMDC.SelectObject(&Brush);
//ペンの作成
CPen Pen;
CPen *pTmpPen;
Pen.CreatePen(PS_SOLID,1,cBaseLineColor); //ペンの作成
pTmpPen = pMDC.SelectObject(&Pen); //元のペンを一時退避しながら新たなペンの設定
//bitmapのBackColorの塗りつぶし
RECT zRect;
pWnd->GetClientRect(&zRect);
pMDC.Rectangle(&zRect);
//グラフの描画
DrowGraph(&pMDC);
pDC->BitBlt(0, 0,iHight,iWidth,&pMDC,0,0,SRCCOPY); // 確保したメモリー領域にBitmapをコピーしたのち、pDC に表示します。
pMDC.SelectObject(pTmpPen); //ペンを戻す
pMDC.SelectObject(pTmpBrush); //ブラシを戻す
Pen.DeleteObject();
Brush.DeleteObject();
DeleteDC(pMDC);
DeleteObject(pBitmap);
pWnd->ReleaseDC(pDC);//CDCを解放(必ず必要
pWnd->SetRedraw(false);//描画の停止
}
};
void Graph::SetData(long HightLimit,long WidthCount,long**lDataBuf,int LineCount=1){
//delete lWData;
lHlimit = HightLimit;
lWCount = WidthCount-1;
lWData = lDataBuf;
iLineCount = LineCount;
}
long**Graph::GetData(){
return lWData;
}
void Graph::push_back(int iLineNo,long data){
for(long pos=0;pos<lWCount;pos++){
lWData[iLineNo][pos] = lWData[iLineNo][pos+1];
}
lWData[iLineNo][lWCount] = data;
OnDrow();
}
▲トップページ