動作環境
C++ Builder XE4
コンポーネントのTagプロパティ
コンポーネントのTagプロパティ。
これをうまく使うと共通処理が実装できる。
Tagには数値を入力可能だが、どういう値が使えるのか?
XE2 以降では、Tag プロパティは NativeInt 型になりました。これにより、32bit / 64bit アプリケーションに関わらず、ポインタを型キャストして利用する事が可能となっています。
@ht_deko さん
情報感謝です。
NativeInt は整数の部分集合を表します。NativeInt の範囲は、現在のプラットフォームによって異なります。32 ビット プラットフォームでは、NativeInt は Integer 型と同等です。64 ビット プラットフォームでは、NativeInt は Int64 型と同等です。
用途 > 共通処理 v0.1 > TTrackBarのみ
以下のようにして処理を共通化できる。
- 各TTrackBarのTagプロパティに変更したい設定項目のレジスタ値を設定しておく
- 全てのTTrackBarのOnChangeをTrackBarChange_general()で共通化
- TimerCheckChangeTimer()にてTag値を用いて処理
code
Unit1.h
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include "editex.h"
#include "numedit.h"
#include <Vcl.ComCtrls.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE で管理されるコンポーネント
TTrackBar *TrackBar1;
TTrackBar *TrackBar2;
TTimer *TimerCheckChange;
TMemo *Memo1;
TTrackBar *TrackBar3;
void __fastcall TrackBarChange_general(TObject *Sender);
void __fastcall TimerCheckChangeTimer(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 link "editex"
#pragma link "numedit"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
// 別ファイルで定義されているとする
#define REG_XXX (1024)
#define REG_YYY (2048)
#define REG_ZZZ (3072)
//
static TTrackBar *s_trbPtr = NULL;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Memo1->Clear();
// タグの割付
TrackBar1->Tag = REG_XXX;
TrackBar2->Tag = REG_YYY;
TrackBar3->Tag = REG_ZZZ;
//
TrackBar1->OnChange = TrackBarChange_general;
TrackBar2->OnChange = TrackBarChange_general;
TrackBar3->OnChange = TrackBarChange_general;
//
TimerCheckChange->Enabled = false;
TimerCheckChange->Interval = 300; // msec
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TrackBarChange_general(TObject *Sender)
{
// 共通処理
if (TimerCheckChange->Enabled) {
return;
}
s_trbPtr = (TTrackBar *)Sender;
TimerCheckChange->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TimerCheckChangeTimer(TObject *Sender)
{
if (s_trbPtr == NULL) {
TimerCheckChange->Enabled = false;
return;
}
int regval = s_trbPtr->Tag; // register value
String msg = L"Change register of [" + IntToStr(regval) + L"]";
Memo1->Lines->Add(msg);
s_trbPtr = NULL;
TimerCheckChange->Enabled = false;
}
//---------------------------------------------------------------------------
実行例
- (1) : TrackBar1を変更時
- (2) : TrackBar2を変更時
- (3) : TrackBar3を変更時
TrackBarのPositionの値を用いて、TrackBarのTag値のレジスタ内容を変更するというような共通処理を実装できる。
用途 > 共通処理 v0.2 > TTrackBarとTEdit + XXX設定
- コンポーネント1変更
- コンポーネント2変更
- XXX設定変更
という流れを考えてきたが、以下でもいいかもしれない。
- コンポーネント1変更
- XXX設定変更
- コンポーネント2変更
- XXX設定から読出し
code
Unit1.h
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include "editex.h"
#include "numedit.h"
#include <Vcl.ComCtrls.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE で管理されるコンポーネント
TTrackBar *TrackBar1;
TTrackBar *TrackBar2;
TTimer *TimerCheckChange;
TMemo *Memo1;
TTrackBar *TrackBar3;
TEdit *Edit1;
TEdit *Edit2;
TEdit *Edit3;
void __fastcall TrackBarChange_general(TObject *Sender);
void __fastcall TimerCheckChangeTimer(TObject *Sender);
void __fastcall EditKeyDown_general(TObject *Sender, WORD &Key, TShiftState Shift);
void __fastcall EditExit_general(TObject *Sender);
private: // ユーザー宣言
// XXXの設定と読込み
void __fastcall XXX_SetValue(int regval, int value);
void __fastcall XXX_GetAllValuesToComponents(void);
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 link "editex"
#pragma link "numedit"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
// { XXXの設定
// 別ファイルで定義されているとする
#define REG_XXX (1024)
#define REG_YYY (2048)
#define REG_ZZZ (3072)
typedef struct {
int xval;
int yval;
int zval;
} SENSOR_SETTING_t;
static SENSOR_SETTING_t s_setting = { 0, 0, 0 };
// } XXXの設定
static TTrackBar *s_trbPtr = NULL;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Memo1->Clear();
// タグの割付
TrackBar1->Tag = REG_XXX;
TrackBar2->Tag = REG_YYY;
TrackBar3->Tag = REG_ZZZ;
Edit1->Tag = REG_XXX;
Edit2->Tag = REG_YYY;
Edit3->Tag = REG_ZZZ;
// イベント処理の共通化
TrackBar1->OnChange = TrackBarChange_general;
TrackBar2->OnChange = TrackBarChange_general;
TrackBar3->OnChange = TrackBarChange_general;
Edit1->OnKeyDown = EditKeyDown_general;
Edit2->OnKeyDown = EditKeyDown_general;
Edit3->OnKeyDown = EditKeyDown_general;
Edit1->OnExit = EditExit_general;
Edit2->OnExit = EditExit_general;
Edit3->OnExit = EditExit_general;
//
TimerCheckChange->Enabled = false;
TimerCheckChange->Interval = 300; // msec
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TrackBarChange_general(TObject *Sender)
{
// 共通処理
if (TimerCheckChange->Enabled) {
return;
}
s_trbPtr = (TTrackBar *)Sender;
if (s_trbPtr->Focused() == false) { // 他のコンポーネントからの値の変更
return;
}
TimerCheckChange->Enabled = true;
}
void __fastcall TForm1::TimerCheckChangeTimer(TObject *Sender)
{
if (s_trbPtr == NULL) {
TimerCheckChange->Enabled = false;
return;
}
int regval = s_trbPtr->Tag; // register value
XXX_SetValue(regval, s_trbPtr->Position);
XXX_GetAllValuesToComponents(); // 毎回全部の項目を読むため、処理は重い
// debug
String msg = L"TrackBar: Change register of [" + IntToStr(regval) + L"]";
Memo1->Lines->Add(msg);
s_trbPtr = NULL;
TimerCheckChange->Enabled = false;
}
void __fastcall TForm1::EditExit_general(TObject *Sender)
{
TEdit *srcPtr = (TEdit *)Sender;
int setval = StrToIntDef(srcPtr->Text, -1);
if (setval < 0) {
return; // error
}
int regval = srcPtr->Tag; // register value
XXX_SetValue(regval, setval);
XXX_GetAllValuesToComponents(); // 毎回全部の項目を読むため、処理は重い
// debug
String msg = L"Edit: Change register of [" + IntToStr(regval) + L"]";
Memo1->Lines->Add(msg);
}
void __fastcall TForm1::EditKeyDown_general(TObject *Sender, WORD &Key, TShiftState Shift)
{
if (Key != VK_RETURN) {
return;
}
EditExit_general(Sender);
}
//---------------------------------------------------------------------------
// { XXXの設定と読込み
void __fastcall TForm1::XXX_SetValue(int regval, int value)
{
switch(regval) {
case REG_XXX:
s_setting.xval = value;
break;
case REG_YYY:
s_setting.yval = value;
break;
case REG_ZZZ:
s_setting.zval = value;
break;
};
}
void __fastcall TForm1::XXX_GetAllValuesToComponents(void)
{
Edit1->Text = String(s_setting.xval);
Edit2->Text = String(s_setting.yval);
Edit3->Text = String(s_setting.zval);
TrackBar1->Position = s_setting.xval;
TrackBar2->Position = s_setting.yval;
TrackBar3->Position = s_setting.zval;
}
// } XXXの設定と読込み
実行例
XXX_GetAllValuesToComponents()を毎回実行するのは無駄な処理ではある。
変更があったものだけを読直すように処理をすれば、なお良い。