質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

2364閲覧

ButtonコンポーネントにColorプロパティを追加したい

dem0nmichik0

総合スコア37

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/09/22 04:37

編集2018/09/29 10:01

【実現したいこと】
C++BuilderでButtonクラスにColorプロパティを追加した自作コンポーネントを作成したい.
理由は背景色を変更したいからです.

【現在の状況・困っていること】
Buttonクラスを継承した「TDoorButton」クラスを作成後,「FColor」フィールドの追加,「Color」プロパティ(SetColor, GetColor)を追加したまではいいのですが,自作コンポーネントのテストでチェックボックスをクリックしたら,TDoorButtonクラスのボタンの背景色が変わるようにコーディングしたのですが,ボタンの背景色が変わらないくて困っています.なにか処理が足りないのでしょうか?それとも処理が間違っているのでしょうか?ご指導お願いいたします.

【試したこと】
各メソッドにブレークポイントをはって処理の流れは確認しました.
1.チェックボックスにチェックを入れる.
2.ClickCheckBoxClickイベントに処理が移り,チェックボックスの状態によりボタンのColorプロパティに色情報が設定される.(ClickCheckBoxClick)
3.Colorプロパティに色情報が設定されるとSetColorメソッドに処理が移り,ColorプロパティにTColorの色情報を設定する.(SetColor)
4.ボタンの背景色も変更する.

【変更箇所】
回答をいただき,プログラムを次のように変更.下記のように修正したのですが,ボタンの色が変更せず,何も動作しなくて困っています.
1.FColorフィールド,Colorプロパティを削除してFBrushフィールド,Brushプロパティ,GetBrushメソッドを追加した.
2.TButtonクラスのpublicプロパティにBrushプロパティがあることが分かったので,1で追加したBrushフィールドやプロパティ,メソッドをコメント化した.
3.ClickCheckBoxClickイベントでBrushプロパティのColorプロパティを変更するように修正.

【開発環境】
OS:Windows10 64bit
C++Builder10.2 Community Edition

フォーム画面には
・ボタン(Name:Button1),パネル(Name:Panel1),チェックボックス(Name:ClickCheckBox)コンポーネントを張り付けています.

ソースコードは次の通りです.
<Unit.cpp>

//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "DoorButton.h" #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { DoorButton = new TDoorButton(this); DoorButton->Parent = this; DoorButton->Left = 32; DoorButton->Top = 140; DoorButton->Height = 40; DoorButton->Width = 100; DoorButton->Caption = "DoorButton"; Panel1->Color = clRed; } //--------------------------------------------------------------------------- void __fastcall TForm1::ClickCheckBoxClick(TObject *Sender) { if( ClickCheckBox->Checked == true ) { DoorButton->Brush->Color = clRed; } else { DoorButton->Brush->Color = clBtnFace; } } //---------------------------------------------------------------------------

<Unit.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 で管理されるコンポーネント TButton *Button1; TPanel *Panel1; TCheckBox *ClickCheckBox; void __fastcall ClickCheckBoxClick(TObject *Sender); private: // ユーザー宣言 public: // ユーザー宣言 __fastcall TForm1(TComponent* Owner); TDoorButton *DoorButton; }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------- #endif

<DoorButton.cpp(TButtonクラスを継承した作成中のコンポーネント)>

//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "DoorButton.h" #pragma package(smart_init) //--------------------------------------------------------------------------- // ValidCtrCheck は、作成したコンポーネントに純粋仮想関数が // ないことを確認するために使用します。 // static inline void ValidCtrCheck(TDoorButton *) { new TDoorButton(NULL); } //--------------------------------------------------------------------------- __fastcall TDoorButton::TDoorButton(TComponent* Owner) : TButton(Owner) { } //--------------------------------------------------------------------------- namespace Doorbutton { void __fastcall PACKAGE Register() { TComponentClass classes[1] = {__classid(TDoorButton)}; RegisterComponents(L"Samples", classes, 0); } } //--------------------------------------------------------------------------- /* TBrush* __fastcall TDoorButton::GetBrush() { return Brush; } */ //---------------------------------------------------------------------------

<DoorButton.h>

//--------------------------------------------------------------------------- #ifndef DoorButtonH #define DoorButtonH //--------------------------------------------------------------------------- #include <System.SysUtils.hpp> #include <System.Classes.hpp> #include <Vcl.Controls.hpp> #include <Vcl.StdCtrls.hpp> //--------------------------------------------------------------------------- class PACKAGE TDoorButton : public TButton { private: // TBrush *FBrush; // TBrush* __fastcall GetBrush(); protected: // void __fastcall CreateParams(Controls::TCreateParams & Params); public: __fastcall TDoorButton(TComponent* Owner); __published: // __property TBrush *Brush = { read=GetBrush }; }; //--------------------------------------------------------------------------- #endif

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2018/09/22 13:51

ボタンの背景色を変えているところが見当たりませんがどこですか?
dem0nmichik0

2018/09/22 14:09

ClickCheckBoxClickイベントハンドラの「DoorButton->Color = clRed;」または「DoorButton->Color = clBtnFace」でボタンの背景色を変えていると思っているのですが,間違いでしょうか?このどちらかの処理によって,SetColorメソッドが処理されてボタンの背景色が変わると思っていたのですが,処理の流れとしても間違いでしょうか?
Zuishin

2018/09/22 14:11

間違いだと思います。その件について回答しました。VCL で間違いありませんか?
guest

