Help us understand the problem. What is going on with this article?

C++ Builder > { コンポーネントの[Tag]値の範囲 > NativeInt型 } | { Tagを使った共通実装: TTrackBar値, TEdit値の同期, XXX設定 }

More than 1 year has passed since last update.
動作環境
C++ Builder XE4

コンポーネントのTagプロパティ

コンポーネントのTagプロパティ。
これをうまく使うと共通処理が実装できる。

Tagには数値を入力可能だが、どういう値が使えるのか?

http://ht-deko.com/tech006.html

 XE2 以降では、Tag プロパティは NativeInt 型になりました。これにより、32bit / 64bit アプリケーションに関わらず、ポインタを型キャストして利用する事が可能となっています。

@ht_deko さん
情報感謝です。

http://docwiki.embarcadero.com/Libraries/XE4/ja/System.NativeInt

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;
}
//---------------------------------------------------------------------------

実行例

qiita.png

  • (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の設定と読込み

実行例

qiita.png

XXX_GetAllValuesToComponents()を毎回実行するのは無駄な処理ではある。

変更があったものだけを読直すように処理をすれば、なお良い。

7of9
セブンオブナインです。Unimatrix 01の第三付属物 9の7という識別番号です。Star trek Voyagerの好きなキャラクターです。まとめ記事は後日タイトルから内容がわからなくなるため、title検索で見つかるよう個々の記事にしてます。いわゆるBorg集合体の有名なセリフから「お前たち(の知識)を吸収する。抵抗は無意味だ」。Thanks in advance.
qiitadon
Qiitadon(β)から生まれた Qiita ユーザー・コミュニティです。
https://qiitadon.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした