(追記 2017/09/06)
下記に記載事項は「ビルド環境」「OS環境」により再現しないかもしれません。
環境が変わった時点でバグとなる可能性が考えられるため、お薦めの方法ではありません。
なんらかの参考にはなるかもしれないため、記事としては残しておきます。
動作環境
C++ Builder XE4
- TTrackBarを使ったスライダー表示
- TEditを用いた数値の入力
上記を同期させるとする。
失敗編
方法
- TTrackBarのOnChangeイベントでTEditの値を変更する
- TEditのOnExitイベントでTTrackBarの値を変更する
こうした場合、TEditの値を変更してフォーカスをはずしたとき、以下となる。
- TEditのOnExitイベントが発生
- => TTrackBarの値が変更される
- => TTrackBarのOnChangeイベントが発生
- => TEditの値が変更される
 
 
- => TTrackBarのOnChangeイベントが発生
 
- => TTrackBarの値が変更される
回避案
方法
- TTrackBarのOnChangeイベントでTEditの値を変更する
- 変更条件: 変更終了時のみ
 
- TEditのOnExitイベントでTTrackBarの値を変更する
こうした場合、TEditの値を変更してフォーカスをはずしたとき、以下となる。
- TEditのOnExitイベントが発生
- => TTrackBarの値が変更される
- 変更終了時(i.e., 値がpreと同値)でないためTTrackBarのOnChangeイベントは発生しない
 
 
- => TTrackBarの値が変更される
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>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TEdit *Edit1;
	TTrackBar *TrackBar1;
	TMemo *Memo1;
	void __fastcall TrackBar1Change(TObject *Sender);
	void __fastcall Edit1Exit(TObject *Sender);
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 bool kCatchEndChange = true;  // true: TrackBar1の最後の変更(+1)だけ検知する
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	TrackBar1->Min = 0;
	TrackBar1->Max = 100;
	TrackBar1->Frequency = 10;
	Memo1->Clear();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TrackBar1Change(TObject *Sender)
{
	static int pre = -1;
	if (kCatchEndChange) {
		if (pre == TrackBar1->Position) {
			Memo1->Lines->Add(L"TrackBar1Change [" + IntToStr(TrackBar1->Position) + L"] " + DateTimeToStr(Now()));
			Edit1->Text = IntToStr(TrackBar1->Position);
		}
		pre = TrackBar1->Position;
		return;
	}
	Memo1->Lines->Add(L"TrackBar1Change [" + IntToStr(TrackBar1->Position) + L"] " + DateTimeToStr(Now()));
	Edit1->Text = IntToStr(TrackBar1->Position);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Edit1Exit(TObject *Sender)
{
	Memo1->Lines->Add(L"Edit1Exit [" + Edit1->Text + L"] " + DateTimeToStr(Now()));
	int val = StrToIntDef(Edit1->Text, -1);
	if (val > 0) {
        TrackBar1->Position = val;
	}
}
//---------------------------------------------------------------------------
実行例
失敗編
kCatchEndChange = false;で実行。
- (1)の部分: TrackBar1の値を2から24に上げた
- 途中の変更がイベント処理されてしまう
 
- (2)の部分: TEditからフォーカスをはずした
- OnExitイベントに加えて、TrackBar1:OnChangeイベントが発生してしまう
 
成功編
kCatchEndChange = true;で実行。
- (1)の部分: TrackBar1の値を2から45に上げた
- 最後の二回のイベントが発生
 
- (2)の部分: TEditからフォーカスをはずした
- OnExitイベントのみ発生
 

