2015年9月1日火曜日

VB PictureBox に一時的に別の Image を

PictureBox で画像を表示して、一時的に、その上に別の画像を表示させるコードを書いて見ました。
表示された画像の上に、暫くして、別の画像が現れ、また暫く経つと、これが消えて元の画像になるイメージです。
元々は、 msdn の Visual Basic Forum に投稿した コードです。
少し、説明も書いて見ます。


元のご質問の URL です。   gif表示→数秒後gifの位置にimgファイルを表示するには?  msdn Visual Basic Forum

そして、私の投稿。

PictureBox の Image と BackGroundImage を使って書いてみました。 Timer を使っています。(デザイナで設定)

コードがこれです。  少し、ほんの少し、変えて、体裁を整えました。  内容は一緒です。

              尚、コード中、日本語のファイル名が出て来ますが、本来は避けておいた方が無難です。.
              普通、問題は生じないのですが、海外のライブラリ等を使う場合に不具合が発生する可能性があります。
              今回、Forum に投稿する為、急いで Paint でサンプル画像を作ったので、無題 のファイル名になっていますが、
              文字列以外は 英数半角で命名する事をお勧めします。  習慣・癖になさるのをお勧めします。.

Public Class Form1
    Dim status As Integer = 0

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' 無題1=無題1.gif Resources 登録
        ' 無題2=無題2.jpg Resources 登録
        Me.PictureBox1.BorderStyle = BorderStyle.Fixed3D    '分り易く
        Me.PictureBox1.BackgroundImage = My.Resources.無題1
        Me.PictureBox1.BackgroundImageLayout = ImageLayout.Zoom
    End Sub

    Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
        'Timer
        Me.Timer1.Interval = 3000  '3 秒
        Me.Timer1.Start()    ' 処理開始
    End Sub


    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Select Case status
            Case 0
                Me.PictureBox1.Image = My.Resources.無題2
                Me.PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage

                'Timer
                status = 1
                Me.Timer1.Interval = 2000  '2 秒
                Me.Timer1.Start()    ' 処理再開

            Case 1
                Me.PictureBox1.Image = Nothing
                Me.Timer1.Dispose()

        End Select
    End Sub

End Class

画面と画像はこんな感じ。
左が 作ったコードを実行している処。  中央と右が Resources に登録した画像。 GIF と JPG 。
     う~ん、GIF Animation を作れば分り易いのですが、面倒なので、普通の画像でお茶を濁しました。.
Form が表示されて、赤い画像が表示され、3秒後に、白地に緑の画像が2秒間出て、また赤い画像に戻ります。
2つの画像のサイズは同一ですが、片や Zoom、他方は Stretch と、あえて変えて見ました。




では、少し、解説。
 
PictureBox は、画像を表示していない時に、背景画像を表示する機能があります。  これが BackgroundImage ですね。
画像が表示されていない時等、 ここに絵が表示されるんだよ と利用者に知らせる訳です。
或いは、PictureBox と画像との縦横比が異なる場合に、 その 穴埋め を画像で出来る訳です。
PictireBox1.Image で画像を指定すれば、普通の使い方になりますね。

ここで、逆転の発想。
画像の上に、一時的に、別の画像を被せたい なら、BackgroundImage と Image とを入れ替えて使います。
上に被る画像が Image です。
もし、被ってるよと明確にしたいなら、この画像を PictireBox のサイズより小さめに作成して
PictureBoxSizeMode.CenterImage にする事も。
そう、PictireBox1.Image に対して、Me.PictureBox1.SizeMode で、様々なモードが指定出来る様に、
BackgroundImage に対しても、BackgroundImageLayout で、様々なモードが指定出来ます。
但し、指定サイズでの表示は簡単ではないので、
     ( g.DrawImage 等で書くとか、指定サイズのイメージを新たに作るとかしないと ... ).
元の画像サイズを調整してしまうのが簡単ですね。
     あるいは、画像を PNG にして、透過(アルファチャンネル)を利用するのも いい と思います。.

  少し、初心者向けに書きます。
  普通は、Form をデザイナで設計して、 先ずは、それをクリックして、コードに FormX_Load を書く(自動生成させる)と思います。
  デザイナでの指定を変更したり、変数の初期値を設定したり ですね。
  今回の例では、背景に画像を設定しています。
  そこで、次に考えるのは、 どうやって その上に一時的な画像を表示させるか ですね。
  色々な方法が考えられますが、
  今回の例では、以下に書いた様な方針で行く事にしました。
  経過時間(タイマー利用)でイベントを発生させ、これで一時的な画像を表示したり消したりする方法です。
  手始めに、表示を考えます。(以下参照)
         上の例で言えば、変数 status の宣言やそれに絡む条件分岐 そして タイマー再セットがない コードです。
         文末に、そのコードと経緯を。.


また、時間の調整は Timer を使います。
Form が表示された時を基準に Timer をスタートさせ、 同じ様に、被った画像が表示された時を基準に 再スタートさせます。
このままでは、Timer.Tick で受ける処理の分岐が出来ませんので、
別途、status と言う変数を用意し、
これを基に分岐し、 上に被る Image を 表示したり 消したり しています。
今回のケースでは、分岐する状態は2種類ですので、 If 文でもいいのですが、応用が利く様に、Select Case で書いています。
  おっと、コード中 冒頭、 Dim status と宣言していますが、 Friend status As ... の方が良かったですね。  いけねぇ いけねぇ。.



  おまけ 参考 コードの考え方(初心者用解説)

  変数 status が無い、途中の(記述中の)コードです。
  薄くした部分は、こんな感じで、追加して行っています。
Public Class Form1
    Dim status As Integer = 0               '② 条件分岐の為に新設  Dim ではなく Friend をお勧め

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' 無題1=無題1.gif Resources 登録
        ' 無題2=無題2.jpg Resources 登録
        Me.PictureBox1.BorderStyle = BorderStyle.Fixed3D    '分り易く
        Me.PictureBox1.BackgroundImage = My.Resources.無題1
        Me.PictureBox1.BackgroundImageLayout = ImageLayout.Zoom
    End Sub

    Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
        'Timer
        Me.Timer1.Interval = 3000  '3 秒
        Me.Timer1.Start()    ' 処理開始
    End Sub


    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Select Case status               '③ 条件分岐
            Case 0               '③
                Me.PictureBox1.Image = My.Resources.無題2
                Me.PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage

                'Timer               '① タイマー再設定 また このハンドラーに戻って来るので、条件分岐が必要
                status = 1              '④ 条件分岐させる為に値を変更
                Me.Timer1.Interval = 2000  '2 秒              '① 
                Me.Timer1.Start()    ' 処理再開              '① 

           Case 1               '⑤ 一時画像を消すケース新設
                Me.PictureBox1.Image = Nothing         '⑤ 一時画像を消す  
                Me.Timer1.Dispose()                     '⑤ タイマー後処理(もう使わない)

        End Select               '③
    End Sub

End Class
  一時的な画像は表示されるだけで、消したり出来ません。    コードで 薄い色の部分は削除した(無いもの)とお考え下さい。
  それを、①~⑤ のステップで、最初に示したコードに持って行っています。



0 件のコメント:

コメントを投稿