C++ Builder 10.2 Tokyo > color > RGB値(16進数)を入力して、TShapeの色を変更する > strtol()使用版 | 16進数から10進数への変換

```txt:動作環境
RAD Studio 10.2 Tokyo Update 3
```

### 概要

- TEditにRGB値の16進数を代入
- フォーカスが他に移った時にTShapeの色を指定値に変更する

### 実装 v0.1

```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>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TShape *Shape1;
	TEdit *Edit1;
	TButton *Button1;
	void __fastcall Edit1Exit(TObject *Sender);
private:	// ユーザー宣言
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

```

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

#include <vcl.h>
#pragma hdrstop

#include <sstream>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Edit1Exit(TObject *Sender)
{
	// char型を扱うため、ここでAnsiStringにする必要がある (Stringだとwchar_tになる)
	AnsiString astr = AnsiString(Edit1->Text);   // e.g. FFFF00

	int Red, Green, Blue;

	Red   = strtol(astr.SubString(1, 2).c_str(), /*endptr=*/NULL, 16);
	Green = strtol(astr.SubString(3, 2).c_str(), /*endptr=*/NULL, 16);
	Blue  = strtol(astr.SubString(5, 2).c_str(), /*endptr=*/NULL, 16);

	Shape1->Brush->Color = (TColor)RGB(Red, Green, Blue);
	Shape1->Pen->Color = (TColor)RGB(Red, Green, Blue);
}
//---------------------------------------------------------------------------
```

### 実行例

左上のTEditに代入してからButton1へフォーカスを変えた結果

![2019-07-01_17h40_23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/2fa67a66-6c7d-7696-e8ba-c60397be8434.png)

Note: Button1の押下処理は未実装。フォーカスを移す先にしているだけ。


### 16進数から10進数への変換

16進数から10進数への変換にはいろいろな方法がある。

今回はstrtol()を使用した。

http://www.cplusplus.com/reference/cstdlib/strtol/

strtol()以外も含めた16進数から10進数変換の参考として以下がある。

- C++ convert hex string to signed integer
    - https://stackoverflow.com/questions/1070497/c-convert-hex-string-to-signed-integer

### 実装 v0.2

- 不正文字の対応をした
- TEditのMaxLengthプロパティは6に変更済

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

#include <vcl.h>
#pragma hdrstop

#include <sstream>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Edit1Exit(TObject *Sender)
{
	// char型を扱うため、ここでAnsiStringにする必要がある (Stringだとwchar_tになる)
	AnsiString astr = AnsiString(Edit1->Text);   // e.g. FFFF00

	int tmp;
	int Red, Green, Blue;
	char *endptr;

	AnsiString wrk = astr.SubString(1, 6);
	tmp = strtol(wrk.c_str(), &endptr, 16);

	if (*endptr == 0x00) {
		Red   = strtol(astr.SubString(1, 2).c_str(), /*endptr=*/NULL, 16);
		Green = strtol(astr.SubString(3, 2).c_str(), /*endptr=*/NULL, 16);
		Blue  = strtol(astr.SubString(5, 2).c_str(), /*endptr=*/NULL, 16);
	} else {
		Red = 255;
		Green = 255;
		Blue = 255;
		Edit1->Text = L"FFFFFF";
	}

	Shape1->Brush->Color = (TColor)RGB(Red, Green, Blue);
	Shape1->Pen->Color = (TColor)RGB(Red, Green, Blue);
}
//---------------------------------------------------------------------------
```


### 備考

- `Edit1->Text = L"FFFFFF";`についてはSenderからコンポーネントを取得して代入、まで可能ではあるが、ここではそこまで実装してはいない。
- strtol()は一回だけ実行し、その結果をR、G、B値それぞれに分割する、という方法もある