////////////////////////////////////////////////////////////////////////////
//折れ線グラフ作成クラス
//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();
}



▲トップページ