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

解決


HH  2010-07-13 19:17:03  No: 38794

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

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

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


Delphi大好き  2010-07-13 19:27:57  No: 38795

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

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

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

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

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

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


igy  2010-07-13 20:34:26  No: 38796

Delphi5 のヘルプによると、

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

だそうです。


ぽむぽむ  2010-07-13 20:39:35  No: 38797

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


HH  2010-07-14 04:56:02  No: 38798

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

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

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


ぽむぽむ  2010-07-14 18:15:52  No: 38799

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


Mr.XRAY  2010-07-18 09:13:41  No: 38800

こんにちは.

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

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

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

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

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

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

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


KHE00221  2010-07-18 12:35:00  No: 38801

説明変だぞ


KHE00221  2010-07-18 12:52:50  No: 38802

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 20:47:13  No: 38803

その説明も正確じゃないですね。
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の座標を使って描画したりすると
> ダイアログの部分が描かれなかったり、ダイアログ部分以外のところが更新されなかったり
といった現象が起こりえます。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加