Link to home
Start Free TrialLog in
Avatar of nascar_3
nascar_3

asked on

shift pics from box to box

If I have say 5-10 image boxes for previewing jpgs in a file directory, and I want to have 2 command buttons to shift those pictures "up" and "down" the line of image boxes. What would be the best way to do this.

What I'm looking for is to have those boxes start by showing the 1st 10 images in the directory. Then if I click the "up" button, they all shift 1 box, knocking image #1 off, and displaying images 2-11, click again and they shift again displaying 3-12 and so on until you get to the last image. The "down" button would do the same thing in reverse. So you can move up and down the list of images and preview 10 of whatever number of pictures in that directory at a time.

The directories will have any number of pictures in them all under various names. Ideally, if possible, when you get to the last picture, it would bring the first picture back up again, so in a sense it would be a "circular" effect to keep browsing in 1 direction indefinately. (but thats not so important)
 
More points for really good code :)
Avatar of vettranger
vettranger

I don't have time this morning to write the code for you, but here's the approach I would take.

First, design your image controls as a control array (images 0 to 9).

1. Make an array with the top and left properties of your image controls. Set a 'FirstImage' variable to zero.

2. Load your filenames for the images in a directory into an array.

3. Load the first ten images into your ten image controls.

4. When the user clicks the button to go 'forward' in the directory :
   a. coordinate your firstimage variable with the control array to shift each image's location 'down one'.
   b. reset the location of the firstimage to the last location in the location array
   c. load the next image from your array of filenames
   d. add one to the firstimage variable, if its = 10 set it to 0

Now do the reverse for the 'down' button.

Of course you'll need checks for hitting the 'top' and 'bottom' of the directory list.

Using this method means that you only change the contents of one image control per user action. The code would be slightly more simple if you actually reloaded each image control to move thru the images, but would take a LOT longer to execute for each user action.
Assuming that you have created a control array of ten picture boxes called picControl, giving the first one an index of 0 and the last one an index of 9...

In your General Declarations Section:
Dim sPics() as String
Dim lTopIndex as Long

In your form Load:
Dim sPath as string
Dim sMatch as String
Dim FirstTime as boolean

FirstTime = True
sPath = IIF(Right(App.Path, 1) = "\", App.Path, App.Path & "\")

sMatch = Dir$(sPath & "*.jpg")
Do While sMatch <> ""
if FirstTime then
   Redim sPics(0) as String
   FirstTime = False
else
   Redim Preserve sPics(Ubound(sPics) + 1)
End If
sPics(Ubound(sPics)) = sPath & sMatch
sMatch = Dir$()
Loop

In your Up button Click:

If lTopIndex = 0 then
   lTopIndex = Ubound(sPics)
Else
   lTopIndex = lTopIndex - 1
End if

DisplayPictures

In your Down button Click:

If lTopIndex = Ubound(sPics) then
   lTopIndex = 0
Else
   lTopIndex = lTopIndex + 1
End if

DisplayPictures

Then, create a sub called DisplayPictures:

Private Sub DisplayPictures()
Dim x as Integer

For x = 0 to 9
   picControl(x).Picture = LoadPicture(sPics(lTopIndex + x))
Next x
ASKER CERTIFIED SOLUTION
Avatar of mcrider
mcrider

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
(vet posted while I was writing the above code)

Mine is an example of the less efficient method, but I chose it because of it's simplicity.  Also, I figure that if you have 10 jpgs for a page, they can't be very big images, and would probably not take too long to load.  Also, if you change the location of the picture boxes, then I think that the user may see the boxes shifting around...
Just do a lockwindowupdate API on the form before and after the code. No picture shifting will be evident.
Another approach
Use a flexgrid to disp sized pics and
use it's scroll bars.


Option Explicit

Private Sub Form_Load()
Dim i As Integer

Image1.Visible = False
Picture1.Visible = False
Picture1.AutoRedraw = True
MSFlexGrid1.Font.Size = 24
MSFlexGrid1.Row = 1
Picture1.Width = MSFlexGrid1.CellWidth
Picture1.Height = MSFlexGrid1.CellHeight
File1.Path = "F:\vb6\Graphics\Bitmaps\Assorted"

MSFlexGrid1.Rows = File1.ListCount

For i = 0 To File1.ListCount - 1
Image1.Picture = LoadPicture(File1.Path & "\" & File1.List(i))
Picture1.PaintPicture Image1.Picture, 0, 0, Picture1.Width / 2, Picture1.Height
Set Picture1.Picture = Picture1.Image
MSFlexGrid1.Row = i
Set MSFlexGrid1.CellPicture = Picture1.Picture  'LoadPicture(File1.Path & "\" & File1.List(i))
Next

End Sub
By the way, in the code above, you would probably want to do the following in the Form Load, after loading the file names into sPics:

lTopIndex = 0
DisplayPictures
Avatar of nascar_3

ASKER

Thanks for all the response!

I'll fidgit with all these ideas and see what works best.
I do like mdougan's so far. I got to try it at lunch today.
It's what I envisioned doing myself, although I couldn't come up with the code for it on my own. The only drawback is it's a little slow.

I won't have time to check the others for a day or so, so please be patient with me. I've got other "REAL" projects to finish first.

I'll post again when I've sorted through it all.
I'm still looking at this, but so far, for sure, I don't like jbil's MSFlexGrid option. It takes a long time to load all images at start-up and I don't like the scrollbar "look and feel" for what I'm doing.

mdougan, I again like the solution and found it was only slow because of the size of the images I'm loading. I found that if I use thumbnails that are only 60x60, it runs pretty snappy. I am however, crashing out when I hit either end of the immage array. It gets a subscript out of range error on
picControl(x).Picture = LoadPicture(sPics(lTopIndex + x)). Otherwise I like it!

mcriders code works great when I move pass the end of the array and provides me with a good smooth circular browsing effect. 2 problems I found on this though:
1) when you "reverse" direction the pictures shift the wrong way on the first click, then move correctly on the second, third etc. until you reverse again.

2) I'm not crazy about referencing the FileList box, because that box needs to update on each click, and when it needs to advance the list beyond what is already on screen, it delays the pic display noticably.

