C++ Builder XE4 > 共通処理 > 一つのTEditを変更後、別のTEditを変更する + TCheckBoxで機能のON/OFFを選択可能 > v0.1, v0.2

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


### 内容

- E_maxA:TEdit, E_stepA:TEdit, CHK_AutoA:TCheckBox がある
- CHK_AutoAがチェックされているとき
    - E_maxA変更時にE_stepAに5で除算した値を代入する

コンポーネント間の連動を行う

### 検討事項

今後、上記のようなセットをN個(N>3)扱う時、処理を共通化するといい場合があるかもしれない

### 実装 v0.1

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

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "editex"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	// コンポーネントアドレスの格納と関数の設定
	//    セットA
	E_maxA->Tag = (int)E_stepA;
	E_maxA->HelpContext = (int)CHK_AutoA;
	E_maxA->OnExit = NE_maxExit_general;  // 関数設定
	E_maxA->OnKeyDown = NE_maxKeyDown_general;  // 関数設定
	CHK_AutoA->Tag = (int)E_stepA;
	CHK_AutoA->HelpContext = (int)E_maxA;
	CHK_AutoA->OnClick = CHK_AutoClick_general;  // 関数設定
	//    セットB
	E_maxB->Tag = (int)E_stepB;
	E_maxB->HelpContext = (int)CHK_AutoB;
	E_maxB->OnExit = NE_maxExit_general;  // 関数設定
	E_maxB->OnKeyDown = NE_maxKeyDown_general;  // 関数設定
	CHK_AutoB->Tag = (int)E_stepB;
	CHK_AutoB->HelpContext = (int)E_maxB;
	CHK_AutoB->OnClick = CHK_AutoClick_general;  // 関数設定
}
//---------------------------------------------------------------------------
// { 共用の関数 (XXX_general)
//
void __fastcall TForm1::updateMajorStep_general(TEdit *maxPtr)
{
	// 共用: 複数のコンポーネントで使用する
	// Senderのプロパティ
	//    Tag: stepのアドレス
	//    HelpContext: CHK_Autoのアドレス

	if (maxPtr == NULL) {
		return;  // error
	}
	TCheckBox *chkAutoPtr = (TCheckBox *)maxPtr->HelpContext;
	if (chkAutoPtr->Checked == false) {  // AutoがONかどうか
		return;
	}

	TEdit *stepPtr = (TEdit *)maxPtr->Tag;
	// 計算式を代入 (例として5で割る)
	int step = StrToIntDef(maxPtr->Text, 0);
	int wrk = step / 5;
	stepPtr->Text = IntToStr(wrk);

}
void __fastcall TForm1::NE_maxExit_general(TObject *Sender)
{
	// 共用: 複数のコンポーネントで使用する
	updateMajorStep_general((TEdit *)Sender);
}
void __fastcall TForm1::NE_maxKeyDown_general(TObject *Sender, WORD &Key, TShiftState Shift)
{
	// 共用: 複数のコンポーネントで使用する
	if (Key != VK_RETURN) {
		return;
	}

	updateMajorStep_general((TEdit *)Sender);
}
void __fastcall TForm1::CHK_AutoClick_general(TObject *Sender)
{
	// 共用: 複数のコンポーネントで使用する
	// Senderのプロパティ
	//    Tag: stepのアドレス
	//    HelpContext: maxのアドレス

	if (Sender == NULL) {
		return;
	}
	TCheckBox *chkPtr = (TCheckBox *)Sender;
	TEdit *stepPtr = (TEdit *)chkPtr->Tag;
	if (chkPtr->Checked) {
		stepPtr->Color = cl3DLight;
		stepPtr->ReadOnly = true;
		updateMajorStep_general(/*neMaxPtr=*/(TEdit *)chkPtr->HelpContext);
	} else {
		stepPtr->Color = clWhite;
		stepPtr->ReadOnly = false;
	}
}
// } 共用の関数 (XXX_general)
//---------------------------------------------------------------------------
```


### 動作例

Autoにチェックを付けて、Maxに値を代入した後 (AとBについて)
![2019-01-10_15h34_36.png](https://qiita-image-store.s3.amazonaws.com/0/32870/76fa562c-5d28-c0f5-229c-d81412d8a0da.png)


### 備考

- エラー処理は不十分かもしれない
- 処理の中身(5で除算)は見えにくくなってはいる
- updateMajorStep_general()の中身は5で除算する以外の処理もしたいかもしれない
    - => 共通処理を緩和する
    - => 共通処理を複数用意する
    - など

### 実装 v0.2

- 変更
    - プロパティと関数の設定を共通化

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

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "editex"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
//	// コンポーネントアドレスの格納
//	//    セットA
//	E_maxA->Tag = (int)E_stepA;
//	E_maxA->HelpContext = (int)CHK_AutoA;
//	E_maxA->OnExit = NE_maxExit_general;
//	E_maxA->OnKeyDown = NE_maxKeyDown_general;
//	CHK_AutoA->Tag = (int)E_stepA;
//	CHK_AutoA->HelpContext = (int)E_maxA;
//	CHK_AutoA->OnClick = CHK_AutoClick_general;
//	//    セットB
//	E_maxB->Tag = (int)E_stepB;
//	E_maxB->HelpContext = (int)CHK_AutoB;
//	E_maxB->OnExit = NE_maxExit_general;
//	E_maxB->OnKeyDown = NE_maxKeyDown_general;
//	CHK_AutoB->Tag = (int)E_stepB;
//	CHK_AutoB->HelpContext = (int)E_maxB;
//	CHK_AutoB->OnClick = CHK_AutoClick_general;

	// コンポーネントアドレスの格納
	setRelatedComponentsAndFunctions(E_maxA, E_stepA, CHK_AutoA);
	setRelatedComponentsAndFunctions(E_maxB, E_stepB, CHK_AutoB);
}

void __fastcall TForm1::setRelatedComponentsAndFunctions(TEdit *maxPtr, TEdit *stepPtr, 
    TCheckBox *chkPtr)
{
	if (maxPtr == NULL || stepPtr == NULL || chkPtr == NULL) {
		ShowMessage("[DEBUG 38] address is NULL");
		return;
	}

	// コンポーネントアドレスの格納
	maxPtr->Tag = (int)stepPtr;
	maxPtr->HelpContext = (int)chkPtr;
	maxPtr->OnExit = NE_maxExit_general;
	maxPtr->OnKeyDown = NE_maxKeyDown_general;
	chkPtr->Tag = (int)stepPtr;
	chkPtr->HelpContext = (int)maxPtr;
	chkPtr->OnClick = CHK_AutoClick_general;
}
//---------------------------------------------------------------------------
// { 共用の関数 (XXX_general)
//
void __fastcall TForm1::updateMajorStep_general(TEdit *maxPtr)
{
	// 共用: 複数のコンポーネントで使用する
	// Senderのプロパティ
	//    Tag: stepのアドレス
	//    HelpContext: CHK_Autoのアドレス

	if (maxPtr == NULL) {
		return;  // error
	}
	TCheckBox *chkAutoPtr = (TCheckBox *)maxPtr->HelpContext;
	if (chkAutoPtr->Checked == false) {  // AutoがONかどうか
		return;
	}

	TEdit *stepPtr = (TEdit *)maxPtr->Tag;
	// 計算式を代入 (例として5で割る)
	int step = StrToIntDef(maxPtr->Text, 0);
	int wrk = step / 5;
	stepPtr->Text = IntToStr(wrk);

}
void __fastcall TForm1::NE_maxExit_general(TObject *Sender)
{
	// 共用: 複数のコンポーネントで使用する
	updateMajorStep_general((TEdit *)Sender);
}
void __fastcall TForm1::NE_maxKeyDown_general(TObject *Sender, WORD &Key, TShiftState Shift)
{
	// 共用: 複数のコンポーネントで使用する
	if (Key != VK_RETURN) {
		return;
	}

	updateMajorStep_general((TEdit *)Sender);
}
void __fastcall TForm1::CHK_AutoClick_general(TObject *Sender)
{
	// 共用: 複数のコンポーネントで使用する
	// Senderのプロパティ
	//    Tag: stepのアドレス
	//    HelpContext: maxのアドレス

	if (Sender == NULL) {
		return;
	}
	TCheckBox *chkPtr = (TCheckBox *)Sender;
	TEdit *stepPtr = (TEdit *)chkPtr->Tag;
	if (chkPtr->Checked) {
		stepPtr->Color = cl3DLight;
		stepPtr->ReadOnly = true;
		updateMajorStep_general(/*maxPtr=*/(TEdit *)chkPtr->HelpContext);
	} else {
		stepPtr->Color = clWhite;
		stepPtr->ReadOnly = false;
	}
}
// } 共用の関数 (XXX_general)
//---------------------------------------------------------------------------
```

動作結果はv0.1と同じため、省略。