Y'herd thisun? 

“You can export from and to any data format... once you know the middleware trick.”

from this classic page by smith

Your own image control and App part 24

TaggedCoding, VB, Imaging

Originally published December 2002 on using VB7.0/2002. Updated for VB7.1 February 2005

Links for compiled demo versions, all required resources and source code are included at the end of this article.

Plus, get the complete eBook in Adobe Acrobat 7 format ... all here.


24) The final solution

Pretty much all that's left is some VB3, hooking up control properties to other control methods.

We need to show and hide the toolbar buttons for page up, page down and the page number label depending on whether the source viewport editor has a multipage image:


Private Sub SetSourcePageButtonsVisible()
Dim bHasPages As Boolean = svImageSource.TotalPageCount > 1
tbrSource.Controls(tbrSource.ControlIndexByName("lblPageSpacer")).Visible = bHasPages
 tbrSource.Controls(tbrSource.ControlIndexByName("butPageDown")).Visible = bHasPages
 tbrSource.Controls(tbrSource.ControlIndexByName("lblPageNumber")).Visible = bHasPages
 tbrSource.Controls(tbrSource.ControlIndexByName("butPageUp")).Visible = bHasPages
End Sub


And, better than Microsoft's Picture and Fax Viewer, we'll want the page buttons to be disabled if the user is at a first or last page:


Private Sub SetSourcePageButtonsEnabled()
tbrSource.Controls(tbrSource.ControlIndexByName("butPageDown")).Enabled = _
CBool(svImageSource.CurrentPageNumber <> 1)
tbrSource.Controls(tbrSource.ControlIndexByName("butPageUp")).Enabled = _
CBool(svImageSource.CurrentPageNumber <> svImageSource.TotalPageCount)
End Sub

These helpers will be called when an image is loaded into the editor and optionally when a PageChanged event is fired. The svImageEditor ImageLoaded event is also a good place to enable the rest of the toolbar buttons:


Private Sub svImageSource_ImageLoaded(ByVal sender As System.Object, _
ByVal e As Smithvoice.svImageLoadEventArgs) _
Handles svImageSource.ImageLoaded
'update the toolbar
'buttons enabled if image loaded
For Each ctl As Control In tbrSource.Controls
Select Case ctl.Name
Case "butClear", _
"butRotateCounterclock", "butRotateClock", _
"butZoomMinus", "svcboZooms", "butZoomPlus", "butZoomFit", _
"butMouseCrop", "butMouseSticky", _
ctl.Enabled = True
Case "lblPageNumber"
ctl.Text = "1"
End Select
mnuSource.Enabled = True
'clear the result editor
If m_SizeToFitOnLoad Then svImageSource.ZoomToFit()
End Sub
Private Sub svImageSource_PageChanged(ByVal sender As Object, _
ByVal e As Smithvoice.svImagePageChangeEventArgs) _
Handles svImageSource.PageChanged
tbrSource.Controls(tbrSource.ControlIndexByName("lblPageNumber")).Text = _
End Sub

On the flipside we'll want to disable the buttons on both toolbars and clear the editors. We'll do that with a specific method for Source and Result:


Private Sub ClearSourceViewport()
For Each ctl As Control In tbrSource.Controls
Select Case ctl.Name
Case "butClear", _
"butRotateCounterclock", "butRotateClock", _
"butZoomMinus", "svcboZooms", "butZoomPlus", "butZoomFit", _
"butMouseCrop", "butMouseSticky", _
ctl.Enabled = False
Case "lblPageNumber"
ctl.Text = "0"
End Select
mnuSource.Enabled = False
End Sub
Private Sub ClearResultViewport()
For Each ctl As Control In tbrResult.Controls
Select Case ctl.Name
Case "butRotateCounterclock", "butRotateClock", _
"butZoomMinus", "svcboZooms", "butZoomPlus", "butZoomFit", _
"butMouseCrop", "butMouseSticky", _
ctl.Enabled = False
End Select
mnuResult.Enabled = False
End Sub


Notice that ClearResultViewport is called when you clear the source and also when a new image is loaded into the source editor.

One last helper, to let the form show a OpenFileDialog and get the ball rolling:


Private Sub LoadSourceEditor()
Dim fo As New OpenFileDialog
With fo
.Filter = "Image files|*.jpg;*.gif;*.bmp;*.png;*.tif"
.Multiselect = False
If .ShowDialog = DialogResult.OK Then
Catch ex As svImageExceptions.svImageInvalidImageFileException
End Try
End If
End With
fo = Nothing
End Sub

 Now hook up the toolbar buttons:


