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

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

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

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

Delphi

DelphiはPascalを拡張してオブジェクト指向を導入したWindows, OS X,iOS,Androidのネイティブアプリケーションを開発するための言語です。旧称はObject Pascal。開発用IDE「Delphi」にあわせ現在の名前に改称されました。

C++Builder

C++Builderは、C/C++を用いてアプリ開発できる統合開発環境 (IDE) 。DelphiのC++版です。コンポーネントによるビジュアル開発、高機能なコードエディターなどで生産性の高い開発ができます。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

Q&A

解決済

1回答

1724閲覧

円や楕円などを描画するときに図形外部を親コントロールの色と合わせたい

dem0nmichik0

総合スコア37

canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

Delphi

DelphiはPascalを拡張してオブジェクト指向を導入したWindows, OS X,iOS,Androidのネイティブアプリケーションを開発するための言語です。旧称はObject Pascal。開発用IDE「Delphi」にあわせ現在の名前に改称されました。

C++Builder

C++Builderは、C/C++を用いてアプリ開発できる統合開発環境 (IDE) 。DelphiのC++版です。コンポーネントによるビジュアル開発、高機能なコードエディターなどで生産性の高い開発ができます。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

0グッド

0クリップ

投稿2019/07/06 09:13

編集2019/07/06 14:25

実現したいこと

四角形や円などの図形と文字列を同時に生成する自作コンポーネントを作成しようとしています.
イメージ説明
例:正方形の上に文字列を書いたインスタンスや円の横に文字列を書いたインスタンス(ペイントで作ったイメージ図)

###実現方法・困っていること
実現したいことに対する実現方法は次のように考えています.
0. 四角形や円などの図形と文字列を同時に生成する独自クラスを作成する.
0. 1で作成したクラスをコンポーネント化する.

その中で1は既に出来ています.簡単に1の独自クラスを説明すると,インスタンス生成時にTShape型とTLabel型のインスタンス生成しています.デフォルトのインスタンス(コンストラクタ利用時)生成時では例1のようなインスタンスが生成でき,メソッドで文字列(TLabel)の位置をずらすことで例2のようなインスタンスが生成できます.
現在,2に取り組んでいます.自作コンポーネントパッケージ自体は情報量の多いDelphiを使い開発し,それをC++Builderにインストールするつもりです.2自体の実現方法は次のように考えています.

  1. TCustomControlクラスを継承したクラスをつくる.
  2. 円や四角形,正方形など描画する.
  3. 文字列を描画する.

1の独自クラスを実現するにはTShape型とTLabel型を同時に生成する必要があるので,TCustomContorlから継承したクラスを作る.2はCanvas, Pen, Brushなどを利用してプロパティ(Shape)で選択した形の図形を作成する.そして,Flabelプロパティ(TLabel型)を図形の上に描画すればよいと考えています.

###困っていること
自作コンポーネントをドラッグアンドドロップでフォーム上にインスタンス生成した後,インスタンスの色をBrushのColorプロパティから変えます.そのあと,フォームのColorプロパティをインスタンスとは異なる色に変えると,図形外部の余白部分が白色がフォームのColorと同じにならなくて困っています.原因は描画するときに矩形領域を白色に変えているからだとは分かるのですが,そうしないと図形外部も塗りつぶされてしまい困っています.描画の順番がおかしいなどご指摘を,どなたかご教授お願いいたします.

###試したこと
図形を描画する順番を1-1~1-3と2-1~2-4で試してみましたがどちらもダメでした.

1-1. penの設定
1-2. Brushの設定
1-3. 図形の描画(EllipseやRoundRectなど)

2-1. 矩形領域を白色で塗りつぶし
2-2. penの設定
2-3. Brushの設定
2-4. 図形の描画(EllipseやRoundRectなど)

イメージ説明
図:stCircleが1-11-3で描画したインスタンス,それ以外が2-12-4で描画したインスタンス

###開発環境
OS:Windows10:64bit
IDE:Embarcadero Delphi 10.3 Community Eddition

###参考情報
開発環境自体はDelphiですが,作成したコンポーネントのパッケージをインストールして使用する環境自体は下記になります.
OS:Windows10:64bit
IDE:Embarcadero C++Builder 10.3 Professional

###ソースコード

Delphi

