C++ Builder 10.2 Tokyo > color > UI > 色選択 + RGB値入力 [一つのセット版]

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

### 概要

- 下記UIを用意した
    - A. TColorBoxからの色選択
    - B. RGB値の直接入力

BのUIだけを検討していたが、Aもあるほうが使い勝手が良いと思った


### 実装 v0.1

2つのフォームを用意した。
Unit2の方がTColobBoxでの色選択を受け持つ。

#### Unit2

```Unit2.h
//---------------------------------------------------------------------------

#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm2 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TColorBox *ColorBox1;
	TButton *B_ok;
	TButton *B_cancel;
	void __fastcall B_okClick(TObject *Sender);
	void __fastcall B_cancelClick(TObject *Sender);
private:	// ユーザー宣言
public:		// ユーザー宣言
	__fastcall TForm2(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm2 *Form2;
//---------------------------------------------------------------------------
#endif

```

```Unit2.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm2::B_okClick(TObject *Sender)
{
	this->ModalResult = mrOk;
}
//---------------------------------------------------------------------------
void __fastcall TForm2::B_cancelClick(TObject *Sender)
{
    this->ModalResult = mrCancel;
}
//---------------------------------------------------------------------------

```

#### Unit1

```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 で管理されるコンポーネント
	TButton *B_select;
	TShape *Shape1;
	TEdit *E_RGBvalue;
	void __fastcall B_selectClick(TObject *Sender);
	void __fastcall FormShow(TObject *Sender);
	void __fastcall E_RGBvalueExit(TObject *Sender);
private:	// ユーザー宣言
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

```

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

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
void __fastcall TForm1::FormShow(TObject *Sender)
{
    E_RGBvalue->Text = L"FFFFFF";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_selectClick(TObject *Sender)
{
	Form2->ShowModal();
	if (Form2->ModalResult != mrOk) {
		return;
	}

	TColor acol = Form2->ColorBox1->Selected;
	int Rval = GetRValue(acol);
	int Gval = GetGValue(acol);
	int Bval = GetBValue(acol);

	Shape1->Pen->Color = acol;
	Shape1->Brush->Color = acol;

	E_RGBvalue->Text = String().sprintf(L"%02X%02X%02X", Rval, Gval, Bval);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::E_RGBvalueExit(TObject *Sender)
{
	TEdit *edPtr = (TEdit *)Sender;

	// char型を扱うため、ここでAnsiStringにする必要がある (Stringだとwchar_tになる)
	AnsiString astr = AnsiString(edPtr->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;
		edPtr->Text = L"FFFFFF";
	}

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

```


### 実行例

TColorBoxでの選択時
![2019-07-02_17h58_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/c5fc5dfe-5d3f-67d6-5431-949731529783.png)

TColorBoxでの選択後
![2019-07-02_17h58_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/07a6dd48-5ca6-c0ca-736d-6e2b4f079465.png)

RGB値直接入力後
![2019-07-02_17h58_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/bb98d8dc-2ad1-877f-81bc-a64303a94447.png)


### 備考

- 16進数から10進数読取りは厳密にはしていない
    - エラー処理などは状況によって厳密化すること
    

### 実装 v0.2

- TEditのプロパティMaxLength = 6に固定 
- TEditにてEnterキー時に色更新処理をコール

Unit1.cppだけ変更した。

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

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
void __fastcall TForm1::FormShow(TObject *Sender)
{
	E_RGBvalue->MaxLength = 6; // R,G,B値それぞれ00..FF
	E_RGBvalue->Text = L"FFFFFF";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_selectClick(TObject *Sender)
{
	Form2->ShowModal();
	if (Form2->ModalResult != mrOk) {
		return;
	}

	TColor acol = Form2->ColorBox1->Selected;
	int Rval = GetRValue(acol);
	int Gval = GetGValue(acol);
	int Bval = GetBValue(acol);

	Shape1->Pen->Color = acol;
	Shape1->Brush->Color = acol;

	E_RGBvalue->Text = String().sprintf(L"%02X%02X%02X", Rval, Gval, Bval);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::E_RGBvalueExit(TObject *Sender)
{
	TEdit *edPtr = (TEdit *)Sender;

	// char型を扱うため、ここでAnsiStringにする必要がある (Stringだとwchar_tになる)
	AnsiString astr = AnsiString(edPtr->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;
		edPtr->Text = L"FFFFFF";
	}

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

void __fastcall TForm1::E_RGBvalueKeyDown(TObject *Sender, WORD &Key, TShiftState Shift)

{
	if (Key == VK_RETURN) {
        E_RGBvalueExit(E_RGBvalue);
	}
}
//---------------------------------------------------------------------------
```