C++ Builder > TTrackBar > 値変更中にOnChange()が繰返し実行される > TTimer利用によるOnChange回数の緩和

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

TTrackBarで値変更中にOnChangeイベントが頻発する問題の対応を検討中。

### 背景

TTrackBarのOnChangeイベントの実行回数が多い問題において、以下ではOnChange最後に値が連続する振舞いを利用しようとした。
[[廃版] C++ Builder > TTrackBar > 値変更中にOnChange()が繰返し実行される > 変更終了の検知案](http://qiita.com/7of9/items/6f13b78702f9186af345)

しかしながら、上記の振舞いは「ビルド環境」「OSのバージョン」などの組合せで「たまたま」そうなっているのかもしれないと思い始めた。

その振舞いに依存したコードは将来のIDEバージョンアップやOSバージョンアップ時に「はまる」要因になる。将来の負債になりうる。

別の案を考えてみた。

## TTimer使用

OnChangeイベント頻発をTTimerを使って緩和する。

TTimerはEnabledにした後にInterval後に処理される。その仕組みを使う。

### code

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

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ComCtrls.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TMemo *Memo1;
	TTrackBar *TrackBar1;
	TTimer *TimerChanged;
	void __fastcall TrackBar1Change(TObject *Sender);
	void __fastcall TimerChangedTimer(TObject *Sender);
	void __fastcall TrackBar1KeyDown(TObject *Sender, WORD &Key, TShiftState Shift);

private:	// ユーザー宣言
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
```

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

#include <vcl.h>
#pragma hdrstop

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

static const int kUseTimer = true;

__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	TimerChanged->Enabled = false;
	TimerChanged->Interval = 300; // msec
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TrackBar1Change(TObject *Sender)
{

	if (kUseTimer) {
		if (TimerChanged->Enabled) {
			return;
		}
		TimerChanged->Enabled = true;
	} else {
		TimerChangedTimer(Sender);
	}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TimerChangedTimer(TObject *Sender)
{
	// 希望する処理を書く
	String msg = Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz");
	Memo1->Lines->Add(msg);

	// 連続実行を行わない
	TimerChanged->Enabled = false;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::TrackBar1KeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
{
	/*
	for debug
	TTrackBar変更前に区切り線をつけるために使う
	*/
	if (Key == 'V' && Shift.Contains(ssCtrl)) {
		Memo1->Lines->Add(L"-----");
	}
}
//---------------------------------------------------------------------------
```

### 結果 > TTimer不使用時

`kUseTimer = false`

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/ace3aa1c-b832-6b8d-997c-5aa8500d2748.png)

- (1)-(3): マウスドラッグ時 (短時間)
- (4)-(6): カーソル使用時

それぞれ複数回イベントが発生している。

### 結果 > TTimer使用時

`kUseTimer = true`

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/ce300f77-108b-6507-d47b-5e342d7aa0ae.png)

- (1)-(3): マウスドラッグ時 (短時間)
- (4)-(6): カーソル使用時
- (7): マウスドラッグ時 (1.2秒程度)

(1)-(6)ではそれぞれ一回に抑止された。
(7)では複数回実行されるが、間隔は300msec以上にはなる。