[delphi-users:3063] FillRectとRectangleの差

480 views
Skip to first unread message

dev

unread,
Mar 20, 2013, 11:18:04 PM3/20/13
to delphi...@freeml.com
いつもお世話になります。devです。

さて、今回はTCanvasのFillRectとRectangleについてですが。
私の認識では
FillRect - Brushにて矩形の内部を塗る
Rectangle - Penにて矩形の枠を描画しBrushで内部を塗る
と考えておりました。

そこで、FormにTPaintBoxを2つ配置してTagプロパティに0,1を振って
以下のコードをOnPaintに書きます。
 with( TPaintBox( Sender ) )do
 begin
  Canvas.Brush.Style := bsSolid; //bsDiagCross;
  Canvas.Brush.Color := clBlack;
  Canvas.Pen.Color := clRed;
  case( Tag )of
  0: Canvas.FillRect( ClientRect );
  1: Canvas.Rectangle( ClientRect );
  end;
 end;

BrushのStyleがbsSolidの場合は思っていた通りの描画になりますが
Styleに例えばbsDiagCrossを指定すると
Rectangleの方はちゃんと指定したBrushで内部も塗られるのに対し
FillRectの方は真っ黒に塗られます。

これは、正しい描画なのでしょうか?
私の認識が間違っているのでしょうか?

よろしくお願いします。



MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
あなたの作ったランキングが副収入になる!
http://ad.freeml.com/cgi-bin/sa.cgi?id=jCE1v
------------------------------------------------------[freeml byGMO]--

DEKO

unread,
Mar 21, 2013, 12:52:02 AM3/21/13
to delphi...@freeml.com
こんにちは。
> FillRect - Brushにて矩形の内部を塗る
> Rectangle - Penにて矩形の枠を描画しBrushで内部を塗る

ですです。

この仕様であるため、Brush.Style が bsSolid である場合はどちらも同じように描画されます。

ただ、TCanvas.FillRect() の場合、
NT 系の OS だと "ハッチの背景色" が黒になっているので、
これを変更してやらなければなりません。

SetBkColor(Canvas.Handle, ColorToRGB(clBtnface)); // これを追加
case( Tag )of
 0: Canvas.FillRect( ClientRect );
 1: Canvas.Rectangle( ClientRect );
end;

[SetBkColor (MSDN)]
http://msdn.microsoft.com/ja-jp/library/cc410583.aspx

> 背景モードが OPAQUE の場合、
> 背景色は、スタイル付きの複数の線の隙間、
> ブラシのハッチ線の隙間、文字の背景を塗りつぶすのに使われます。

昔、この情報をどこかで見た記憶があったのですが、
今 Web 上を探しても見つかりませんでした。

> FDELPHI MES( 8)
> [03708] 網掛けが巧く出来ません。

