DOBON.NET DOBON.NETプログラミング掲示板過去ログ

ウインドウ等に隠れても消えないグラフィックを動的に描画する方法について

環境/言語:[VB.NET]
分類:[.NET]

はじめまして。RUGIと申します。VBの描画に関する質問です。

一応、この掲示板とTipsの関連項目は全て読んでみたのですが、なにぶん
vbを始めてまだ2週間の初心者のため、もしかしたら文章の意味がわかって
いないだけで、本当はTips内で簡単に解決できる問題であったとしたら
どうかお許しください。

私は現在、他ウインドウ等に隠れても消えない描画法を使用して
「複数のキャラクターが動くタイプの画面」を構成したいと思っています。

構想の中に「キャラクターどうしが重なり合うケース」も存在するので、
ピクチャボックスにキャラクターを表示しピクチャボックスそのものを
動かすというやり方はダメでした。(重なりが表現できないので)

次に、tips「画像ファイルを表示する」の「1.Control.CreateGraphics
メソッドにより取得する」により、実際にキャラクターを動かすところ
まで一応作りました。 これだと見た目的にはイメージ通りなのですが、
他のウインドウに隠れると簡単に消えてしまいます。

途中で消えてしまうとまずい部分があるので、
tips「画像ファイルを表示する」の「2.Paintイベントハンドラ等では
パラメータから取得できる」を使用し、なんとか動かしてみようとした
のですが力不足でうまくコーディングできませんでした。

もしこれを実現する具体的な方法や別の表現の仕方がありましたら
ご指南どうぞよろしくお願い致します。
えっと‥‥結局のところ、何をお訊ねになりたいのでしょう?

・画像データを描画する方法は解っている
・それを動かすにはどのようにすれば良いかも理解している

 その上で
> もしこれを実現する具体的な方法や別の表現の仕方がありましたら
> ご指南どうぞよろしくお願い致します。
と仰られるということは、コーディングを依頼されてることに他ならないかと。
#勿論、そのような心算で仰られたのではないのでしょうが。

 ポイントを絞って質問された方がレスが付き易いと思いますよ。



‥‥と、これだけというのもなんなので少し。

> ピクチャボックスにキャラクターを表示しピクチャボックスそのものを
> 動かすというやり方はダメでした。(重なりが表現できないので)

フォームやコントロールの形を変える
http://dobon.net/vb/dotnet/form/formregion.html

を利用して、表示する内容に合わせてピクチャ ボックスの形状を変えてあげれば大丈夫そうな気もします。
#画像データに応じた Region を取得する方法? そんなの私は知りません :-p <無責任


> 他のウインドウに隠れると簡単に消えてしまいます。

 描画処理が既にあるのなら、 Paint イベント発生時にもそれをコールするようにすれば良いかと。


> 力不足でうまくコーディングできませんでした。

 どのような結果を期待して、どのようなコーディングをして、どのような結果になったのでしょう?
 詳細が不明なので全くの的外れかもですが、 Invalidate メソッドについて調べられると解決するかも知れません。
深山さん。レス本当にありがとうございました。

どこを中心に質問したら解決できるのかもよくわからなかったので
漠然と質問してしまいました。申し訳ありません。
もう一度書いてみますのでどうかよろしくお願い致します。

◆Tips「画像ファイルを表示する」の

Dim g As Graphics = PictureBox1.CreateGraphics()
g.DrawImage(bitmap, x, y)

この例を流用し、
「キャラ描画→背景の一部を取得しキャラを消去→キャラ再描画」を
繰り返してキャラクターを動かすことはできました。 
でも、この方法だとTipsでも述べられている通り、他のウインドウに隠れると
消えてしまいます。
それで、同Tips内の「Paintイベントハンドラで画像を表示することにより
画像が消えないようにする例」を参考にしようとしました。

e.Graphics.DrawImage(bmp, x, y)

これで「最初のキャラ描画」はうまくいったのですが、次の段階で必要な
「PictureBoxに描かれた画像を取得すること」と
「Paintイベントハンドラで再描画すること」ができなくて悩んでいた次第です。
もしかしたら「超」のつくほど初歩的な質問なのかもしれませんが、
ご指南どうぞよろしくお願いします。

>フォームやコントロールの形を変える

一応ヘルプのGraphicsPathメンバに目を通してみたものの
ドット単位でキャラの形に切り抜く方法が発見できなくてあきらめていました。

