Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Passing Pictures

15 views
Skip to first unread message

BeeJ

unread,
Oct 24, 2012, 12:39:45 PM10/24/12
to
I have two solutions below and wonder
Is there a better way?
What, if any, are the advantages or disadvantages of using the
methods I propose or some other method? I have not explored passing
an Object.
I want to pass, in effect, pointers to picture boxes rather than the
actual picture data to keep processing speed at a maximum.

I have a complex method, not shown, that manipulates each image from an
array of image sources.
I need to pass into the method that array.
The array may either be an array of picture boxes already loaded with
images, picBox(n), or an array of paths, asDPName(n), to images.

There may be an array of picture boxes: picBox(0 .. 35) max.
And for string: asDPName(0 .. 1000) or more.
These are high res images and are fairly large on disk.

So here are the samples I use to test passing arrays using a single
argument. These seem to work and pass pointers to picture boxes thus
minimizing memory usage to the picBox() array and picShow (see below).

I have also fiddled with passing an array of user defined Type but have
not included that here since it is slightly more complex. But there
may be advantages that I do not know about.

The samples here are used to verify that I can differentiate between a
picturebox and a string and use that to load a single working
picturebox picShow from either.

The call to these:
for PicColSet I need to load up a collection of either picBox or
string. It looks like the collection contains a pointer to each
picBox.

Private Function PicColSet(ByRef oCol As Collection) As Boolean

Dim lX As Long
'
For lX = 1 To oCol.Count
If TypeOf oCol.Item(1) Is PictureBox Then
' Picturebox collection
Debug.Print "Is PicBox"
Set picShow = oCol.Item(lX)
Else
Set picShow.Picture = LoadPicture(CStr(oCol.Item(lX)))
End If
Next lX

End Function 'PicColSet

' ===============================================================
for PicSet I simply pass the picBox array or the string array.

PicVarSet picBox
PicVarSet asDPName

Private Function PicVarSet(ByRef vObj As Variant) As Boolean

Dim lUBound As Long
Dim lPic As Long
'
If TypeOf vObj(0) Is PictureBox Then
' PictureBox Array
Debug.Print "Is Pic"
lUBound = vObj.UBound
Else
' String Array
Debug.Print vObj(0)
lUBound = UBound(vObj)
End If
'
For lPic = 0 To lUBound

If TypeOf vObj(0) Is PictureBox Then
Set picShow.Picture = vObj(lPic).Picture

Else
Set picShow.Picture = LoadPicture(CStr(vObj(lPic)))

End If

Next lPic

End Function 'PicVarSet

I will be adding error handling when I wrap this up.


Larry Serflaten

unread,
Oct 24, 2012, 4:47:36 PM10/24/12
to
BeeJ wrote:
> I have two solutions below and wonder
>
> Is there a better way?


That's going to be a bit subjective. How is your code going to look when
you include appropreate error handling? Try it once and see....


Here is another way to 'skin that cat' with effective error handling baked in.

It handles:
- A collection of PicutreBoxes
- A collection of Strings
- A mixed collection of PicutreBoxes or Strings
- An array of Variants (Strings or PictureBoxes or mixed)
- An array of PictureBoxes
- An array of Strings

Also note it will continue processing the group even if one or more items
cause errors.

Its just another take on attacking that problem. Use as you see fit!

LFS


Sub PicSet(ByVal Group As Variant)
Dim item As Variant

Select Case VarType(Group)
Case 9, 8200, 8204 ' Collection or () of Strings or () of Variants

On Error GoTo badItem ' Error handling does not leave For/Each loop

For Each item In Group

If TypeOf item Is PictureBox Then

PicShow.Picture = item.Picture

ElseIf VarType(item) = vbString Then

PicShow.Picture = LoadPicture(item)

Else
badItem: MsgBox "invalid item ..."
End If

On Error GoTo -1 ' close active error handler (if any)

Next

Case Else
MsgBox "invalid parameter ... "
End Select

End Sub


Larry Serflaten

unread,
Oct 24, 2012, 5:15:57 PM10/24/12
to

> It handles:
>
> - A collection of PicutreBoxes
> - A collection of Strings
> - A mixed collection of PicutreBoxes or Strings
> - An array of Variants (Strings or PictureBoxes or mixed)
> - An array of PictureBoxes
> - An array of Strings


I sure wish these groups had an edit feature.... <g>


Change:
> Case 9, 8200, 8204 ' Collection or () of Strings or () of Variants


To read:
Case 9, 8200, 8201, 8204 ' Collection or () of Strings or () of <Control> or () of Variants


The change was needed to support the array of pictureboxes as in:

Dim pb() As PictureBox

The 'control array' style (multiple pictureboxes on the same form) will also
work which is what I meant to say, above.

Oh well!
LFS

BeeJ

unread,
Oct 24, 2012, 6:00:37 PM10/24/12
to
That is very interesting and the probable best solution.
Took me a few to figure out 8200, 8201, 8204 ? MSDN only shows 8192.
I see the example of vbInteger + vbArray = 8194.
so 8192 + 8 = () String
8192 + 9 = () object
8192 + 12 = () variant

This both simplifies and amplifies the sample code I provided.

Since some folks discourage Variants, is any of this possible with
Object. I tried that a little but could not get it going.
I have no problem with Variant so maybe it is not worth the effort.

Thanks for this tutorial!


BeeJ

