smithvoice.com
 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 DoItIn.net 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", _
"butSave"
ctl.Enabled = True
 
Case "lblPageNumber"
ctl.Text = "1"
 
End Select
 
Next
  
SetSourcePageButtonsVisible()
SetSourcePageButtonsEnabled()
mnuSource.Enabled = True
 
'clear the result editor
ClearResultViewport()
 
If m_SizeToFitOnLoad Then svImageSource.ZoomToFit()
  
End Sub
 
  
Private Sub svImageSource_PageChanged(ByVal sender As Object, _
ByVal e As Smithvoice.svImagePageChangeEventArgs) _
Handles svImageSource.PageChanged
 
SetSourcePageButtonsEnabled()
tbrSource.Controls(tbrSource.ControlIndexByName("lblPageNumber")).Text = _
e.NewPage.ToString
 
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", _
"butSave"
ctl.Enabled = False
 
Case "lblPageNumber"
ctl.Text = "0"
 
End Select
 
Next
 
svImageSource.InitializeControl()
SetSourcePageButtonsVisible()
mnuSource.Enabled = False
ClearResultViewport()
 
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", _
"butSave"
ctl.Enabled = False
 
End Select
 
Next
 
svImageResult.InitializeControl()
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
Try
svImageSource.LoadImage(.FileName)
Catch ex As svImageExceptions.svImageInvalidImageFileException
MsgBox(ex.Message)
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"
LoadSourceEditor()
 
Case "butClear"
ClearSourceViewport()
 
Case "butPageDown"
svImageSource.CurrentPageNumber -= 1
 
Case "butPageUp"
svImageSource.CurrentPageNumber += 1
 
Case "butRotateClock"
svImageSource.RotateDisplay(RotateFlipType.Rotate90FlipNone)
 
Case "butRotateCounterclock"
svImageSource.RotateDisplay(RotateFlipType.Rotate270FlipNone)
 
Case "butZoomPlus"
svImageSource.ZoomPercent = _
CInt(tbrSource.Controls(tbrSource.ControlIndexByName("svcboZooms")).Text)
 
Case "butZoomMinus"
svImageSource.ZoomPercent = _
-CInt(tbrSource.Controls(tbrSource.ControlIndexByName("svcboZooms")).Text)
 
Case "butZoomFit"
svImageSource.ZoomToFit()
 
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
 
svImageResult.LoadImage(e.CroppedImage)
 
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
Try
'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
 svImageSource.LoadImage(theFile)
 
 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 smithvoice.com