1unit Door; 2 3interface 4 5uses 6 Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, 7 Vcl.Controls, Vcl.Graphics, Vcl.Forms, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.Dialogs; 8 9type 10 TDoor = class(TCustomControl) 11 private 12 { Private 宣言 } 13 Flabel: TLabel; 14 FShape: TShapeType; 15 16 procedure SetShape(Value: TShapeType); 17 protected 18 { Protected 宣言 } 19 public 20 { Public 宣言 } 21 left: Integer; 22 top: Integer; 23 24 // コンストラクタ(オーバーライド) 25 constructor Create( AOwner: TComponent ); override; 26 procedure Paint; override; 27 published 28 { Published 宣言 } 29 // プロパティにdefaultを付けるとデフォルト値にできる 30 property Shape: TShapeType read FShape write SetShape default stRectangle; 31 // 継承プロパティ(再宣言するとオブジェクトインスペクタに表示できるようになる) 32 property Anchors; 33 property Brush; 34 property Color; 35 property Enabled; 36 property Name; 37 property ParentColor; 38 property Visible; 39 property OnClick; 40 property OnDblClick; 41 end; 42 43procedure Register; 44 45//--------------------------------------------------------------------------- 46implementation 47 48procedure Register; 49begin 50 // 「Samples」パレットにドアを登録 51 RegisterComponents('Samples', [TDoor]); 52end; 53 54 55constructor TDoor.Create( AOwner: TComponent ); 56begin 57 // 継承元のTCustomControlクラスのCreateメソッドの呼び出し 58 inherited Create(AOwner); 59 // 必要かわからないから,試し中 60{ 61 SetBounds(Left, Top, 25, 25); 62 left:= Left; 63 top:= top; 64} 65end; 66 67// WM_PAINTメッセージで起動 68// クライアントエリアに更新領域が存在するときにコール 69procedure TDoor.Paint; 70begin 71 // 四角形の場合 72 if FShape = stRectangle then 73 begin 74 with Canvas do begin 75 // Color色で塗りつぶし 76 Brush.Color:= Color; 77 Brush.Style:= bsSolid; 78 FillRect(Rect(0, 0, Width, Height)); 79 // 黒色で太さ1で枠線描画 80 Pen.Color:= clBlack; 81 Pen.Style:= psSolid; 82 Pen.Width:= 1; 83 Rectangle(Rect(0, 0, Width, Height)); 84 end; 85 end 86 // 円の場合 87 else if FShape = stCircle then 88 begin 89 90 with Canvas do begin 91 if Width <> Height then 92 begin 93 Height:= Width; 94 end; 95{ 96 // 白色で塗りつぶし 97 Brush.Color:= clWhite; 98 Brush.Style:= bsSolid; 99 FillRect(Rect(Left, Top, (Left+Width), (Top+Height))); 100} 101 // Color色で塗りつぶし 102 Brush.Color:= Color; 103 Brush.Style:= bsSolid; 104 // 黒色で太さ1で枠線描画 105 Pen.Color:= clBlack; 106 Pen.Style:= psSolid; 107 Pen.Width:= 1; 108 Ellipse(Left, Top, (Left+Width), (Top+Height)); 109 end; 110 end 111 // 楕円の場合 112 else if FShape = stEllipse then 113 begin 114 with Canvas do begin 115 // フォームのColor色で塗りつぶし 116 Brush.Color:= Color; 117 Brush.Style:= bsSolid; 118 FillRect(Rect(Left, Top, (Left+Width), (Top+Height))); 119 // ↓の図形内部の色を決めるBrushに何を書けばいいかわからない 120 Brush.Color:= Brush.Color; 121 Brush.Style:= bsSolid; 122 // 黒色で太さ1で枠線描画 123 Pen.Color:= clBlack; 124 Pen.Style:= psSolid; 125 Pen.Width:= 1; 126 Ellipse(Left, Top, (Left+Width), (Top+Height)); 127 end; 128 end 129 // 角の丸い四角形の場合 130 else if FShape = stRoundRect then 131 begin 132 with Canvas do begin 133 // 白色で塗りつぶし 134 Brush.Color:= clWhite; 135 Brush.Style:= bsSolid; 136 FillRect(Rect(Left, Top, (Left+Width), (Top+Height))); 137 // Color色で塗りつぶし 138 Brush.Color:= Color; 139 Brush.Style:= bsSolid; 140 // 黒色で太さ1で枠線描画 141 Pen.Color:= clBlack; 142 Pen.Style:= psSolid; 143 Pen.Width:= 1; 144 RoundRect(Left, Top, Width, Height, 50, 50); 145 end; 146 end 147 // 角の丸い正方形の場合 148 else if FShape = stRoundSquare then 149 begin 150 with Canvas do begin 151 if Width <> Height then 152 begin 153 Height:= Width; 154 end; 155 // 白色で塗りつぶし 156 Brush.Color:= clWhite; 157 Brush.Style:= bsSolid; 158 FillRect(Rect(Left, Top, (Left+Width), (Top+Height))); 159 // Color色で塗りつぶし 160 Brush.Color:= Color; 161 Brush.Style:= bsSolid; 162 // 黒色で太さ1で枠線描画 163 Pen.Color:= clBlack; 164 Pen.Style:= psSolid; 165 Pen.Width:= 1; 166 RoundRect(Left, Top, Width, Height, 50, 50); 167 end; 168 end 169 // 正方形の場合 170 else if FShape = stSquare then 171 begin 172 with Canvas do begin 173 if Width <> Height then 174 begin 175 Height:= Width; 176 end; 177 // 白色で塗りつぶし 178 Brush.Color:= Color; 179 Brush.Style:= bsSolid; 180 FillRect(Rect(0, 0, Width, Height)); 181 // 黒色で太さ1で枠線描画 182 Pen.Color:= clBlack; 183 Pen.Style:= psSolid; 184 Pen.Width:= 1; 185 Rectangle(Rect(0, 0, Width, Height)); 186 end; 187 end; 188end; 189 190procedure TDoor.SetShape(Value: TShapeType); 191begin 192 // FShapeが変更されていない場合 193 if FShape <> Value then 194 begin 195 // 新しいコントロール形状を設定 196 FShape:= Value; 197 // 新しい図形の再描画 198 Invalidate(); 199 200 end; 201 202end; 203 204end.

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

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

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

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

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

