トップ回答者
描画した画面に別のWIN画面が上に重なった後外れると重なり部分の描画画面が消えてしまいます。

質問
回答
すべての返信
-
どうやってグラフを描画しているのでしょうか?
Windows アプリケーションは基本的に、重なった部分についてもう一度描き直す、再描画という処理が必要になっています。
VB6 の頃はプロパティの設定によっては勝手に実行されたかもしれませんが、.NET 世代の VB2005 では基本的に自身でそのコードを書かないといけません。
下記のページにあるように、Paint イベントで描画するようにするか、一度、Bitmap に描きこんでしまって、それを Image プロパティに設定するかなどの対応を取る必要があります。
http://dobon.net/vb/dotnet/graphics/pictureboximageanddrawimage.html
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。 -
Azulean様
早速回答をいただき ありがとうございます。
再描画の処理を行う必要がある事は 判りました。現在 Dim g as graphics と定義してg.DrawLine / g.FillRectangle で
描画しています。ご案内頂いたURLを参考にしてBitmapに一度描きこんでPaintイベントで再描画したら うまく描画はできました。
しかしBitmapに描きこむタイミング=”他の画面が重なった時” をイベントの中から探していますが見つけられずにいます。
windows対応の基本常識レベルの質問で申し訳ありませんがヒントだけでも よろしくお願いします。 -
外池と申します。
2段階のステップがあることはご理解されてますよね? Bitmapにグラフを描くステップと、そのBitmapをFormに描くステップと。
A)あるBitmapが既に用意されているとして、ユーザーはアプリケーション自身の「窓」も、他のアプリケーションの「窓」も、チャカチャカ勝手に動かしますから、「窓」が後ろに隠れたり前に現れたり、画面の縁に隠れたりまた現れたり、その都度再描画が必要になります。これは、PaintイベントでOSから通知が来ますので、その都度BitmapをFormに描けば良いわけです。
B)それに先立つBitmapに肝心のグラフを描くのは、uri_uriさんのお考え次第で、どのタイミングでも良いのですが・・・。普通は、ユーザーがボタンを押したりしたときに、データを整理してグラフに描く動作をする、という感じではないでしょうか。
で・・・、何が見つからないのか・・・、と推察するに、A)のPaintイベントと、B)のBitmapに描くところが分離しちゃっていて、プログラムの実行として繋がらないということでしょうか?
だとすれば、2つ解決方法があります。私としては前者がお奨めです。
ひとつは、アプリからOSに再描画を促す方法があります。FormのInvalidateメソッドです。そうすると、OSはA)の動作をしてくれるのでPaintイベントが発生します。厳密にPaintイベントがいつ発生するかはOS任せなので、グラフの描画がアニメーションのようなものになる場合は注意が必要です。UpdateメソッドやRefreshメソッドも調べてみてください。
もうひとつは、B)でBitmapが用意できたら、FormのCreateGraphicsメソッドでGraphicsオブジェクトを生成して、そこにBitmapを描いてやればOKです。ただし、このGraphicsオブジェクトは描画が終わったらDisposeしてください。
(ホームページを再開しました) -
しかしBitmapに描きこむタイミング=”他の画面が重なった時” をイベントの中から探していますが見つけられずにいます。
ご質問の意図を掴めていないのかもしれませんが、Paint イベントは、他の画面が重なった後、その画面がどけられた時など、画面を再描画する必要がある時に呼び出されます。
「他の画面が重なった」というピンポイントのイベントはないと思います。
ところで、Bitmap に一度書き込まないといけないような状況なのでしょうか?
Paint イベントで得られる e.Graphics に直接書き込むのは速度面などの事情で実現できないのでしょうか?
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。 -
外池様
ご回答をありがとうございます。
再描画はOSが勝手に処理してくれるとの事なので問題は画像を保存するタイミングです。
画像は毎秒6ラインほどのスピ-ドで追加されています。ですから保存するタイミングは
最後まで残しておいて上に別画像が重なった瞬間を保存したいのです。
そのイベントがないとの事で今回FormイベントのDeactivate を使ってみました。
●Deactivateイベントが発生したらBitmapに画面を保存する。 g.CopyFromScreen():g.Dispose()
●OSからPaintイベントが来たらBitmapを描画する。 e.Graphics.DrawImage()
これで静止画像なら問題ないレベルと思います。
今回は画像が常に追加されているので2つのイベントの時間差部分に画像のない所が
当然の事ながら発生してしまいました。
Invalidateメソッドも試してみました。再描画をアプリから指定できるので便利そうです。
しかし今回は相手の画面の動きが判らないのでOSまかせが簡単です。
まあ 今回はこれで妥協かな と言うレベルです。
ありがとうございました。 -
外池です。
画像が時々刻々更新されるタイプのアプリなんですね。そこ、大事なところなので、最初に仰ってもらわないと・・・(笑)
私は、時々刻々チャート紙にプロットされていくような感じでグラフを描画するアプリを作ったことがあります。計測器からデータが流れ込んでくるタイプのものと、アプリ自身がちょっとした時間依存のシミュレーターで自らデータを吐き出すタイプのものと・・・。
いずれも、時々刻々フォームの表示を更新するには、Timerコントロールのイベントを使います。1秒に1回でも、1秒に数回でも、定期的にイベントを発生させられますので、その都度Form.Invalidateをしてやるわけです。
データの流れ込んでくる早さと、画面の表示を同期させることは、必ずしも必須ではありません。画面に描く画像が大きい場合、早い頻度で更新するとかなりマシンパワーを食います。Bitmapに描画するだけの方がずっと処理は軽いです。
そんなわけで、データが流れ込んでくるたびにBitmapは更新するものの、そのBitmapをForm上に描画するのは、1秒に1回というのもアリだと思います。
(ホームページを再開しました) -
外池 様
BufferedGrafics のやり方を理解してから外池様の この提案を読むと
考え方は同じなんだなと思います。
Bitmap(Buffer)に描画すべき画像を用意しておいて区切りのタイミングに
なったらFormへ転送すると言う事ですね。
本来あるべき画像を送っているので画面の重なりとかタイミングに無関係になると言う事!!
私の乏しい経験で”Bitmapに描画”の意味が理解できていませんでした。
Formと同じようにBitmapへもグラフ描画が可能な事が理解できていませんでした。
Form<--->Bitmap へのコピ-ばかり考えていたので正解にたどりつけませんでした。
今は ご提案 よく理解できます。
ありがとうございました。