C++ Builder XE4 > Form > フォーム上のコンポーネントの配置を比率で行う


動作環境
C++ Builder XE4

コンポーネントの自動配置

コンポーネントの自動配置としてAnchorsプロパティがある。
AnchorsプロパティのakLeft, akTop, akRight, akBottomを全てTrueにすると、フォーム拡大時にフォームサイズに合わせてコンポーネントサイズが変更される。

しかしながら、それは「絶対値」での変更であり、複数のコンポーネントがある場合に希望の動作にならない。

初期状態

拡大時

配置を比率で行う

配置を「絶対値」でなく「比率」で行うようにしてみる。

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.Grids.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE で管理されるコンポーネント
    TStringGrid *StringGrid1;
    TStringGrid *StringGrid2;
    TStringGrid *StringGrid3;
    void __fastcall FormResize(TObject *Sender);
    void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
    void __fastcall FormShow(TObject *Sender);
private:    // ユーザー宣言
    void __fastcall registerComponents(TForm *formPtr, TControl *ctlPtr);
    void __fastcall releaseComponents(void);
    void __fastcall resizeWithRatio(void);
    TList *m_ctlList;  // 位置情報の構造体リスト
    struct POSI_RATIO { // 位置情報の構造体
        TControl *ctlPtr;
        double left;
        double top;
        double width;
        double height;
    };
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;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    m_ctlList = new TList();
}

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
    releaseComponents();

    m_ctlList->Clear();
    delete m_ctlList;
}

//---------------------------------------------------------------------------

void __fastcall TForm1::registerComponents(TForm *formPtr, TControl *ctlPtr)
{
    POSI_RATIO *posRat;

    posRat = new POSI_RATIO;
    posRat->ctlPtr = ctlPtr;
    posRat->left = (double)ctlPtr->Left / formPtr->Width;
    posRat->top = (double)ctlPtr->Top / formPtr->Height;
    posRat->width = (double)ctlPtr->Width / formPtr->Width;
    posRat->height = (double)ctlPtr->Height / formPtr->Height;

    m_ctlList->Add(posRat);
}

void __fastcall TForm1::releaseComponents(void)
{
    POSI_RATIO *posRat;

    if (m_ctlList == NULL) {
        return;
    }

    for(int idx=0; idx < m_ctlList->Count; idx++) {
        posRat = (POSI_RATIO *)m_ctlList->Items[idx];
        delete posRat;
    }
}

void __fastcall TForm1::resizeWithRatio(void)
{
    POSI_RATIO *posRat;

    for(int idx=0; idx < m_ctlList->Count; idx++) {
        posRat = (POSI_RATIO *)m_ctlList->Items[idx];
        posRat->ctlPtr->Left = posRat->left * this->Width;
        posRat->ctlPtr->Top = posRat->top * this->Height;
        posRat->ctlPtr->Width = posRat->width * this->Width;
        posRat->ctlPtr->Height = posRat->height * this->Height;
    }
}

void __fastcall TForm1::FormResize(TObject *Sender)
{
    resizeWithRatio();
}

void __fastcall TForm1::FormShow(TObject *Sender)
{
    registerComponents(this, this->StringGrid1);
    registerComponents(this, this->StringGrid2);
    registerComponents(this, this->StringGrid3);
}
//---------------------------------------------------------------------------

実行例

初期状態

拡大時

コンポーネントが重なることはなくなった。

比率でのサイズ変更のため、拡大時にマージン(絶対値)自体も大きくなる。