guest

回答1

0

ベストアンサー

どちらかと言えば VCL の話なので VCL のタグを登録依頼してもらった方が良いかと思います。

VCL では ParentColor プロパティで親コントロールの色と合わせれたと思いますが、その辺の作りはどうなっていますか? Color プロパティは直接設定せずに ParentColor を True に設定して、Color プロパティを参照すれば良いかと思います。

投稿2019/07/06 12:02

atata0319

総合スコア881

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

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

dem0nmichik0

2019/07/06 13:17

atata0319様 回答ありがとうございます.VCLタグの登録は依頼しました. 回答いただいたParentColorプロパティなのですが,継承しているTCustomControlクラスの[プロパティ](http://docwiki.embarcadero.com/Libraries/Rio/ja/Vcl.Controls.TCustomControl_Properties)を調べてみましたが,ParentColorプロパティがないため,設定することができないと思います. 現時点では,ParentColorはプロパティにないため,trueに設定することができない状態です. ParentColorを継承する方法を調べてみます.ありがとうございました.
dem0nmichik0

2019/07/06 13:20

すいません,リンクを貼ろうと思い,Markdownで記述しましたが,貼れてませんでした.
dem0nmichik0

2019/07/06 13:55 編集

たびたびすいません,ParentColorプロパティはないといいましたが,自分でpropertyに追加していました.そしてfalseでした. ただ,trueにしても,図形内部の色がフォームの色と変わる形になり,図形外部は白色のままでした.また,現状,プロパティにBrushプロパティとColorがある状態です.Brushの中にはColorとStyleプロパティがり,ParentColorをtrueにすると,ColorがclGrayになり,Brush->Colorがそのままになっている状態です. 「 property Color;」を記述しているから,Colorプロパティまで継承されてしまうと思い,コメントすると,「Door1.Colorの読み取り中のエラー:プロパティColorが存在しません.エラーを無視して続行しますか?注意:エラーを無視すると,コンポーネントまたはプロパティが失われる可能性があります.」といったエラーポップアップが表示されてしまいます. お手数ですが,原因が分かりましたら,ご教授お願いいたします.
atata0319

2019/07/06 14:01

貼り付けてある TShape と TLabel の ParentColor はどうなっていますか?TShape と TLabel に Color を設定しなければ、ParentColor プロパティはデフォルトで true になっており勝手に背景色が反映されるかと思いますが。
atata0319

2019/07/06 14:09 編集

というかコードを読んでませんでした。TShape と TLabel 関係ありませんね。FillRect に使うブラシを tcanvas の Color にすればよく、tcanvas の ParentColor は true になるようにすればよいかと思うのですが・・・。と思ったら、TControlCanvas ではなく TCustomControl の Canvas に描いてるんですね。
atata0319

2019/07/06 14:13

FillRect に渡す Color プロパティとコントロールの描画に使う Color プロパティは分けましょうってのが解決案ですね。Color プロパティは背景色用です。
dem0nmichik0

2019/07/06 14:35

atata0319様 回答ありがとうございます. 試しに楕円部分のソースコードを修正して,インスタンスのParentColorプロパティをtrueにして実行してみました.その結果,背景色も図形内部も同じ色になってしまう状況です. publishedの箇所で追加した「Color」は背景色用だということは分かり,FillRect用のBrush.Colorに「Color」を設定しました.ただ,Ellipseの塗りつぶし色を決めるBrush.Colorに何を設定してよいかわかりません. 申し訳ありませんが,知っていましたらご教授お願いいたします.
atata0319

2019/07/06 19:09 編集

答えは単純で図形を塗りつぶす色を指定する別のプロパティを追加しましょう。例えば、ShapeColor のようなプロパティをコントロールに追加して、 Brush.Color:= ShapeColor; のようにしましょう。
dem0nmichik0

2019/07/07 06:23

atata0319様 回答ありがとうございます. ご指摘のように,図形内部用のFShapeColorフィールドをprivate,ShapeColorプロパティをpublished,SetShapeColorメソッドをpublicに追加して,SetShapeColorメソッド内で色の変化があったときに「FShapeColorフィールドの設定」と「FShape(コントロールの形状)フィールドを判断して,図形を塗りつぶす(EllipseやRoundRect)」処理を実装したところ,正常に動作しました. 丁寧に教えていただき,ありがとうございました.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問