BITBLT後の画像が消えないようにするには?

解決


どこか行きたいパパ  2005-05-04 21:38:07  No: 121415

2度目の投稿です。
BITBLTで以下のようにすると
        Dim Data_g = Graphics.FromImage(DataArea.Image)
                Data_g.Drawline等
        Dim MainPic1DC As Integer
        Dim api As Boolean
        MainPic1DC = GetDC(Picture1.Handle)
        api = BitBlt(MainPic1DC, 100, 100, 150, 150, MainPic1DC, 0, 0, SRCCOPY)
意図した通り表示はされるのですが他のウインドウがかぶると消えてしまいます。そこで以下のようにしたのですがその位置に黒色の箱が描かれる
だけです。どこに問題があるのか皆目わかりません。
BITBLT後の画像が消えないようにしたいのです。
どなたかご教示・アドバイスをいただけないでしょうか?
        Dim Data_g = Graphics.FromImage(DataArea.Image)
              Data_g.Drawline等
        Dim MainPic1DC As Integer
        Dim api As Boolean
        Dim g_MemoryBufferDC As IntPtr = Data_g.GetHdc()
        MainPic1DC = GetDC(Picture.Handle)
        api = BitBlt(MainPic1DC, 100, 100, 150, 150, g_MemoryBufferDC.ToInt32, 0, 0, SRCCOPY)


どこか生きたいパパ  2005-05-04 21:41:48  No: 121416

すいません。上のGetDC(Picture.Handle)は
GetDC(DataArea.Handle)の間違いでした。
よろしくお願いいたします。


ガッ  2005-05-05 04:55:00  No: 121417

.NETは分かりませんが、およそPaintイベントで再描写するのが普通なのでは?


どこか行きたいパパ  2005-05-05 19:43:15  No: 121418

やはり、そうなんですよね。
ただVB5でAutoRedraw=Trueで手間なしプログラム
で楽してきた身には、なんで一度書いたものを再描画しなければいけ
ないんだ!!という感覚なんです。(メモリの節約とかあるんでしょうが)
そのためにコーディングの量が倍増なんて馬鹿らしいと思いますので
何とかならないでしょうか?
ちなみにVB.NETです。


マグ  2005-05-05 23:39:46  No: 121419

再描画って上記のソースを2回、同じことを記述するのですか?

もし、そうだったら、上記のソースをサブルーチンしてしまい、
そのサブルーチンをCallして、描画するという方法は出来なかったのでしょうか?


mimo  2005-05-05 23:50:39  No: 121420

VB.NETはわかりませんが、VB6でなら
BitBlt関数で画像をコピーした後
Picture1.Picture = Picture1.Image
で画像を保持できます
もちろんAutoRedraw=Trueの場合に限ります
VB.NETでそのようなことは出来ないでしょうか?


ガッ  2005-05-06 06:04:58  No: 121421

ノ<.NETをちょっと弄ってみましたが、やっぱりPaintイベントでできますたw
私は、描写する線や点の情報を保持するのではなく、
動作中に静的に存在するBitmapオブジェクトに描写し、
必要なときにそのBitmapオブジェクト全体を描写するという風にしました。
…まぁ、ゴリゴリやっただけです(orz


さるべーじ  2005-05-06 12:16:44  No: 121422

もともとWindows OSでの再描画は自己責任(個々のプログラム側の責任)です。
ウィンドウの前後関係が変わる等再描画が必要になった場合には、
OS側から再描画を促すメッセージが流れてきて、プログラム側で対処するといぅ。

VB6までのPictureBoxではそのコントロール自身が描画結果をビットマップ
イメージとして保持、Paintメッセージが流れてくると自動的にその
ビットマップイメージを再描画するといぅ仕組みを持っていたんですが。

この方式の欠点としては、
  ・ビットマップイメージを流し込む動作しかできない。
  ・のろい。(ちらつきやすい)
があり、特に「VBではゲームを作りにくい」と言われる要因のひとつとなっていました。

.NET Framework上(下?)で動作するVB.NETになった際に、このへんの仕様が
他言語と統一(てゅうかWindows OSの仕様に準拠)されました。
PictureBoxはコンテナとしての位置付けからも外され、勝手に再描画する機能もなくなり、
純粋に描画用のウィンドウとしての扱いになったんですね。

mimoさんの言われるように、VB6まではImageプロパティが持つイメージを
Pictureプロパティに流し込む(正確にはちょっと違いますが)ことで
静的にイメージを保持できる簡便さを持っていましたが、他方でそれは
VBのPictureBoxの限界にもなっていたわけで。

VB6と同等の機能を実装するのであれば、ガッさんが実践されたよぅに
静的なBitmapオブジェクトを生成して自己管理していくことで可能です。

> そのためにコーディングの量が倍増なんて馬鹿らしいと思いますので

従来ソースのあちこちに書き散らかしていた描画ロジックを一ヶ所にまとめ、
Paintイベントのトリガで動作するようにするだけですので
コーディング量としてはさほど増減しないのではないでしょうか。

どちらかといぅと、旧来の手法からソース組み立ての発想を変えていく必要が
あるという点で抵抗感があるのではないかなぁと思います。


どこか行きたいパパ  2005-05-07 04:36:15  No: 121423

アドバイスありがとうございます。
確かにそのようにして解決できると思いますし他に手段がなければ
そうしようと考えていたところです。
ただ以下のようなコードで再描画属性(この言葉正しいか疑問ですが)
を持ったように見える動作をするものですから。
       Dim Data_g = Graphics.FromImage(DataArea.Image)
             Data_g.DrawString....
             Data_g.Line....
       DataArea.Image = DataArea.Image
何か手段があるのではと考えたもので..


M.Sx  2005-05-20 09:04:33  No: 121424

質問の意図と違っていたらごめんなさい。
.NETのGraphicsオブジェクトは、Paintイベント内で、
パラメータから得られるe.Graphicsを使わないと
Windowが重なったときなどは消えてしまいます。
(Paintイベント内でやってててもだめです。)
コードを見ると自分で作っているものを使っているようなので。

Graphicsオブジェクトを引数にする描画関数を作って、
全部描画したくないときやユーザーのキー入力の時は自分で
  dim g as Graphics = me.CreateGraphics
のように描画オブジェクトから作った
Graphicsオブジェクトを渡し、Paintイベントからはe.Graphicsで
描画してあげるようにすれば描画関数は一つで済みます。

描画順としてはBitBltした後、.NETの描画関数で描くということに
なると思います。

※尚、自分で作ったGraphicsオブジェクトは使い終わったら
  Releaseしてください。


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

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






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