Image Thumbnail Refresh Problem

Image Thumbnail Refresh Problem

Old forum URL: forums.lhotka.net/forums/t/4260.aspx


dufflepud posted on Wednesday, January 30, 2008

I am having a problem with a bound thumbnail image not refreshing in a datagridview column.  I am allowing the user to double click the thumbnail to pull up a little drawing window.  After they draw I assign the bitmap to the BO property.  I also need the thumbnail image to update on the grid.  No matter what I do the thumbnail returns the same image it initially had.  It seems to be caching it and not getting the updated image.  Here is the code from the BO class:

Public Property Sketch() As Drawing.Bitmap
        Get
            CanReadProperty("Sketch", True)
            Return _sketch
        End Get
        Set(ByVal value As Drawing.Bitmap)
            CanWriteProperty("Sketch", True)
            _sketch = value
            _sketchThumbnail = GetThumbnail(_sketch)
            PropertyHasChanged("Sketch")
            PropertyHasChanged("SketchThumbnail")
        End Set
    End Property

    Public ReadOnly Property SketchThumbnail() As Drawing.Bitmap
        <System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
        Get
            CanReadProperty("SketchThumbnail", True)
            Return _sketchThumbnail
        End Get
    End Property
    Private Shared Function GetThumbnail(ByVal imageIn As Drawing.Bitmap) As Drawing.Bitmap
        Dim myThumb As Drawing.Bitmap
        If imageIn IsNot Nothing Then
            myThumb = CType(imageIn.GetThumbnailImage(25, 25, Nothing, New System.IntPtr), Drawing.Bitmap)
        Else
            myThumb = Nothing
        End If
        Return myThumb
    End Function

I have tried a variety of ways to get this to update but no dice.  Any help would be greatly appreciated.

dufflepud replied on Wednesday, January 30, 2008

I should have mentioned this is a winform project and I am using CSLA 2.0
Thanks.

tmg4340 replied on Thursday, January 31, 2008

I am not a thumbnail expert, but based on the MSDN docs, I'm wondering if your "GetThumbnail" routine is working properly.  According to the docs on "GetThumbnailImage", you must pass a callback delegate for your third parameter, and the fourth parameter must be "IntPtr.Zero" (which may be different than a new, uninitialized pointer value.)

I can't say whether that's affecting your overall issue, but it's something you might want to look into.

- Scott

dufflepud replied on Thursday, January 31, 2008

Thanks for the ideas Scott.  The initial load of the thumbnail does work.  It seems to be an issue of the thumbnail bitmap variable not changing - like it is cached or the memory that is being pointed to isn't pointed to a new area or something strange like that.

I made the following changes but it didn't have any affect:
Private Function GetThumbnail(ByVal imageIn As Drawing.Bitmap) As Drawing.Bitmap
        Dim myThumb As Drawing.Bitmap
        If imageIn IsNot Nothing Then
            myThumb = CType(imageIn.GetThumbnailImage(25, 25, MyCallBack, IntPtr.Zero), Drawing.Bitmap)
        Else
            myThumb = Nothing
        End If
        Return myThumb
    End Function
    Private Function MyCallBack() As Drawing.Bitmap.GetThumbnailImageAbort
        Return Nothing
    End Function

I'm not sure what the delegate should do but I assume it is for something like a cancel button or something to trigger an abort of the process.  It is being called though so that doesn't make a whole lot of sense.  I added a line in there with PropertyHasChanged("SketchThumbnail") just to see if it would change the image in the grid after a bit but it doesn't.  At this point I am very confused.  I even changed the sketchthumbnail property to public and tried setting it from the UI but even there it doesn't update it.
Here is the UI side in case it might show what I am doing wrong:

