Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
1
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

@7of9

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

動作環境
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;
}
//---------------------------------------------------------------------------

実行例

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()を毎回実行するのは無駄な処理ではある。

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

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
1
Help us understand the problem. What are the problem?