I'm trying to cross-breed these 2 so that mcriders circular display works on mdougans method of developing the picture array (without FileList Box). Then split points to both of you. Let me work on another day or two and I'll see what I come up with.


nascar_3,
About the problems you found...

1)  I'll look at the circular logic again.. I just dashed it off here in EE without actually trying it...

2) Hide the listbox... You wouln't have to "wait" for the listbox to update on the screen...

Cheers!
mcrider,

 I got it figured out. Killed both problems at once. I'll post final code and give points later. No time now. Just wanted to save you the trouble of looking at it further.
Cool!! (Waiting for your return...)


;-)


Cheers!
Yea, I dashed it out in EE without trying it either.  

The only thing I could see to cause this (I know you've figured it out, but lets see how close I can come):
"It gets a subscript out of range error on picControl(x).Picture = LoadPicture(sPics(lTopIndex + x))"

For x = 0 to 9
   picControl(x).Picture = LoadPicture(sPics(lTopIndex + x))
Next x

If your picControl control array does not have a member with a zero index, you would get an error, and if you had less than 10 images total, you would also get the error at the end of the loop.

As I said, make sure that you have your ten picControls with indexes starting from zero to nine, then I'd change the above code to:

Dim iCount as Integer

iCount = UBound(sPics)
if iCount > 9 then iCount = 9
For x = 0 to iCount
   picControl(x).Picture = LoadPicture(sPics(lTopIndex + x))
Next x
nascar_3,

It you're going to use my example code, please reject the current answer and select my comment as the correct answer...


Cheers!
if nascar_3 uses a combination of both answers, then who's answer do they accept?

:)
Sorry, I have to go with Mcrider's comment, see below!
OK, here's the final product!
Hiding the filebox works just fine.
The problem with it shifting 1 space the wrong way was fixed by moving the "I=File1.Listindex" line. Where it sat before, the File1.Listindex was changing after "I" was set. It needed to change prior to setting "I".

mcdougan, thanks for your input, the out of subscript error was not due to the array of the pic boxes, it was on lTopIndex (I think). It crashed out on, say, if you have 80 pics and you move right until pic #80 is in the rightmost box and then try to continue to the right. Likewise when Pic1 is in the leftmost box and you try to keep going left.

Mcrider's code handles this perfectly. In fact if you have less pics than boxes they will just repeat over until all boxes are displayed (with Dups-but thats OK)

Oh- BTW, I've increased the number of image boxes to 17.

Dim X As Long
Dim I As Long
Dim dVal As Long
Dim lPath As String

Sub ShowThePictures(Direction As Boolean)
 
X = 0
  ' Move Pics to the Left
  If Direction = True Then dVal = 1
  ' Move Pics to the Right
  If Direction = False Then dVal = -1

lPath = File1.Path
If Not Right$(lPath, 1) = "\" Then lPath = lPath + "\"
   
' check ListIndex for highest number, if so, reset to Zero
If File1.ListIndex + dVal < File1.ListCount Then
   File1.ListIndex = File1.ListIndex + dVal
Else
   File1.ListIndex = 0
End If
 
' check Listindex for Zero, if so, reset to highest number
If File1.ListIndex = -1 Then File1.ListIndex = File1.ListCount - 1
           
' synchronize ListIndex with List Names "(I)"
I = File1.ListIndex
   
' show pics!
Do
  DoEvents
  If I > File1.ListCount - 1 Then I = 0
    Image1(X).Picture = LoadPicture(lPath + File1.List(I))
    Label1(X).Caption = Mid(File1.List(I), 4, 5)
      X = X + 1
      I = I + 1
  If X = 17 Then Exit Do
Loop
   
End Sub

Private Sub MoveLeft_Click()
' DO NOT try to show pics if there are none!
If File1.ListCount = 0 Then GoTo skip
ShowThePictures True
skip:
End Sub

Private Sub MoveRight_Click()
' DO NOT try to show pics if there are none!
If File1.ListCount = 0 Then GoTo skip
ShowThePictures False
skip:
End Sub

Private Sub Dir1_Change()
File1.Path = Dir1.Path
' need to set to -1 to get display to start with 1st pic
' otherwise the math causes pic 1 to be skipped....
File1.ListIndex = -1
' DO NOT try to show pics if there are none!
If File1.ListCount = 0 Then GoTo skip
' causes pic boxes to be shown when Dir1.Path is chosen :)
ShowThePictures True
skip:
End Sub

Private Sub Drive1_Change()
Dir1.Path = Drive1.Drive
End Sub

Private Sub Form_Load()
' start on root drive
Dir1.Path = "C:\"
End Sub