回答1

0

ベストアンサー

C++ Builder は使っていないので確かめることができませんが、プロパティの実装法が間違っているように見えます。
__property を参考にしてください。
GetColor(), SetColor() は必要ないと思います。

そして掲載されたコードでは新しく作ったプロパティの値を設定しているだけで背景色の変更をしていません。
ブラシを作って Brush プロパティを変更してください。

Vcl.Controls.TWinControl.Brush

プロパティを変更しただけで背景色が変わるのではないかと思いますが、もしかしたら再描画が必要になるかもしれません。

#追記

GetColor(), SetColor() は必要ないと書きましたが、これは間違いです。
GetColor(), SetColor() の中で Color プロパティを使っていますが、必要ないのはこっちです。循環していると思います。

投稿2018/09/22 13:58

編集2018/09/22 14:17
Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dem0nmichik0

2018/09/22 14:29

回答ありがとうございます. 記載していただいたURLを参考に試してみます.
Zuishin

2018/09/22 16:55

それはプロパティの作り方だけで、本命は Brush の方です。
dem0nmichik0

2018/09/23 03:01

回答ありがとうございます. 記載していただいたBrushのURLを参考にフィールドにTBrush *FBrush,プロパティにTBrush *Brush,読み取り専用GetBrushメソッドを作成してみたのですが,GetBrushメソッドで「E2122 関数呼び出しが未処理例外 'value' によってアドレス 'addr' で終了した 」が発生している状況です.原因が分からなくて困ている状態です.
dem0nmichik0

2018/09/23 03:08

すいません,発生しているエラーは「プロジェクトProject.exeは例外クラス$C000000FD(メッセージ'stack overflow at 0x77b1db68')を送出しました」でした.エラー文の通り,オーバーフローがどこかで発生しているんだろうなってことはわかるのですが,その原因が分からなくて修正方法が分からず困っています.
Zuishin

2018/09/23 04:21

Brush プロパティはすでにあるので追加してはいけませんよ。
Zuishin

2018/09/23 04:35

これは余談ですが、C++ Builder は一時期に比べてユーザーがかなり減っていると思います。 情報は少なくプログラミング初心者の独学には向きません。 Delphi のほうがまだマシかもしれませんね。 私も使ったことないので十分な解説ができません。 プロパティなにそれ継承なにそれというレベルなのであれば、一度古本屋かネットで昔の本を買って基礎から学習することをおすすめします。 そもそも Visual Studio と C# の方が数百倍から下手をすれば数千倍の初心者向け情報があると思いますから、可能ならそちらに乗り換えた方が楽です。
Zuishin

2018/09/23 04:42

それとスタックオーバーフローが発生しているのは恐らく循環参照しているためです。 質問のコードでは循環参照していますが、例に挙げたサンプルではしていないはずです。
dem0nmichik0

2018/09/23 05:27

回答およびアドバイスありがとうございます。 現在のコードはFColor,Setcolor,GetColorメソッドがいらないとしてきされたのでコメント化しています.BrushはButtonのpublicメンバということがわかり,追加したFBrushやGetBrushメソッドもコメントにして,クリックイベントハンドラで「DoorButton->Brush->Color = clRed;」で実行したところ,何の変化もなくて困っています.RefreshやRepaintメソッドで再描画や強制再描画をしても色が変わらず困っています. 私自身も個人的にアプリケーションを作成する場合は書籍やネットの情報が多いことからVisualStudioのC#で作成しています.ですが,会社でのアプリケーション開発がC++Builderをしようしております.モジュールが多いコーディングとなっており,プロジェクトごとにアプリを流用するのですが,細かな仕様が異なるため,修正が多いというコーディングになっているのをオブジェクト指向で再利用度が高いプログラムにしようと,継承を使った自作コンポーネントを試しているところです.会社でC++BuilderからC#になるのがいつかわからないなら,最初からC#でオブジェクト指向で会社のアプリを一から作り直してみたほうがいいでしょうか? 質問と関係ないことまで聞いて申し訳ありません.
Zuishin

2018/09/23 05:47

会社の方針なら C++ Builder を使わなければ仕方ありませんが、それならやっつけの突貫工事をするのではなく言語やライブラリの基本仕様くらいはあらかじめチェックした方がいいと思います。 でないと肝心の再利用性がなくなって本末転倒です。
dem0nmichik0

2018/09/29 10:29

コメントありがとうございます. DoorButtonインスタンスを作成しているTForm1のコンストラクタの最後でBrutyのStyleもbsClear以外の7通り全て試しましたが,変化しませんでした.再描画のRefreshやRepaintをクリックイベント時にやっても変わらない状態です.
Zuishin

2018/09/29 12:53

じゃあちょっと試してみてください。 まず普通に VCL のフォームアプリを作ります。 フォームにボタンを一つ貼り付けてボタンをダブルクリックし、イベントハンドラを次のように書きます。 void __fastcall TForm1::Button1Click(TObject *Sender) { ((TButton *)Sender)->Brush->Color = clRed; } これを実行し、ボタンを押して色が変わるかどうか確かめてください。
dem0nmichik0

2018/09/29 13:14

コンパイルは通り実行した結果,クリックしてもボタンの色は変わりませんでした. RefreshやRepaintを追加しても変わりませんでした.
dem0nmichik0

2018/09/29 14:01

コメントありがとうございます. URLを参考にオーナードローを自前で実装してみたいと思います.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問