2019-02-19 C++ Builder XE4 > TeeChart > geometry > グラフ描画領域の左側を固定化 > ラベルの有効桁の変化 + 左軸右軸の切替、に対応

```txt:動作環境
C++ Builder XE4
```

### 処理概要

- TChartのグラフ描画領域の左側は以下の状況で変化する
    - A. 左軸ラベルの有効桁の違い
        - 例: 8.0
        - 例: 8.50
    - B. データセットの軸設定 (左軸 or 右軸)
- 上記の状況でも「同じ座標に左軸が来るように」する

### 実装

```Unit1.h
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
#include <VCLTee.Chart.hpp>
#include <VCLTee.Series.hpp>
#include <VCLTee.TeEngine.hpp>
#include <VCLTee.TeeProcs.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TChart *Chart1;
	TFastLineSeries *Series1;
	TMemo *Memo1;
	TButton *B_upper;
	TButton *B_middle;
	TButton *B_leftRight;
	TShape *Shape1;
	TShape *Shape2;
	void __fastcall B_upperClick(TObject *Sender);
	void __fastcall B_middleClick(TObject *Sender);
	void __fastcall B_leftRightClick(TObject *Sender);
	void __fastcall Chart1AfterDraw(TObject *Sender);
private:	// ユーザー宣言
	void __fastcall updateGraphView(TChart *chrPtr);
	void __fastcall addDummyData();
	void __fastcall changeChartRect(int left, int top, int right, int bottom);
	void __fastcall correctForLabelTextWidth(int atop);
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
```

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <DateUtils.hpp>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

static const int kLeft_chartRect = 100; // この位置を基準としてグラフ描画領域の左を計算

__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	addDummyData();
	Shape1->Left = kLeft_chartRect;
}
//---------------------------------------------------------------------------
// { 汎用関数
void __fastcall TForm1::updateGraphView(TChart *chrPtr)
{
	if (chrPtr == NULL) {
		return;
	}

	// グラフ描画の更新を促すため
	int pre = chrPtr->Title->Font->Size;
	chrPtr->Title->Font->Size = pre + 1;
	chrPtr->Title->Font->Size = pre;

	//
	Application->ProcessMessages();  // ***正しい[ChartRect.Top]を得るために必要
	Sleep(100); // msec
}
// } 汎用関数
//---------------------------------------------------------------------------
void __fastcall TForm1::addDummyData()
{
	Chart1->Series[0]->XValues->DateTime = true;
	Chart1->BottomAxis->DateTimeFormat = L"nn:ss";

	TDateTime dt = Now();

	for (int idx=0; idx < 10; idx++) {
		double yval = (1+ idx) % 2;
		Series1->AddXY(dt, yval, "", clRed);
		dt = IncSecond(dt, 1);
	}
}

void __fastcall TForm1::changeChartRect(int left, int top, int right, int bottom)
{
	Chart1->CustomChartRect = true;
	Chart1->ChartRect = Rect(left, top, right, bottom);
	updateGraphView(Chart1);  // ***正しい[ChartRect]を得るために必要
}

void __fastcall TForm1::correctForLabelTextWidth(int atop)
{
	int diff_hori = Chart1->ChartRect.Left - kLeft_chartRect;
	changeChartRect(kLeft_chartRect- diff_hori, atop, 500, 300);

	// for debug
	String infmsg = String().sprintf(L"diff: %d", diff_hori);
	Memo1->Lines->Add(infmsg);
}

void __fastcall TForm1::B_upperClick(TObject *Sender)
{
	int atop = 0;  // グラフ描画領域を上に
	changeChartRect(kLeft_chartRect, atop, 500, 300);
	correctForLabelTextWidth(atop);
}

void __fastcall TForm1::B_middleClick(TObject *Sender)
{
	int atop = 100;  // グラフ描画領域を中段に
	changeChartRect(kLeft_chartRect, atop, 500, 300);
	correctForLabelTextWidth(atop);
}

void __fastcall TForm1::Chart1AfterDraw(TObject *Sender)
{
	Shape2->Left = Chart1->ChartRect.Left;  // 位置確認用
}
//---------------------------------------------------------------------------

void __fastcall TForm1::B_leftRightClick(TObject *Sender)
{
	// 左軸と右軸の切替

	if (B_leftRight->Tag == 0) {
		B_leftRight->Tag = 1;
		Chart1->Series[0]->VertAxis = aRightAxis;
	} else {
		B_leftRight->Tag = 0;
		Chart1->Series[0]->VertAxis = aLeftAxis;
	}
}
//---------------------------------------------------------------------------
```

### ボタン

- [1] B_upper: グラフ描画領域のTop位置を上側にする
- [2] B_lower: グラフ描画領域のTop位置を中段にする
- [3] B_leftRight: データセットの左軸右軸割当ての切替


### 動作例

[1]を押した後
(緑の四角は常に同じ位置にくる。参照用)
![2019-02-19_17h37_15.png](https://qiita-image-store.s3.amazonaws.com/0/32870/803c0652-1657-342c-e36d-600ed6c68eba.png)

[2]を押した後
![2019-02-19_17h37_28.png](https://qiita-image-store.s3.amazonaws.com/0/32870/f7370ee3-d9d8-a13e-4206-2fe34e2f58cf.png)

[3]を押して、[1]を押した後
![2019-02-19_17h37_35.png](https://qiita-image-store.s3.amazonaws.com/0/32870/ce224d25-9e00-bc0e-dd66-51349773cdb6.png)

さらに[2]を押した後
![2019-02-19_17h37_39.png](https://qiita-image-store.s3.amazonaws.com/0/32870/61bf9e01-6b4d-2e12-682e-02c1fdee022b.png)

全ての状況で「同じ左位置」にグラフ描画領域の左側が来るようになった。