Private Sub AHERAResultsEnhancedDGV1_CellDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles AHERAResultsEnhancedDGV1.CellDoubleClick
        Dim mAHERA As AHERAResult

        If AHERAResultsEnhancedDGV1.Columns(e.ColumnIndex).Name = "Sketch" Then
            Dim rowguid As Guid
            rowguid = CType(AHERAResultsEnhancedDGV1.Rows(e.RowIndex).Cells("RowGUIDColumn").Value, Guid)
            mAHERA = _analysis.AHERAResults.FindByID(rowguid)

            Using sketchForm As frmSketch = frmSketch.GetInstance
                sketchForm.Bitmap = mAHERA.SketchThumbnail
                If sketchForm.ShowDialog() = Windows.Forms.DialogResult.OK Then
                    'show me the thumbnail going in
                End If
            End Using

            Using sketchForm As frmSketch = frmSketch.GetInstance
                sketchForm.Bitmap = mAHERA.Sketch
                If sketchForm.Bitmap Is Nothing Then
                    sketchForm.Bitmap = sketchForm.MakeNewBitmap() 'call form to make sure size is correct.
                End If
                If sketchForm.ShowDialog() = Windows.Forms.DialogResult.OK Then
                    mAHERA.Sketch = sketchForm.Bitmap
                End If

            End Using
            Using sketchForm As frmSketch = frmSketch.GetInstance
                sketchForm.Bitmap = mAHERA.SketchThumbnail
                If sketchForm.ShowDialog() = Windows.Forms.DialogResult.OK Then
                    'show me the thumbnail coming out
                End If
            End Using
        End If
    End Sub

Thanks again for any help.
Glenn

tmg4340 replied on Thursday, January 31, 2008

Well - the only other thing I can suggest is something I saw in either a forum post or one of Rocky's e-books.  Basically, in a WinForms data-binding scenario, once you have bound your object, you should never directly interact with the object properties.  Instead, you should interact with the BindingSource control.  That may be your problem, as the BindingSource may not be propagating to the grid properly.  I would leave the "GetThumbnailImage" changes too, though it appears they didn't make a difference.

HTH

- Scott

dufflepud replied on Thursday, January 31, 2008

Scott,

It definitely is something wacky with the GetThumbnailImage.  When I just assign the non-thumnail to the property it updates fine.  I am going to see what other options I have there.
Thanks for your help.

Glenn

dufflepud replied on Monday, February 04, 2008

I think I have something that will work.  Just in case someone else might find this helpful here is the code that seems to take care of this for me.

Private Function GetThumbnail(ByVal imageIn As Drawing.Image) As Drawing.Image
        Dim myThumb As Drawing.Image
        If imageIn IsNot Nothing Then
            Dim newsize As Drawing.Size = New Drawing.Size(25, 25)
            myThumb = New Drawing.Bitmap(imageIn, newsize)
        Else
            myThumb = Nothing
        End If
        Return myThumb
    End Function

I did change everything to drawing.image rather than drawing.bitmap but either should work.
Also getting and storing the image data as a byte string image field was confusing for me so in case it might help someone here is the code I used.

 'get the bitmap
Dim bufferSize As Integer = 100
        Dim mByteImage(bufferSize - 1) As Byte
        Dim retVal As Long
        Dim startIndex As Long = 0

            Using stream As New System.IO.MemoryStream
                startIndex = 0
                retVal = .GetBytes("Sketch", startIndex, mByteImage, 0, bufferSize)
                If retVal > 0 Then
                    Do While retVal = bufferSize
                        stream.Write(mByteImage, 0, mByteImage.Length)
                        stream.Flush()
                        startIndex += bufferSize
                        retVal = .GetBytes("Sketch", startIndex, mByteImage, 0, bufferSize)
                    Loop
                    stream.Write(mByteImage, 0, CInt(retVal))
                    Sketch = New Drawing.Bitmap(stream) 'use property to make sure thumb is assigned
                Else
                    Sketch = Nothing
                End If
            End Using

'saving it here was the parameter
cm.Parameters.Add("@Sketch", SqlDbType.Image).Value = ConvertToByteArray(_sketch)
'and here is the function
Public Shared Function ConvertToByteArray(ByVal value As Drawing.Image) As Byte()
        If value IsNot Nothing Then
            Dim bitmapBytes As Byte()
            Using stream As New System.IO.MemoryStream
                value.Save(stream, value.RawFormat)
                bitmapBytes = stream.ToArray
            End Using
            Return bitmapBytes
        Else
            Return Nothing
        End If
    End Function

Copyright (c) Marimer LLC