PaintBoxでCanvasに描いたときの処理に関して

解決


HH  2010-07-13 10:17:03  No: 38794  IP: 192.*.*.*

PaintBoxのCanvasに図を描いています。

Rectangleを使用して図を描いていますが、そのPaintBoxの手前側にダイアログがある場合、図がうまくかけません。
PaintBox全体を描きたいのに、ダイアログの部分が描かれなかったり、ダイアログ部分以外のところが更新されなかったりします。
ダイアログがPaintBoxの枠の上に重なっていない場合は問題なくうまく描けます。

色々なやり方をしても、うまくできません。
この現象はしょうがないものなのでしょうか?

編集 削除
Delphi大好き  2010-07-13 10:27:57  No: 38795  IP: 192.*.*.*

それはPaintBoxの仕様だったと記憶しています。

PaintBoxは使用メモリがとても少ない代わりに、
描画した内容を再描画する機能が無かったはずです。

その為、他のウインドウ等のダイアログにPaintBoxが隠れてしまうと、
その部分は保持されていないので、再描画された時に白紙になってしまいます。

これを回避するには、素直にImageコンポーネントを使うか、
PaintBoxを拡張して(自分でコンポーネントを作って)機能をつけるしか、
無いと思います。

自分が持っている古いDelphiのフリーコンポーネント集に、
そんなコンポーネントがあったと記憶してます。

因みに、Delphi1や2,3の頃の古い書籍なので、
現在のDelphiに対応している可能性は低いと思います。

編集 削除
igy  2010-07-13 11:34:26  No: 38796  IP: 192.*.*.*

Delphi5 のヘルプによると、

>PaintBox コンポーネントについて
>
>用途
>フォーム上での描画を PaintBox で囲まれた特定の長方形の領域に限定します。 
>
>作業
>・PaintBox の描画にアクセスするには Canvas プロパティを使う
>・PaintBox のキャンバスに描画するには,OnPaint イベントのイベントハンドラに適切なコードを記述する

だそうです。

編集 削除
ぽむぽむ  2010-07-13 11:39:35  No: 38797  IP: 192.*.*.*

TPaintBoxのOnPaint で、図形を描いていますか?
それ以外のタイミングでPaintBoxに描画した内容は、他のウインドウなどで隠れたりすると、消えてしまいます。

編集 削除
HH  2010-07-13 19:56:02  No: 38798  IP: 192.*.*.*

回答ありがとうございます。

OnPaintでもその現象はおきます。

Delphi大好きさんの言っているようにImageを使えば、解決できました。

編集 削除
ぽむぽむ  2010-07-14 09:15:52  No: 38799  IP: 192.*.*.*

PaintBoxのOnPaint で PaintBoxのCanvasに対して描画していますか?
例えば、PaintBox1.Canvas.FrameRect(〜 ではなく Canvas.FrameRect(〜 にしていると
FormのCanvasに描画に行くので、OnPaintで描いても消えてしまいます。

編集 削除
Mr.XRAY  2010-07-18 00:13:41  No: 38800  IP: 192.*.*.*

こんにちは.

>それはPaintBoxの仕様だったと記憶しています。

ですね.
TPaintBoxはTWinContorlの派生コントロールです.
一方,TImageはTGraphicControlの派生コントロールです.

TGraphicContorlはウィンドウを持っていません.マウスやキーボードのイベントを受取れません.
もちろん,受取るようにすることも可能ですが,デフォルトではです.
TGraphiControlのCanvsで描画した内容は,他のフォームが重なっても消えません.
内部で自動処理してくれます.

TWinControlは従来からWindowsにあるコントロールで,これらはマウスやキーイベントを
受取ることができますが,描画内容は他のウィンドウに重なった場合,再描画が必要と
なります.つまり,再描画の際に発生するOnPaintイベント内で,Canvasに記述することに
なります.

これ以上は,長くなるので,ネットで調べてください.

>OnPaintでもその現象はおきます。

そういう現象を経験したことがありません.
具体的なコードがあれば,検討できますが,もし本当にそうであれば,そのTPaintBoxか
Delphiか,OSの一部が破損されているのかも知れません(笑).

編集 削除
KHE00221  2010-07-18 03:35:00  No: 38801  IP: 192.*.*.*

説明変だぞ

編集 削除
KHE00221  2010-07-18 03:52:50  No: 38802  IP: 192.*.*.*

TImage.Canvas は内部でもっている TPicutre の Canvas
それを Paint で描画しているだけ

Formの上にPaintBoxを置いて

 Memo1.Lines.Add (IntToStr(PaintBox1.Canvas.Handle));
 Memo1.Lines.Add (IntToStr(Form1.Canvas.Handle));

とやるとわかるけど  ハンドルが同じ

つまり PaintBoxに描画しているわけではなく PaintBoxを置いている
フォームに直接描画しているわけ

つまり保存されていないので、消える

TBitmapをPaintBoxと同じサイズにして描画をTBitmapにして
PaintBox.Paint で Bitmap を Draw すれば Image と同じになる

編集 削除
tor  2010-07-18 11:47:13  No: 38803  IP: 192.*.*.*

その説明も正確じゃないですね。
PaintBoxのOnPaintの中で
  PaintBox1.Canvas.TextOut(0, 0, IntToStr(PaintBox1.Canvas.Handle));
  PaintBox1.Canvas.TextOut(0, 10, IntToStr(Form1.Canvas.Handle));
とやると、ちゃんと別々のハンドルが表示されます。
何故かというと、OnPaintを呼び出す前にBeginPaintして、そのDCを使うようにしているから。
(OnPaint以外の場所でCanvasを要求された時は、仕方がないので親のCanvasを借ります)

BeginPaintでもらった方のDCには、描画が必要な領域以外をクリップするよう設定がされています。
一方、FormのCanvasを使うとそのような設定はされていません。
両者を混ぜて使ったり、PaintBoxではなくFormの座標を使って描画したりすると
> ダイアログの部分が描かれなかったり、ダイアログ部分以外のところが更新されなかったり
といった現象が起こりえます。

編集 削除