>詳細が不明なので全くの的外れかもですが、
>Invalidate メソッドについて調べられると解決するかも知れません。

Invalidate メソッドについて目を通してみました。
なるほどです。たしかにこの項目が核心をついていそうな気がします。
知識が少なすぎてまだ理解できていないですが、もう少し繰り返して
読んでみようと思います。
> これで「最初のキャラ描画」はうまくいったのですが、次の段階で必要な
> 「PictureBoxに描かれた画像を取得すること」と
> 「Paintイベントハンドラで再描画すること」ができなくて悩んでいた次第です。

 前者は用途が今一つ不明なのですが‥‥一応 API を使用すれば可能です。次の URL など参考になるでしょうか。
#他にもっと良い方法があるかも知れませんが、私は知りません(^_^;)

画面、フォーム、ウィンドウを取り込んで印刷する方法
http://support.microsoft.com/default.aspx?scid=kb;ja;161299

 けれども必要性があるのでしたら、描画すべき内容自体を Bitmap オブジェクトとして保持しておいたほうが良さそうな気がします。
<取得する方法を考えるのではなく、逆の発想ですね。
#って我ながら判り辛い説明だなぁ(ーー;)


 後者については、先に Invalidate メソッドの話をしたので必要ない、かな?

> Invalidate メソッドについて目を通してみました。
> なるほどです。たしかにこの項目が核心をついていそうな気がします。
> 知識が少なすぎてまだ理解できていないですが、もう少し繰り返して
> 読んでみようと思います。

 繰り返し読むのも大切だと思いますけど、実際に使ってみたほうが理解が深まると思いますよ。
簡単なサンプルを下記しますので、よろしければ動作を見てくださいな。
#新規 Windows アプリ、デザイン画面で Timer コントロールを配置しておきます。
#尚、直打ちしてるのでタイプミスがあるかも知れません。

    Private p As Point
    
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.Timer1.Interval = 50
        Me.Timer1.Start()
    End Sub
    
    Private Sub Form1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Hadles MyBase.Paint
        e.Graphics.FillEllipse(Brushes.Red, p.X, p.Y, 50, 50)
    EndSub
    
    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        p.Offset(1, 1)
        Me.Invalidate()
    End Sub
再々の質問に対してレスをありがとうございます。

> >「PictureBoxに描かれた画像を取得する」
>必要性があるのでしたら、描画すべき内容自体を Bitmap オブジェクトとして
>保持しておいたほうが良さそうな気がします。
>取得する方法を考えるのではなく、逆の発想ですね。

なるほど。 言われてみればそうですよね。
この件はその方向で解決したいと思います。
我ながら頭が固いなあと思いました。

> >「Paintイベントハンドラで再描画することができない」
>簡単なサンプルを下記しますので、よろしければ動作を見てくださいな。

ほんとに参考になりました。 Invalidate(Rectangle)を使用することによって
なんとか複数のキャラを「消えない描画」によって動かすことができるように
なりました。

ところで、Invalidateを使っての再描画を連続で行わせると、その部分で頻繁に
表示のちらつきが発生するのですが、これを抑えるような策は存在するのでしょ
うか?
ヘルプやWebで「Invalidate・画像表示・ちらつき」などのキーワードで検索して
みたのですが、それらしいものを発見できませんでした。
何か参考になりそうな情報などもし知っておられましたらどうぞよろしくお願い
します。
どういたしまして。少しでもお役に立てたなら何よりです(^^)


> ヘルプやWebで「Invalidate・画像表示・ちらつき」などのキーワードで検索して
> みたのですが、それらしいものを発見できませんでした。

 『ちらつき』では何もヒットしませんでした? んー、他に思い付くのは『再描画』とか『ダブル バッファリング』とかかなぁ‥‥。

 取り敢えず、以前私が参考にしたページを挙げておきます。参考まで。

背景の描画を禁止して再描画時のちらつきをなくすには?
http://www.atmarkit.co.jp/fdotnet/dotnettips/194nopaintbg/nopaintbg.html

ダブル・バッファリングにより描画を行うには?
http://www.atmarkit.co.jp/fdotnet/dotnettips/197doublebuf/doublebuf.html
深山さん、本当に本当にありがとうございます!

お教え頂いたダブルバッファリングを導入することによって
ちらつきも回避でき、自分が始めに思い描いていた通りの
画面表示を実現することができました。

これからもこの掲示板やサイトを読んで勉強させてもらいたいと
思います。 それでは失礼致しますm(_ _)m
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板