そりゃ、見つかりませんわね (^^;A

--
by DEKO
-----------------------------
http://ht-deko.minim.ne.jp/
de...@ht-deko.minim.ne.jp
-----------------------------


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
在宅OK・初心者・未経験者歓迎のライター案件募集中!
http://ad.freeml.com/cgi-bin/sa.cgi?id=jCFJS
------------------------------------------------------[freeml byGMO]--

dev

unread,
Mar 21, 2013, 1:33:45 AM3/21/13
to delphi...@freeml.com
DEKOさん、早速の返信ありがとうござます。

(2013/03/21 13:52), DEKO wrote:
> ただ、TCanvas.FillRect() の場合、
> NT 系の OS だと "ハッチの背景色" が黒になっているので、
> これを変更してやらなければなりません。
> SetBkColor(Canvas.Handle, ColorToRGB(clBtnface)); // これを追加

なるほど。
TBrushのPropertyにColorしか無い為、ハッチの背景色の指定方法が
判りませんでした。(というか、背景色の存在自体判らなかった)
バックカラーを設定しないといけないという事ですね。

で、Rectangleで矩形を書く場合は、Canvasの背景色に自動で設定される
という認識でいいのでしょうか。




MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
【キャンペーン】広告プログラム参加でamazonギフトが1000円分貰える!
http://ad.freeml.com/cgi-bin/sa.cgi?id=jCGnN
------------------------------------------------------[freeml byGMO]--

DEKO

unread,
Mar 21, 2013, 7:10:16 AM3/21/13
to delphi...@freeml.com
> で、Rectangleで矩形を書く場合は、Canvasの背景色に自動で設定される
> という認識でいいのでしょうか。

んーちょっとだけ違います。

Brush が作られる時、ブラシスタイルが bsSolid の場合には、
SetBkMode() で TRANSPARENT が指定されます。

なので、

Canvas.Brush.Style := bsDiagCross;
Canvas.Brush.Color := clBlack;
Canvas.Pen.Color := clRed;
SetBkMode(Canvas.Handle, OPAQUE); // さらにこれを追加
SetBkColor(Canvas.Handle, ColorToRGB(clBlue)); // これを追加
case( Tag )of
 0: Canvas.FillRect( ClientRect );
 1: Canvas.Rectangle( ClientRect );
end;

こうしてやれば、どちらも黒い線のハッチで青い背景になります。
ですが、規定のままだと

SetBkMode(Canvas.Handle, TRANSPARENT);

を指定しているので、Rectangle() の場合には SetBkColor() でハッチの背景色を
指定したとしても透過してしまいます (フォームの色で塗りつぶされている訳ではない)。
FillRect() は SetBkMode() の影響を受けませんので、ハッチの背景色は透過しません。

# Win9x では FillRect() のハッチの背景色は
# ブラシカラーの反転色で描画されます (確か)。

--
by DEKO
-----------------------------
http://ht-deko.minim.ne.jp/
de...@ht-deko.minim.ne.jp
-----------------------------


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
デートで☆ファミリーで☆行ってみたいアミューズメントパーク&遊び場ランキング
http://ad.freeml.com/cgi-bin/sa.cgi?id=jCLbq
------------------------------------------------------[freeml byGMO]--

DEKO

unread,
Mar 21, 2013, 7:26:03 AM3/21/13
to delphi...@freeml.com
> Brush が作られる時、ブラシスタイルが bsSolid の場合には、
> SetBkMode() で TRANSPARENT が指定されます。

何か訳わかんないこと書いちゃいました。
詳細については (Vcl.)Graphics.pas の中を確認してみてください。

--
by DEKO
-----------------------------
http://ht-deko.minim.ne.jp/
de...@ht-deko.minim.ne.jp
-----------------------------


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
今年の花粉飛散量は昨年より150%UPの予想!花粉症対策グッズランキング
http://ad.freeml.com/cgi-bin/sa.cgi?id=jCLpk
------------------------------------------------------[freeml byGMO]--

DEKO

unread,
Mar 21, 2013, 7:30:03 AM3/21/13
to delphi...@freeml.com
bsSolid の時: SetBkMode(FHandle, OPAQUE)
それ以外の時: SetBkMode(FHandle, TRANSPARENT)

です。

--
by DEKO
-----------------------------
http://ht-deko.minim.ne.jp/
de...@ht-deko.minim.ne.jp
-----------------------------


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
春が待ち遠しい!今からチェック!東海地方のお花見名所ランキング
http://ad.freeml.com/cgi-bin/sa.cgi?id=jCLsk
------------------------------------------------------[freeml byGMO]--

dev

unread,
Mar 21, 2013, 7:58:00 PM3/21/13
to delphi...@freeml.com
DEKOさん。丁寧な解説ありがとうございます。

(2013/03/21 20:30), DEKO wrote:
> bsSolid の時: SetBkMode(FHandle, OPAQUE)
> それ以外の時: SetBkMode(FHandle, TRANSPARENT)

なるほど、透過するかバックカラーで塗っちゃうかの差って事ですね。
と思ってGraphics.pasを覗いていたのですが。

BrushのデフォルトのBkModeが上記仕様になってます。(CreateBrush)
だったら、同じBrushで塗る事になるので、FillRectもRectangleも
同様な描画になるのでは?と思ったのですが。。。

FillRectはSetBkMode()の影響を受けない。という事で違う描画になると・・・

もう、既に無知をさらしていますので、訊くは一時の恥という事で、
「FillRectはSetBkModeの影響を受けない。」を調べてみたのですが
msdnのFillRectのページとかを見ても、そのような記述は見当たりません。
そのような制約?決まり事?の情報はどこら辺で仕入れられるのでしょうか?




MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
初めての引越しでやってしまいがちな失敗<困った!>10選
http://ad.freeml.com/cgi-bin/sa.cgi?id=jCSgX
------------------------------------------------------[freeml byGMO]--

中村@ブレーン

unread,
Mar 21, 2013, 9:08:08 PM3/21/13
to delphi...@freeml.com
中村です。

dev さんは書きました:
>さて、今回はTCanvasのFillRectとRectangleについてですが。
>私の認識では
>FillRect - Brushにて矩形の内部を塗る
>Rectangle - Penにて矩形の枠を描画しBrushで内部を塗る
>と考えておりました。

昔の Halbow さんとの FillRect に関する議論です。
参考になれば

[Delphi-ML:57465] Brush パターンをCombBoxに描画する
http://www2.big.or.jp/~osamu/Delphi/delphi-browse.cgi?index=057465

----------
東京都 日野市 中村拓男


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
魅力的すぎる!心が弾む、絶対行きたい工場見学ランキング
http://ad.freeml.com/cgi-bin/sa.cgi?id=jCTev
------------------------------------------------------[freeml byGMO]--

Mr.XRAY

unread,
Mar 21, 2013, 9:16:12 PM3/21/13
to delphi...@freeml.com
【[delphi-users:3069] Re: FillRectとRectangleの差】 へのレスです.

こんにちは.Mr.XRAYです.

>Rectangle - Penにて矩形の枠を描画しBrushで内部を塗る

いや,違うと思いますよ.単に矩形を描画するだけだと思いますよ.
塗り潰しはしません.塗り潰しをするのが,FillRect です.
ヘルプの説明のそのままだと思いますよ.

>で、Rectangleで矩形を書く場合は、Canvasの背景色に自動で設定される
>という認識でいいのでしょうか。

前の,元の背景のままです.したがって,

>FillRectはSetBkMode()の影響を受けない

結果的にはそうなりますが.この言い方はちょっと疑問ですね.
だって,単に矩形 (四角形) を描画するだけですから.背景は元のままです.

// テストコード
procedure TForm1.PaintBox1Paint(Sender: TObject);
var
ARect : TRect;
begin
 with( TPaintBox( Sender ) )do
 begin
  Canvas.Brush.Style := bsSolid;

//TPaintBox全体を塗り潰す
Canvas.Brush.Color := clYellow;
  Canvas.FillRect( ClientRect );

//Rectangleの描画サイズと位置を変更
ARect := ClientRect;
InflateRect(ARect, -Width div 4, -Height div 4);

//四角形を描画
Canvas.Pen.Color := clRed;
  Canvas.Rectangle( ARect );
 end;
end;


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
10kg以上の大幅減量に成功した人がオススメしているダイエット10選
http://ad.freeml.com/cgi-bin/sa.cgi?id=jCTk8
------------------------------------------------------[freeml byGMO]--

中村@ブレーン

unread,
Mar 21, 2013, 10:05:02 PM3/21/13
to delphi...@freeml.com
Mr.XRAY さんは書きました:
>いや,違うと思いますよ.単に矩形を描画するだけだと思いますよ.
>塗り潰しはしません.塗り潰しをするのが,FillRect です.
>ヘルプの説明のそのままだと思いますよ.

中村です。久しぶりに Graphics.pas(XE2) を覗いてみたけど、
変わってないです。Windows API の Rectangle を呼んでいる
だけ。なので、塗りつぶしもします。

GDI+ や .NET と混同されていないでしょうか?

----------
東京都 日野市 中村拓男


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
新入生のママ必見!ママ友関係を円滑にする10のオキテランキング
http://ad.freeml.com/cgi-bin/sa.cgi?id=jCTS8
------------------------------------------------------[freeml byGMO]--

dev

unread,
Mar 21, 2013, 10:18:21 PM3/21/13
to delphi...@freeml.com
Mr.XRAYさん。返信ありがとうございます。

テストコードを動かしてみました。

違っていたら申し訳ないのですが、
描画サイズ位置を変更して四角を描画していますが、
単に同じBrushでRectangleしているので黄色の四角が描画される。
という事ではないのでしょうか。
下に書きましたが、Rectangleの前に
Canvas.Brush.Color := clWhite;
を入れると、白の四角が描画されます。
Rectangleが四角の中をBrushで塗りつぶしている事になりませんでしょうか。

(2013/03/22 10:16), Mr.XRAY wrote:
> // テストコード
> procedure TForm1.PaintBox1Paint(Sender: TObject);
> var
> ARect : TRect;
> begin
>  with( TPaintBox( Sender ) )do
>  begin
>   Canvas.Brush.Style := bsSolid;
> //TPaintBox全体を塗り潰す
> Canvas.Brush.Color := clYellow;
>   Canvas.FillRect( ClientRect );
> //Rectangleの描画サイズと位置を変更
> ARect := ClientRect;
> InflateRect(ARect, -Width div 4, -Height div 4);
> //四角形を描画
> Canvas.Pen.Color := clRed;
   Canvas.Brush.Color := clWhite <-追加
>   Canvas.Rectangle( ARect );
>  end;
> end;

もっと、奥深い事なのかな。。。。
すみません。ちょっと低空飛行で。




MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
Facebookで思わずいいね!を躊躇してしまうランキング
http://ad.freeml.com/cgi-bin/sa.cgi?id=jCUda
------------------------------------------------------[freeml byGMO]--

DEKO

unread,
Mar 21, 2013, 10:39:22 PM3/21/13
to delphi...@freeml.com
冗長になりますが、コードを貼っておきます。

procedure TForm1.PaintBox_Solid_Transparent(Sender: TObject);
begin
 with TPaintBox(Sender) do
  begin
   Canvas.Pen.Color  := clRed;          // ペン色   (赤)
   Canvas.Brush.Color := clBlue;          // ブラシ色  (青)
   Canvas.Brush.Style := bsSolid;         // ブラシ   (ソリッドブラシ)
   SetBkColor(Canvas.Handle, ColorToRGB(clGreen)); // 背景色   (緑)
   SetBkMode(Canvas.Handle, TRANSPARENT);     // 背景モード (透過)
   case Tag of

    // 青 (Brush.Color) で塗りつぶされる
    0: Canvas.FillRect(ClientRect);

    // 赤 (Pen.Color) で枠が描画され、
    // 青 (Brush.Color) で塗りつぶされる
    1: Canvas.Rectangle(ClientRect);

   end;
  end;
end;

procedure TForm1.PaintBox_Solid_Opaque(Sender: TObject);
begin
 with TPaintBox(Sender) do
  begin
   Canvas.Pen.Color  := clRed;          // ペン色   (赤)
   Canvas.Brush.Color := clBlue;          // ブラシ色  (青)
   Canvas.Brush.Style := bsSolid;         // ブラシ   (ソリッドブラシ)
   SetBkColor(Canvas.Handle, ColorToRGB(clGreen)); // 背景色   (緑)
   SetBkMode(Canvas.Handle, OPAQUE);        // 背景モード (透過なし)
   case Tag of

    // 青 (Brush.Color) で塗りつぶされる
    0: Canvas.FillRect(ClientRect);

    // 赤 (Pen.Color) で枠が描画され、
    // 青 (Brush.Color) で塗りつぶされる
    1: Canvas.Rectangle(ClientRect);

   end;
  end;
end;

procedure TForm1.PaintBox_Hatch_Transparent(Sender: TObject);
begin
 with TPaintBox(Sender) do
  begin
   Canvas.Pen.Color  := clRed;          // ペン色   (赤)
   Canvas.Brush.Color := clBlue;          // ブラシ色  (青)
   Canvas.Brush.Style := bsDiagCross;       // ブラシ   (ハッチブラシ)
   SetBkColor(Canvas.Handle, ColorToRGB(clGreen)); // 背景色   (緑)
   SetBkMode(Canvas.Handle, TRANSPARENT);     // 背景モード (透過)
   case Tag of

    // 青 (Brush.Color) でハッチが描画され、
    // 緑 (SetBkColor) の背景色になる。
    0: Canvas.FillRect(ClientRect);

    // 赤 (Pen.Color) で枠が描画され、
    // 青 (Brush.Color) でハッチが描画され、
    // 背景は透過する。
    1: Canvas.Rectangle(ClientRect);

   end;
  end;
end;

procedure TForm1.PaintBox_Hatch_Opaque(Sender: TObject);
begin
 with TPaintBox(Sender) do
  begin
   Canvas.Pen.Color  := clRed;          // ペン色   (赤)
   Canvas.Brush.Color := clBlue;          // ブラシ色  (青)
   Canvas.Brush.Style := bsDiagCross;       // ブラシ   (ハッチブラシ)
   SetBkColor(Canvas.Handle, ColorToRGB(clGreen)); // 背景色   (緑)
   SetBkMode(Canvas.Handle, OPAQUE);        // 背景モード (透過なし)
   case Tag of

    // 青 (Brush.Color) でハッチが描画され、
    // 緑 (SetBkColor) の背景色になる。
    0: Canvas.FillRect(ClientRect);

    // 赤(Pen.Color) で枠が描画され、
    // 青 (Brush.Color) でハッチが描画され
    // 緑 (SetBkColor) の背景色になる。
    1: Canvas.Rectangle(ClientRect);

   end;
  end;
end;

ペン色 / ブラシ色 / 背景色 を区別すれば混乱しにくいのではないかと思います。

--
by DEKO
-----------------------------
http://ht-deko.minim.ne.jp/
de...@ht-deko.minim.ne.jp
-----------------------------


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
新アプリ「freemlトーク」で気軽に会話を楽しもう!
http://ad.freeml.com/cgi-bin/sa.cgi?id=jCUuF
------------------------------------------------------[freeml byGMO]--

dev

unread,
Mar 21, 2013, 10:50:11 PM3/21/13
to delphi...@freeml.com
中村様。返信ありがとうございます。

(2013/03/22 10:08), 中村@ブレーン wrote:
> 昔の Halbow さんとの FillRect に関する議論です。
> 参考になれば
>
> [Delphi-ML:57465] Brush パターンをCombBoxに描画する
> http://www2.big.or.jp/~osamu/Delphi/delphi-browse.cgi?index=057465

興味深く読ませていただきました。
まだ、全て深く理解してたわけではありませんが、何となく判ってきました。

Halbowさんの書いた通り
>1.ハッチブラシを使うときは、TCanvas.FillRect() を使わないこと
>2.代わりに SetBkColor() で背景色を設定して、APIを直接つかうこと
>3.2.の時は、背景モードを必ず OPAQUE にすること

と、取敢えずは呪文として覚えておきます。
有難うございます。



MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
シュワちゃん主演!映画『ラストスタンド』試写会へご招待
http://ad.freeml.com/cgi-bin/sa.cgi?id=jCU45
------------------------------------------------------[freeml byGMO]--

dev

unread,
Mar 21, 2013, 10:54:02 PM3/21/13
to delphi...@freeml.com
DEKOさん、何度もありがとうございます。

一つ一つ確認させていただきます。
ありがとうございます。
MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
ランキングを作るだけでお小遣いがもらえる!
http://ad.freeml.com/cgi-bin/sa.cgi?id=jCU8e
------------------------------------------------------[freeml byGMO]--

Mr.XRAY

unread,
Mar 21, 2013, 10:56:40 PM3/21/13
to delphi...@freeml.com
【[delphi-users:3072] Re: FillRectとRectangleの差】 へのレスです.

こんにちは.Mr.XRAYです.

>変わってないです。Windows API の Rectangle を呼んでいる
>だけ。なので、塗りつぶしもします。

あれれっ,失礼しました.「塗り潰はしない」というのは表現がよくなかっ
たですね.現在の Brush での塗り潰しですね.
dev さんも,混乱させてしまって申し訳ありません.


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
あなたの知っている順位やこだわりを表現しよう!
http://ad.freeml.com/cgi-bin/sa.cgi?id=jCUAR
------------------------------------------------------[freeml byGMO]--

Mr.XRAY

unread,
Mar 21, 2013, 10:59:53 PM3/21/13
to delphi...@freeml.com
【[delphi-users:3077] Re: FillRectとRectangleの差】 へのレスです.

>「塗り潰はしない」というのは表現がよくなかったですね.

訂正します.
間違っていますね.


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
あなたの作ったランキングが副収入になる!
http://ad.freeml.com/cgi-bin/sa.cgi?id=jCUDX
------------------------------------------------------[freeml byGMO]--

Reply all
Reply to author
Forward
0 new messages