Various ways to display multiple photographs


You can use an array of PictureBox controls to display multiple photographs or other images. The sample below subclasses the PictureBox control and puts an array of them on a form. You need to change the PixPath to point to a directory with your digital photos.


 


(For an easy way to run the sample, see Use temporary projects in Visual Studio)


 


For years, I’ve had the capability to display an array of images on my Fox custom photo viewer application. When I ran the initial version of the code below, it was painfully slow. Even changing it to use dynamic thumbnails was much slower than the Fox version. Upon further investigation, the Fox version uses a separate related table of thumbnails that have already been generated.


 


You can use Spy++ from Visual studio to see that the PictureBox indeed has its own hWnd, and thus is a Windows Window.


An even faster alternative is to subdivide the Form’s hWnd into rectangles and draw the images in each rect. (next blog post)


 


The code also shows how to use lots of memory by using the ImageLocation property directly for the photo, or to create a thumbnail first, which is much faster and memory efficient.


 


I have all my 25,000 digital photos in a table (the size of which is about 2 photos), which can be queried easily using the VFP OleDB driver.


 


 


See also Sharing Digital Pictures of your friend’s


 


 


Imports System.Data.OleDb


Module Myvars


    Public dt As New DataTable


    Public fUseDBF As Boolean = False


    Public fPixPathPrefix As String = “d:\pictures\”


    Public fUseLotsOfMemory As Boolean = False


End Module


Public Class Form1


    Dim xpix As Integer = 8


    Dim ypix As Integer = 8


    Dim aPic(xpix, ypix) As PictureBox


    ‘Change pixPath to point to a dir tree with many pictures


    Dim PixPath As String = “d:\pictures\2006\08”


    ‘Dim PixPath As String = “c:\windows\help\tours\htmltour”


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


        ‘This code puts an array (xpix by ypix) of PictureBoxes on form


        Dim nRow, nCol As Integer


        If fUseDBF Then


            Dim da As New OleDb.OleDbDataAdapter(“Select ‘d:\pictures\’+fullname from mypix where ‘tyler‘$lower(notes) and ‘.JPG’$fullname”, “Provider=VFPOLEDB.1;Data Source=d:\pictures\mypix.dbf”)


            da.Fill(dt)


        Else


            dt.Columns.Add(New DataColumn(“path”, GetType(String)))


            For Each sFile As String In My.Computer.FileSystem.GetFiles(PixPath, FileIO.SearchOption.SearchAllSubDirectories, “*.jpg”)


                dt.Rows.Add(sFile)


            Next


        End If


 


        Me.Text = dt.Rows.Count.ToString


        Me.WindowState = FormWindowState.Maximized


        For nCol = 0 To ypix – 1


            For nRow = 0 To xpix – 1


                Dim xx As Integer


                xx = Me.Width / xpix.ToString


                aPic(nRow, nCol) = New MyPictureBox ‘(Int(Me.Width / xpix), Int(Me.Height / ypix))


                With aPic(nRow, nCol)


                    .Visible = True


                    .Height = Me.Height / ypix


                    .Width = Me.Width / xpix


                    .Top = nCol * .Height


                    .Left = nRow * .Width


                    .SizeMode = PictureBoxSizeMode.StretchImage


                    .Tag = nCol * ypix + nRow ‘ store the index in the tag


                    Me.Controls.Add(aPic(nRow, nCol)) ‘ add the control to the form


                End With


            Next


        Next


    End Sub


End Class


 


Class MyPictureBox


    Inherits PictureBox


    Private Sub MyPictureBox_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseEnter


        If fUseLotsOfMemory Then


            Me.FindForm.Text = Me.ImageLocation


        Else


            Me.FindForm.Text = dt.Rows(Me.Tag).Item(0).ToString.Trim


        End If


    End Sub


 


    Private Sub MyPictureBox_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint


        Dim nIndex As Integer = Me.Tag


        If nIndex < dt.Rows.Count Then


            If fUseLotsOfMemory Then    ‘ GDI+ uses LOTS of memory!


                If Me.ImageLocation Is Nothing Then


                    Me.ImageLocation = dt.Rows(nIndex).Item(0).ToString.Trim


                End If


            Else


                If Me.Image Is Nothing Then ‘ use much less memory with dynamically created thumbnails


                    Dim imgBig As Image = New Bitmap(dt.Rows(nIndex).Item(0).ToString.Trim)


                    Me.Image = imgBig.GetThumbnailImage(Me.Width, Me.Height, Nothing, Nothing)


                    imgBig.Dispose()    ‘ release the memory


                End If


            End If


        End If


    End Sub


End Class


 

Comments (8)

  1. Tracy.P says:

    You’re using the VFPOleDB provider, do you know why it doesn’t support indexing?

    #DEFINE adIndex   8388608

    If Not File("ADOIndex.DBF")

      Create Table ADOIndex (PK i, Descript c(30))

      Insert Into ADOIndex Values (1, "One")

      Insert Into ADOIndex Values (2, "Two")

      Index On PK Tag PrimaryKey

      Use

    EndIf

    Local ADOConn As ADODB.Connection, ADORecordSet As ADODB.RecordSet, Msg As String

    ADOConn = CreateObject("ADODB.Connection")

    ADOConn.ConnectionString = "Data Source=" + FullPath("")

    ADOConn.Provider = "VFPOleDB"

    ADOConn.Open()

    ADORecordSet = ADOConn.Execute("USE ADOIndex")

    Msg = "Not Supported"

    If ADORecordSet.Supports( adIndex )

      Msg = "Supported"

    EndIf

    MessageBox("Indexing is " + Msg, 0, _Screen.Caption)

  2. Would love to see equivalent VFP code to this .NET framework multiple photograph display implementation.

  3. My prior post showed how to use an array of PictureBox controls to display multiple photographs on a…

  4. I’ve been using Canon Powershot cameras for years, and they take movies in AVI format as well as being…

  5. I have many digital pictures, and I’d like to put some of my favorites on my SmartPhone . However the

  6. In my prior post , I showed how to use XAML and XAMLReader to create inline XAML to display the results

  7. In my prior post , I showed how to use XAML and XAMLReader to create inline XAML to display the results