0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C++ Builder XE4 > TControl > プロパティのコピー > Shape1からShape2へプロパティをコピーする

Last updated at Posted at 2018-12-26
動作環境
C++ Builder XE4

処理概要

  • Shape1:TShapeからShape2:TShapeへプロパティをコピーしたい
    • 線の幅や色などプロパティを一つ一つコピーするのでなく、丸ごとコピーする

参考

RTTIの方法など紹介されている例もあるが、自分の目に留まったのはTMemoryStreamを使った実装。

下記はDelphiでの実装。

それをC++ Builder用に変更した

フォームデザイン

2018-12-26_17h20_30.png

実装

Unit1.h
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TShape *Shape1;
	TShape *Shape2;
	TButton *Button1;
	void __fastcall Button1Click(TObject *Sender);
private:	// ユーザー宣言
	void __fastcall copyProperties(TControl *srcCtrl, TControl *dstCtrl);
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)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	// 
	copyProperties((TControl *)Shape1, (TControl *)Shape2);

	// 重なっているため
	Shape2->Left = Shape1->Left + 150;
}

void __fastcall TForm1::copyProperties(TControl *srcCtrl, TControl *dstCtrl)
{
	// 元の名前を保持
	String orgName_src = srcCtrl->Name;
	String orgName_dst = dstCtrl->Name;

	// プロパティコピー
	TMemoryStream *strm = new TMemoryStream;
	Shape1->Name = L"";  // to avoid source collision
	try {
		strm->WriteComponent(srcCtrl);
		strm->Position = 0;
		strm->ReadComponent(dstCtrl);
	}
	__finally
	{
		delete strm;
	}

	srcCtrl->Name = orgName_src;
	dstCtrl->Name = orgName_dst;
}

動作例

ソフト起動直後
2018-12-26_17h21_11.png

Button1押下後
2018-12-26_17h21_23.png

イベントのコピー

に記載があるように、上記の実装では「プロパティ」のコピーはできるが、「イベント」のコピーはできない。
「イベント」のコピーは上記のDelphi実装を参考に別途実装する必要がある。

(2018年12月現在は不要のため、この記事では実装しない)

関連

不具合? > フォーム間で「同じ」名前のコンポーネント間のコピー

  • FormA: Shape1
  • FormB: Shape1

2つのコンポーネントでコピーをするとどうなるか?
下記のエラーが発生した。

モジュール 'XXX.exe'のアドレス XXXでアドレスXXXに対する読取り違反がおきました。

名前は同じだとダメなのだろうか。

試しに名前を違うようにして実行したが、同じエラーとなった。

失敗理由が分かった。

v0.2

copyProperties()内のsrcCtrl->Name = L"";srcCtrl->Name = L"";に修正。

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)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	// 
	copyProperties((TControl *)Shape1, (TControl *)Shape2);

	// 重なっているため
	Shape2->Left = Shape1->Left + 150;
}

void __fastcall TForm1::copyProperties(TControl *srcCtrl, TControl *dstCtrl)
{
	// 元の名前を保持
	String orgName_src = srcCtrl->Name;
	String orgName_dst = dstCtrl->Name;

	// プロパティコピー
	TMemoryStream *strm = new TMemoryStream;
	srcCtrl->Name = L"";  // to avoid source collision
	try {
		strm->WriteComponent(srcCtrl);
		strm->Position = 0;
		strm->ReadComponent(dstCtrl);
	}
	__finally
	{
		delete strm;
	}

	srcCtrl->Name = orgName_src;
	dstCtrl->Name = orgName_dst;
}
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?