VB2008の関数に付属していたサンプルで、OpenFileDialogで画像ファイルを選択し、その画像をPictureBoxに表示するサンプルだと思うのですが、画像をFromStreamしてもなにも表示されません。
理由がわかる方おられますでしょうか?
(元ソース:http://msdn.microsoft.com/ja-jp/library/system.windows.forms.application.doevents(VS.71).aspx)
ソースは上記のものほぼコピペです。
Public Class Form1
Private Sub InitializePictureBox()
Me.PictureBox1 = New System.Windows.Forms.PictureBox
Me.PictureBox1.BorderStyle = _
System.Windows.Forms.BorderStyle.FixedSingle
Me.PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage
Me.PictureBox1.Location = New System.Drawing.Point(72, 112)
Me.PictureBox1.Name = "PictureBox1"
Me.PictureBox1.Size = New System.Drawing.Size(160, 136)
Me.PictureBox1.TabStop = False
End Sub
Private Sub InitializeOpenFileDialog()
Me.OpenFileDialog1 = New System.Windows.Forms.OpenFileDialog
' Set the file dialog to filter for graphics files.
Me.OpenFileDialog1.Filter = _
"Images (*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF|All files (*.*)|*.*"
' Allow the user to select multiple images.
Me.OpenFileDialog1.Multiselect = True
Me.OpenFileDialog1.Title = "My Image Browser"
End Sub
Private Sub fileButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles fileButton.Click
OpenFileDialog1.ShowDialog()
End Sub
' This method handles the FileOK event. It opens each file
' selected and loads the image from a stream into PictureBox1.
Private Sub OpenFileDialog1_FileOk(ByVal sender As Object, _
ByVal e As System.ComponentModel.CancelEventArgs) _
Handles OpenFileDialog1.FileOk
Me.Activate()
Dim file, files() As String
files = OpenFileDialog1.FileNames
' Open each file and display the image in PictureBox1.
' Call Application.DoEvents to force a repaint after each
' file is read.
For Each file In files
Dim fileInfo As System.IO.FileInfo = New System.IO.FileInfo(file)
Dim fileStream As System.IO.FileStream = fileInfo.OpenRead()
PictureBox1.Image = System.Drawing.Image.FromStream(fileStream)
Application.DoEvents()
fileStream.Close()
' Call Sleep so the picture is briefly displayed,
'which will create a slide-show effect.
System.Threading.Thread.Sleep(2000)
Next
PictureBox1.Image = Nothing
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
InitializePictureBox()
InitializeOpenFileDialog()
End Sub
End Class
補注:リソースにはForm1, PictureBox1, fileButton, OpenFileDialogを作成してあります。エラーは出ません。
アクアと申します。どうぞ宜しくお願いします。
早速ですが、ご提示いただいているコードの
4行目
Me.PictureBox1 = New System.Windows.Forms.PictureBox
それと
15行目
Me.OpenFileDialog1 = New System.Windows.Forms.OpenFileDialog
これを削除してください。
またざっとコードに目を通した中での注意事項として
OpenFileDialog1のOKボタンを押したときのイベントの中で、
PictureBox1.Image = Nothing
とあります。
したがってOpenFileDialog1が閉じると共に画像は消えてしまうと思います。
実行時にはForm1とOpenFileDialog1が重ならないように注意して下さい。
で、何故、2つの行を削除しなくてはならなかったのか? が重要です。
Form1.Designer.vbを覗いてみればインスタンス化の処理が既に存在し、ご提示いただいたコードにもある為だと確認できるはずです。
これに関する理解を深める事をお勧めします。
家から書き込んでいます(元は会社からでした)。
なるほど、おっしゃる原理は大体飲み込めました。
私のWindowsプログラミング感覚からすると、Newは確かに存在するコントロールに対して、Newするのは変だな戸は思っていました。ですけど、Initialize(New)はLoadからよばれているので、一回起動だから問題ないのかなと思ってました(これがVBライクなのかとw)。この手のミスはC++だとメモリリークになりますよね…。
あと、Newに関しては一回疑ったのですが試しに、リソースで取得した画像を入れといたところ、その後リードしてるはずなのに変わっていませんでした(画像なしにもならない)。それでここじゃないのかなとあきらめました。
結局上記のことから考えてみるに、MeのPictureBox1のオブジェクト(インスタンス?)をNewして代入して、その後その代入したオブジェクトを変更しても、現在表示されているForms1のPictureBox(Newした後も実は消えてない?)には反映されていない、ってことでしょうかね。
んーだとするとNewがわざわざサンプルコードについていた理由が今ひとつわからない…。けどとりえあず解決しそうなので良しとします。
試しは家ではまだできないので、解決にはしませんけれども、アクアさんありがとうございました!
質問者さんは
「私は十分な知識を持っているんだけどMSがショボいサンプルを出しているから迷ってしまうじゃないか!」
と思っているんだろうね・・・
(笑)
私の心のうちを代弁していただいてありがとうございます。でも十分な知識はないですよ。。MFCとかもう過去の遺物ですな…。
ともかく、さきほど家環境でもインストール終わって、テストしたところアクアさんのおっしゃった部分のコメントアウト(とLocation設定)で対応できました。ありがとうございます。
追記:まぁMSが(製品バグも含めて)理不尽なのは昔からですので、いまさらなにも言うことはありません。それにタダで配ってる分のものですから、文句つけようないですね。MFCでこういった処理だともう少し中まで覗けるけど、VBはステップイン微妙ですね…。Form1.Designer.vbてのを見れればもう少しわかるのかな?重ねて感謝いたします。
押し忘れましたw
ツイート | ![]() |