MFCでグラフ作成 ChartCtrlLibKit

# MFCでグラフ作成 ChartCtrlLibKit

書き漏らし、勘違い等があれば随時書き込み。

GDI+を利用してグラフを作成するクラスのようです。

> codeprojectに本体があります。
> https://www.codeproject.com/Articles/317712/An-MFC-Chart-Control-with-Enhanced-User-Interface

## 環境

- Windows 10 Pro
- Visual Stuido 2012 Professional

## テストプロジェクトの作成

名前：TestApp

- シングルドキュメント
- 基本クラス->CFormView

あとは適当

<img width="790" alt="0.2588nz9kuvh.png" src="https://qiita-image-store.s3.amazonaws.com/0/76058/a3a5eb4a-e23a-e37e-a30b-4cede1dd50c3.png">

<img width="781" alt="0.lwnqefne0hl.png" src="https://qiita-image-store.s3.amazonaws.com/0/76058/4a3598d0-77a3-6d5c-8bbb-e235ab74cbb4.png">

## Download

**CodeProjectに登録**して、
**Download ChartCtrlLibKitVS2012 (port to VS2012) - 3.2 MB**をダウンロードします。

> https://www.codeproject.com/Articles/317712/An-MFC-Chart-Control-with-Enhanced-User-Interface

<img width="212" alt="0.c6v01e6wdu.png" src="https://qiita-image-store.s3.amazonaws.com/0/76058/6a9bc0c0-6115-c043-b104-f7deccdf4e58.png">

### ダウンロードしたものをプロジェクトに移動

コードファイルと同じところに入れておきます。

<img width="230" alt="0.gwggy894mzv.png" src="https://qiita-image-store.s3.amazonaws.com/0/76058/bdeba5d8-9669-8c55-40d2-734cbb2a4e90.png">

### プロジェクトにファイルを登録

ソリューションエクスプローラーにドラッグアンドドロップでファイルを登録。

<img width="253" alt="スクリーンショット 2018-02-08 13.29.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/76058/49435015-c5de-c717-8284-bea111851246.png">

## プロジェクトの設定

### MFC

Debugは共有、Releaseはスタティック

#### Debug用

構成プロパティ->全般->MFCの使用->共有DLLでMFCを使う

##### ランタイムライブラリ

構成プロパティ->コード生成->ランタイムライブラリ
マルチスレッド デバッグDLL

#### Release用

構成プロパティ->全般->MFCの使用->スタティックライブラリでMFCを使用する

##### ランタイムライブラリ

構成プロパティ->コード生成->ランタイムライブラリ
マルチスレッド

### リンカー

構成プロパティ->リンカー->入力->追加の依存ファイルに以下を追加

```
# Debug用
$(ProjectDir)ChartCtrlLibD2012.lib
# Release用
$(ProjectDir)ChartCtrlLib2012.lib
```

### VC2012用

プロジェクトのプロパティを開いて、
構成プロパティ->C/C++->プリプロセッサ->プリプロセッサの定義に`_VARIADIC_MAX=10`を追記。

## コードを入力

オフィシャルの**How to use it**をベースにコードを記述していきます。

## stdafx.hに追記

```c++:stdafx.h
...
#include <stdlib.h>
#include <tchar.h>
#include <cmath>
#include <vector>
#include <deque>
#include <map>
#include <string>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <tuple>
#include <random>
#include "gdiplus.h"
...
```

### GDI+を使えるようにする。

TestApp.hのCTestAppAppにメンバーを追加。

```c++:TestApp.h
class CTestAppApp : public CWinAppEx
{
private:
    ULONG_PTR m_nGdiplusToken;
...
```

TestApp.cppの`BOOL CTestAppApp::InitInstance()`に追記

```c++:TestApp.cpp
BOOL CTestAppApp::InitInstance()
{
	Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    Gdiplus::GdiplusStartup(&m_nGdiplusToken,
                         &gdiplusStartupInput, NULL);
...
```

TestApp.cppの`int CTestAppApp::ExitInstance()`に追記

```c++:TestApp.cpp
int CTestAppApp::ExitInstance()
{
	Gdiplus::GdiplusShutdown(m_nGdiplusToken);
```

## リソースビューでPictureControlを配置

プロジェクト作成時の状態によって変わりますが、今回は以下の操作。

リソースビュー->TestApp->TestApp.rc->Dialog->IDD_TESTAPP_FORM

デフォルトで配置されているラベルを削除して、ButtonとPicture Controlを配置します。

Picture COntrolのIDを`IDC_STCHARTCONTAINER`に変更して、`Notify`をTrueにしておきます。

<img width="960" alt="0.g4mypkq6agl.png" src="https://qiita-image-store.s3.amazonaws.com/0/76058/af19a3c2-e76d-5daf-ae04-37bdd719fc8a.png">


## メンバの設定

ソリューションエクスプローラーで、TestAppView.hに、include追記

```c++:TestAppView.h
#include "ChartContainer.h"
```

リソースビューで配置したPicutureControlを右クリック->変数を追加(B)...で変数を登録。

- 変数の種類::CChartContainer
- 変数名::m_chartContainer
- コントロールID::IDC_STCHARTCONTAINER

## テストデータ

配置しておいたボタンのスクリプトに以下のように記述してみます。

```c++:TestAppView.cpp

	void CTestAppView::OnBnClickedButton1()
	{
		// TODO: ここにコントロール通知ハンドラー コードを追加します。
		// テスト用データ
		V_CHARTDATAD vData;
		vData.resize(4,PointD(0.0, 0.0));
		vData[0]=	 PointD(0,2);
		vData[1]=	 PointD(1,0);
		vData[2]=	 PointD(2,2);
		vData[3]=	 PointD(3,0);

		V_CHARTDATAD vData2;
		vData2.resize(4,PointD(0.0, 0.0));
		vData2[0]=	 PointD(0,0);
		vData2[1]=	 PointD(1,2);
		vData2[2]=	 PointD(2,0);
		vData2[3]=	 PointD(3,2);

		// ラベル
		string_t label(L"test");
		string_t ylabel(L"y_label");

		// グラフ作成

		int chartIdx = m_chartContainer.AddChart(
			true,			// 表示非表示
			false,			// データのポイントに丸を描くか
			label,			// ラベル
			ylabel, 
			1,				// Y軸の精度
			DashStyle(0),	// 線のスタイル（破線とか）
			5,				// 線幅
			float(1.0),		// カーブの強度
			Color(255, 255, 59, 45),  // 色
			vData,			// データ
			true);			// bRedraw は、グラフコンテナとその子（データラベルとチャート名の凡例）​​の再描画を要求するフラグ

		// 別のグラフを重ねる
		int chartIdx2 = m_chartContainer.AddChart(true,false,label, ylabel, 1, DashStyle(0), 	5, float(0.1), Color(255, 15, 20, 255), vData2, true); 

		string_t path(L"save.jpeg");
		// 画像保存
    m_chartContainer.SaveContainerImage(path);
	}
```

これで完成。
ボタンを押すと、ウィンドウ内に表示されるのと、ファイルが保存されます。

![save.jpeg](https://qiita-image-store.s3.amazonaws.com/0/76058/196390ec-7fb5-fb57-2f2f-9cc2a17f720d.jpeg)