Y'herd thisun? 

“We well know, from repeated experience, how much misery and hardship men will undergo in their own country, before they can determine to desert it; and how often the most tempting proposals of embarking for new settlements have been rejected by people who appeared to be almost starving.”

from Principle of Population, Chapter 10 by Thomas Malthus

Your own image control and App part 6

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.

6) Custom events

Switch mental gears for a second and put yourself in the role of dev-user. When you load a file that contains multiple images you're probably going to want to show the count to your end users right away. You can do this with the current code by remembering to check the TotalPageCount property but it would be nicer if there was an event you could trap, so we'll add one called "ImageLoaded" that has the count as one of its arguments.

Custom events have come a long way from the VBClassic days, now we have lots of options including tooling everything out with Delegates, wiring and unwiring events dynamically at runtime and even just forgetting we're in .Net and doing it "The VB Way". We're going to use a hybrid style to get the advantages of both VB and .Net.

In VBClassic we added events to objects by just declaring "Public Event MyEvent" in a class's declarations section and called it anywhere in code with a RaiseEvent. If the event had to pass extra information you put that in the signature and filled in the blank at the raise. You can still do this. It is perfectly fine and other VB consumers will have no problem with it (and if you're doing Interop out to a COM client it's great to have this option). However, VB isn't the only guy using the VBRuntime these days so it's a better idea to follow the .Net standard of having your event signature start with a "Sender" object and follow with an instance of a class derived from EventArgs.

The Sender will most always be a reference to the object that did the raise (in our case, the svImageEditor instance) but the EventArgs argument is a class so it'll take a bit more code.

Right click on the svImageEdit project node of the Solution Explorer, click on "Add" then on "Class" or "Module", it doesn't matter which you pick, we're just needing an empty file shell with a *.vb extension. Name the file "svEventArguments.vb" and hit ok. When the code designer opens, select all of the default text and delete it. Now paste the following code into the empty codeview:

Public Class svImageLoadEventArgs
Inherits EventArgs
Private m_TotalPages As Integer
Public Sub New(ByVal totalPages As Integer)
m_TotalPages = totalPages
End Sub
Public ReadOnly Property TotalPages() As Integer
 Return m_TotalPages
End Get
End Property
End Class

The base EventArgs class has a number of overloaded constructors and we aren't implementing any of them. Instead, we're using a single constructor that forces us to pass in the page count value and then exposing that value to the client via a read-only property. A developer once attacked this style saying that 'all derived classes *MUST* expose a parameterless default constructor if the base class has one' and if you also were trained this way then I have to tell you that I've never found a clear technical reason for such a rule; "Implementing"? then yes, you have to expose the whole interface, but "Inheriting" doesn't follow the same set of rules.

Go to codeview of the svImageEdit UC and create a new sub-region in the Declarations region, under (not in, under) the "Private Variables" sub-region. Name the new sub-region "Events".

Click in the Events subregion and add your nearly-traditional VB event signature:

#Region "Events"
Public Event ImageLoaded(ByVal sender As Object, ByVal e As svImageLoadEventArgs)
#End Region

Now scroll down to the LoadImage function and add the raise. Note that we'll use the helpful in-line style to create a new instance of the svImageLoadEventArgs class right as we raise the event and in that single line of code we'll be passing in the constructor's required page count value with the ping of the UC's TotalPageCount property. Saves a lot of typing, doesn't it?


Public Function LoadImage(ByVal img As Image) As Boolean
m_OriginalImage = Image.FromFile(fileName)
RaiseEvent ImageLoaded(Me, New svImageLoadEventArgs(TotalPageCount))
Catch ex As Exception
'todo:  test to figure errors
'       and remove catch-all
Throw ex
End Try
End Function

Rebuild the solution so the harness gets the updated file, Save because now would be the perfect time for a crash, then open the testHarness form in codeview. Drop down the IDE object combo and select svImageEditor1, then drop down the IDE event combo and scroll down to the new ImageLoaded event. Click on it to add a stub and in the stub put a little messagebox call to check your work:


Private Sub SvImageEditor1_ImageLoaded(ByVal sender As Object, _
ByVal e As svImageLoadEventArgs) _
Handles SvImageEditor1.ImageLoaded
MsgBox("Image file loaded." & vbcrlf & _
"The file as " & e.TotalPages & " page(s)")
End Sub


If you haven't saved the solution recently, do it now.

Next: Selecting fax pages

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