unread,
Oct 24, 2012, 6:14:37 PM10/24/12
to
I have never seen the
On Error GoTo -1
before and Googling got me nowhere except that one place says it is not
VB6 code and another uses it but does not explain it.

So my assumption, based on usage, is that On Error GoTo -1 resets error
handling (after an error is handled or does nothing if no error) to the
previous On Error GoTo XXXX. Where is that all explained?


ralph

unread,
Oct 24, 2012, 11:46:54 PM10/24/12
to
It isn't. Well, make that not 'officially' in the VB documentation. It
is however mentioned briefly in the Visual Basic.Net documentation.
[This is probably where so many get the idea it is not valid in VB6,
but it has been a, albeit undocumented, feature of VB since at least
VB5.]

I never understood why Microsoft didn't document it. While it is
obscure and is only truly useful in few situations, when it is needed
it can be very useful indeed. However, there are always, thou kludged,
work-arounds. (Perhaps that is why MS saw no reason to go there?)

It exists mainly because of 'symmetry'. VB's structured error handling
is based on C's. C had a "-1" option, so whomever was doing the port
just provided it for VB.
The details on Structured Error Handling:
[http://msdn.microsoft.com/en-us/library/s58ftw19(v=vs.80).aspx]

[Note: Context is everything when it comes to *structured* error
handling.]

"On Error Goto -1" in VB appears similar to "On Error Goto 0", but
they are subtly different.

On Error Goto 0 terminates the current Error Handle and then Raises
all errors. If there is no error then the program proceeds. You can
either create a new handler, or fall back on the default which is to
go back up the call stack till either it finds a handler or GPF.

This means if you call On Error Goto 0 within an Error Handler - you
have a problem. All Errors are raised so off you go. But what if you
wanted another error handler in an Error Handler?

On Error Goto -1 to the rescue. It will set the current Error to
Nothing, which will allow you to setup up another error handler for
that Error Handler.

Common example:
Private Sub Foo
On Error GoTo EH_Main
Err.Raise 3
Exit Sub
EH_Main:
' On Error GoTo 0 <== bad things can happen <g>
On Error GoTo -1: On Error GoTo EH_Err

Err.Raise 3
Exit Sub
EH_Err:
MsgBox "All Clear"
End Sub

Handy at times. You can even nest them.
I'll leave it to you to play with "Resumes". Can get interesting. <bg>

-ralph

ralph

unread,
Oct 25, 2012, 12:13:52 AM10/25/12
to
On Wed, 24 Oct 2012 22:46:54 -0500, ralph <nt_cons...@yahoo.com>
wrote:


>On Error Goto -1 to the rescue. It will set the current Error to
>Nothing, which will allow you to setup up another error handler for
>that Error Handler.
>

I used the common VB idiom and said the "Error was set to Nothing".
That is not accurate and might be misleading.

What I should have said was the current active "Exception Flag" is
reset, ie, ignored and thus no error is raised.

-ralph

ObiWan

unread,
Oct 25, 2012, 3:07:21 AM10/25/12
to


> I have a complex method, not shown, that manipulates each image from
> an array of image sources.
> I need to pass into the method that array.
> The array may either be an array of picture boxes already loaded with
> images, picBox(n), or an array of paths, asDPName(n), to images.

Why don't you just add a class module to your app; the class module
will expose properties like (e.g.)

EntryType
EntryValue

the first will be mapped to an enum which will tell you the content on
that given entry (e.g. string, image, whatever), the second will be a
variant carrying the data; at that point your collection will just hold
a number of instances of such a class and, when looping through the
collection, you'll just need to check the EntryType (a "select case"
would do) and then, knowing it, deal with the EntryValue ... then, by
the way (and if you want) the class may also contain additional
properties which you may find useful (for example image size or other
infos) or encapsulate some internal logic (for example, the class may
have a method "loadimage" which will either directly return the image
or, in case it carries a filename, automatically load the file and,
again, return the image)

Larry Serflaten

unread,
Oct 25, 2012, 8:34:31 AM10/25/12
to
You'd get it from books dedicated to VB programming, and not from MS
documentation.

Your assumption is essentially correct, and Ralph added a bit of clarity.
My take on it, goes like this:

As it relates to error handling, VB code is always in one of three states:
1. No error handler present - all errors climb back up the call stack.
2. A handler is present, but no exception has occured - the ideal state.
3. A handler is present and an exception has occured.

You will find VB documentation that uses the phrase 'an enabled error handler'
when they refer to the 2nd state. Where also 'an active error handler' refers
to the 3rd state.

As Ralph points out, once your error handling code is executing (due to some
exception in the procedure) you can not set another error handler to trap
errors that might happen in the error handling section while the current
error handler is still 'active'.

With "On Error Goto -1", you can de-activate the current error handler. I
used the phrase 'close active error handler' in the example. Whatever you call
it, the current error handler is left enabled, just not active. That is why
I did not need to include On Error inside the For/Each loop.

Resume would not work (well) in this case because you would want to put the
Resume just after the MsgBox command indicating an invalid item. While that
would work if an exception is raised, it would cause problems if an item in
the group failed both the IF condition and ElseIF condition and got down to
the Else clause without raising an error. In that case, the Resume statement
in the Else clause would itself cause an error, which would back jump to the
MsgBox and show the MsgBox a second time.

The main point I wanted to show with the example was that 'sufficient' error
handling was present, without making a mess of an otherwise simple procedure!

HTH
LFS
0 new messages