c++ builder > TImageが来るからそこ空けるように、の実装 v0.1, v0.2


動作環境
C++ Builder XE4

やりたいこと

  • TImageは普段は隠れている (右側の画面外)
  • ある条件でTImageを表示する
    • その場所より下にある複数のコンポーネントを下にずらす

v0.1 Tag使用

実装案

  • 特定のTagの値を持つコンポーネントだけずらす

実装

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

#include <vcl.h>
#pragma hdrstop

#include <pngimage.hpp>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
    Image1->Picture->LoadFromFile(L"AD2.png");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_toLeftClick(TObject *Sender)
{
    static const int kTag_move = 79;
    static const int kMargin_down = 10;

    // 1. Image1の高さ分、コンポーネントを下にずらす

    for(int idx=0; idx < this->ComponentCount; idx++) {
        TComponent *aPtr = this->Components[idx];
        if (aPtr->Tag != kTag_move) {
            continue;
        }

        TControl *ctlPtr = (TControl *)aPtr;
        ctlPtr->Top += ( Image1->Height + kMargin_down );
    }

    this->Height += Image1->Height;

    // 2. Image1を左に移動
    Image1->Left = 16;
}
//---------------------------------------------------------------------------

v0.1の結果

移動前

移動後

別の案

Tagは他の用途に使う場合もある。

その場合は、TControl *のリストにて、移動対象となるコンポーネントのポインタを格納する。
それらに対してのみ移動処理を実装すればいい。

v0.2 TControl *のリストで指定

実装

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

#include <vcl.h>
#pragma hdrstop

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


__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
    Image1->Picture->LoadFromFile(L"AD2.png");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_toLeftClick(TObject *Sender)
{
    static const int kMargin_down = 10;

    static TControl *targetList[] = {
        Panel1,
        Button1,
        Label2,
        StringGrid1,
    };
    int targetCount = sizeof(targetList) / sizeof(targetList[0]);


    // 1. Image1の高さ分、コンポーネントを下にずらす

    for(int idx=0; idx < targetCount; idx++) {
        TControl *aPtr = targetList[idx];
        aPtr->Top += ( Image1->Height + kMargin_down );
    }

    this->Height += ( Image1->Height + kMargin_down );

    // 2. Image1を左に移動
    Image1->Left = 16;
}
//---------------------------------------------------------------------------

targetList[]の定義は関数内でしているが、他の場所で定義するのが良い。

Tag指定よりこちらがいい点は、コードで意図が分かること。
Tag指定の場合は、フォームデザインでTagを確認しないと、どれが移動対象のコンポーネントか分からない。ソースリーディングしにくくなる。

別の場所でtargetList[]を宣言しようとしたが、あきらめた。
targetList[]に格納するポインタはFormShow処理以降に格納する必要がある。
それを考えると処理が複雑になる。

検索用キーワード

(追記 2018/10/18)

  • そこのけそこのけ