Private Sub tbrSource_ButtonClicked(ByVal but As System.Windows.Forms.Button) _
Handles tbrSource.ButtonClicked
Select Case but.Name
Case "butLoad"
Case "butClear"
Case "butPageDown"
svImageSource.CurrentPageNumber -= 1
Case "butPageUp"
svImageSource.CurrentPageNumber += 1
Case "butRotateClock"
Case "butRotateCounterclock"
Case "butZoomPlus"
svImageSource.ZoomPercent = _
Case "butZoomMinus"
svImageSource.ZoomPercent = _
Case "butZoomFit"
End Select
End Sub
Private Sub tbrSource_OptionChanged(ByVal rbut As System.Windows.Forms.RadioButton) _
Handles tbrSource.RadioOptionChanged
If rbut.Checked Then
Select Case rbut.Name
Case "butMouseCrop"
svImageSource.MouseMode = Smithvoice.svMouseMode.Crop
Case "butMouseSticky"
svImageSource.MouseMode = Smithvoice.svMouseMode.AutoScroll
End Select
End If
End Sub


And take care of zooms and croppings:


Private Sub SvImageSource_ImageCropped(ByVal sender As System.Object, _
ByVal e As Smithvoice.svImageCroppedEventArgs) _
Handles svImageSource.ImageCropped
End Sub
Private Sub svImageSource_ZoomChanged(ByVal sender As Object, _
ByVal e As Smithvoice.svImageZoomChangeEventArgs) _
Handles svImageSource.ZoomChanged
tbrSource.Controls(tbrSource.ControlIndexByName("butZoomPlus")).Enabled = _
Not e.MaxLimitReached
tbrSource.Controls(tbrSource.ControlIndexByName("butZoomMinus")).Enabled = _
Not e.MinLimitReached
End Sub

Lastly, hook up the DragDrop by setting the svImageSource's AllowDrop to true in the property sheet (we'll put a switch in a menu later) and adding the boilerplate code:


Private Sub svImageSource_DragDrop(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DragEventArgs) _
Handles svImageSource.DragDrop
Dim theFile As String
'check to make sure the dropped item is of type FileDrop
If e.Data.GetDataPresent(DataFormats.FileDrop) Then
 Dim filenames() As String = _
 CType(e.Data.GetData("FileName", True), String())
 theFile = filenames(0).ToString
 End If
Catch ex As Exception
Throw ex
'Todo: remove after testing
End Try
End Sub

Do the busywork of similarly hooking up the result viewport's toolbar and editor events (svImageResult doesn't need all the same ones as the source editor and probably shouldn't have DragDrop). Then F5 and test things out.

Also verify that a multipage tiff shows the page buttons and disables them at either limit of the collection.

Losing the splitter?

When I first released a system like this my users shot the whole thing down because if they resized the form they no longer could see the result viewport. I remember taking a whole day to work out a solution of forcing the splitter to move on every form resize. It was complex, it was hacky, it was klugely... and months later I realized that I was thinking way too hard. The answer is to simply set the form's AutoScroll property to True; the splitter will add a bit of margin so if you shrink the form and hide the result viewport the horizontal scrollbar will pop up, making it obvious that there's more to the form and easy for the users to get to that hidden area.

We're now 97% done. Except for writing a help file (which I'm not getting into here), we only need to wire up those Save buttons.

Next: Saving images to files

Robert Smith
Kirkland, WA

added to smithvoice march 2005

jump to:

  • 1) The spec
  • 2) Setting up the workspace
  • 3) Feature 1: Loading an image
  • 4) Custom Exceptions
  • 5) "Fax images" and Multipage TIFFs
  • 6) Custom events
  • 7) Selecting specific fax pages
  • 8) Feature 2: Rotating image displays
  • 9) The most useful tool in GDI+: DrawImage
  • 10) Feature 3: Zooming
  • 11) Handling the unhandleable exception
  • 12) Fixing the squish
  • 13) Zooming to fit the control
  • 14) You're already beating the Pros
  • 15) Feature 4: Cropping
  • 16) Bonus Feature: StickyMouse
  • 17a) Final Cleanup
  • 17b) Passing the current display image
  • 18) Making the application
  • 19) Source and result viewports
  • 20) A better toolbar
  • 21) Hooking the toolbar to the project
  • 22) Adding ImageEditors
  • 23) The toolbar ZoomCombo
  • 24) The final solution
  • 25) Saving to image files
  • 26) An integer-only textbox
  • 27) Passing save options between forms
  • 28) Dealing with that last exception
  • 29) Offer more options with menus
  • 30 The downloads and ebook

  • home     who is smith    contact smith     rss feed π
    Since 1997 a place for my stuff, and it if helps you too then all the better