DesktopX: Creating a Slideshow Widget (Beginner)
From WinCustomize Wiki
| Creating a Slideshow Widget | ||||||||
| ||||||||
Contents |
[edit] Introduction
This tutorial will show you how to make a simple picture slideshow. If you're not familiar with the process of scripting and creating widgets please refer to the previous tutorials. You will also need a brief understanding of the FileSystemObject which you can read about here.
[edit] Concept
- What is it? This will be a simple picture slideshow. It will alternately display images.
- What does it do? The user will drag and drop some images onto the slideshow and it will begin.
- What are its functions? The slideshow will also have some control buttons to go back, forward, play/pause, and manually browse for images to add/load to the slideshow.
- How does it function? The user can click on the add or load images button to manually add/load images, and the user can drag and drop images onto the image thumbnail. The back, forward, play/pause buttons are self-explanatory.
[edit] Execution
[edit] Overview
We’ll have a total of 9 objects: the background image, thumbnail, image size object, back button, forward button, play/pause button, load image button, wait sign object and the close button.
We’ll use drag & drop (OnDropFiles) and l-click (System.FolderOpenDialog) to load/add images. To keep it simple, we won’t be persistently storing this information (in advanced widgets you’d store the info in an initialization file). The images will be stored in an array. Therefore, it will clear each time the widget is loaded. We’ll use the thumbnail script to apply the image to the thumbnail object and we’ll use a timer to play the images.
We'll also be using the Ex-Callbacks to get the user interaction with the controls, which are child objects.
We’ll be relying on the use of the File System Object which you should read about before continuing this tutorial.
FSO will be used to get file paths, extensions, folders and subfolders. Basically all the file handling needs.
[edit] Setup
Create a new object and call it “background”. Apply the image below.
Create three more objects and name them “back”, “forward” & “add”.
Apply their images below:
Create the play button object, name it “play”. In Properties > General change the default appearane to the play button below. Next, create 2 states: ‘playing’, ‘paused’.
Apply these images to the states described in the tool tip:
Arrange the buttons on the background as shown. Then, select all the buttons and group them (group name: “controls”, group method: ‘normal’). Select all the buttons and set parent to “background”.
Create the thumbnail object, name it “thumbnail”. Apply the image below and set width/height to 180/150. Center it inside the background object and set parent to “background”.
Create a text object, name it “waitsign”. Enter these settings: text = “Loading images…” , font size = 12, font style = bold, font color = black, font border color = white, shadow color = white. Place it in the middle of the background object and set parent to “background”. Go to Properties > Relation. Set activiation to ‘none’ and visibility to ‘no’.
Create the image size object, name it “sizeObj”. Place it anywhere inside the background object, and set parent to “background”. Go to Properties > Relation and set visibility to ‘no’.
Create a text object and name it ‘close’. Apply these settings: text = “x” , size = 18, color = black. Go to Properties > summary and change object type to ‘widget’. In the drop down, choose ‘widget close’. Position it on the background as seen below and set parent to "background".
[edit] Script
All scripts here go in the "background" object.
As usual we declare the variables in the script; several arrays and a few others. In OnScriptEnter, we set the FileSystemObject, position the waitsign in the middle of the background, and set a few variables we’ll be using to check the status of the player. We also set the image array size to zero, for starters.
Dim objFSO
Dim icount, curImg
Dim images(), imgW(), imgH()
Dim status
'Called when the script is executed
Sub Object_OnScriptEnter
Set objFSO = CreateObject("Scripting.FileSystemObject")
Desktopx.Object("waitsign").move ((object.width/2) - (Desktopx.Object("waitsign").width/2)),_
((object.height/2) - (Desktopx.Object("waitsign").height/2))
status = "paused"
Desktopx.Object("play").state = status
ReDim Preserve images(0)
End Sub
( Scripting Tip #2: For really long lines of code you can use the underscore ( _ ) to continue it on the next line; as seen in line 9 & 10)
Here we have the OnLButtonUpEx function. As you can see we have different results for each of the control buttons. Clicking on the add button will bring up the dialog box to browse for images. Clicking on the back button will stop the show if it is playing and then subtract from the current image variable so you get the previous image. Clicking on the forward button does the reverse of the back button. Clicking on play will change the status variable depending on whether or not the show is playing. Finally, we set the play button state appropriately (paused or playing).
'Called when L-click on object or its children
Function Object_OnLButtonUpEx(obj, x, y, dragged)
If Not dragged Then
Select Case obj.name
Case "add"
folder = System.FolderDialog("", "", &H4000)'--Browse for all folders
If folder <> "" Then Call Object_OnDropFilesEx(obj,folder)
status = "playing"
Case "back"
object.KillTimer 1
status = "paused"
If curImg =< 0 Then curImg = UBound(images) Else curImg = curImg - 1
If images(curImg) <> "" Then SetThumbPic
Case "forward"
object.KillTimer 1
status = "paused"
If curImg => UBound(images) Then curImg = 0 Else curImg = curImg + 1
If images(curImg) <> "" Then SetThumbPic
Case "play"
If status = "paused" Then
status = "playing"
startshow
Else
status = "paused"
Object.KillTimer 1
End If
End Select
Desktopx.Object("play").state = status
End If
End Function
Now we have the OnDropFilesEx procedure. We use a simple message box to verify whether the user wants to replace all the images already loaded or add to them. If the user chooses 'yes' (replace the images) we clear all the arrays. We show the waitsign which will remain up until the files are loaded and the show is ready. Finally, we pass the array of files to the procedure which will weed out any folders or invalid file types.
'Called when files are dropped onto object
Sub Object_OnDropFilesEx(obj,files)
Select Case obj.name
Case "thumbnail", "add"
'Stop timer
object.killtimer 1
If msgbox("Do you wish to replace the current images(Yes) Or append(No)?"_
,vbYesNo)= vbYes Then
'reset counts, arrays
icount = 0
curImg = 0
ReDim Preserve images(icount)
ReDim Preserve imgW(icount)
ReDim Preserve imgH(icount)
End If
'---Show waitsign, hide thumbnail---
Desktopx.Object("waitsign").visible = True
Desktopx.Object("thumbnail").visible = False
Desktopx.Object("waitsign").OnTop
'-----------------------------------
'If many files dropped
If Instr(files, "|") > 0 Then
filelist = Split(files, "|")
Call validate(filelist)
'If one file dropped
Else
Dim tempArr(0)
tempArr(0) = files
Call validate(tempArr)
End If
startShow
End Select
End Sub
This is the validate function. It takes the array of files we got earlier from OnDropFiles and uses FSO to check the extensions for valid image file types. If it is valid it adds to the image array. It applies the image to the size object so we can get the original dimensions. The dimensions are put into an array for later use when it’s time to scale it down. If there is no extension then the file is obviously a folder, and it is run through another procedure which handles folders and their contents.
Function validate(imageArr)
For Each elem In imageArr
'Check file extension for valid images
Select Case LCase(objFSO.GetExtensionName(elem))
'If valid extension, add to array and count
Case "png", "bmp", "jpg", "tga", "ico"
ReDim Preserve images(icount)
ReDim Preserve imgW(icount)
ReDim Preserve imgH(icount)
images(icount) = elem
'Get image dimensions
DesktopX.Object("sizeObj").states("").picture = elem
imgW(icount) = DesktopX.Object("sizeObj").width
imgH(icount) = DesktopX.Object("sizeObj").height
icount = icount + 1
'If no extension, run through foldercheck
Case ""
Call foldercheck(elem)
End Select
Next
End Function
The foldercheck function is a simple one. It uses FSO to get all files in the folder and run them through the validate procedure. If any subfolders are found they are run through this same procedure. It’s a good example of how reusable functions are when you can pass and return values. Go ahead and type it up as you see it below.
After all that, we come to the function which starts the show. It removes the waitsign and shows the thumbnail. It sets and calls the timer which applies the images to the thumbnail.
This is the timer which sets the images. It calls the procedure which scales down the image and applies it to the thumbnail. Then it adds to the current image count. I used an If Else statement to check whether or not there are actually any images in the array. This is only applicable if the user tries to use the controls before loading any images.
Sub Object_OnTimer1
If images(0) <> "" Then
If curImg > UBound(images) Then curImg = 0
SetThumbPic
curImg = curImg + 1
If UBound(images) =< 0 Then object.KillTimer 1
Else
object.KillTimer 1
status = "paused"
Desktopx.Object("play").state = status
End If
End Sub
Finally, we have the SetThumbPic procedure which scales down the thumbnail image. It’s basically the same as explained in the DesktopX: Scripting Images (Beginner) tutorial; except we get the original dimensions from the arrays we set earlier. In addition, we set the position of the thumbnail to the center of the background.
Sub SetThumbPic
maxSize = 160
oldW = imgW(curImg)
oldH = imgH(curImg)
'If image width is greater than image height
'calculate what percentage height is of width
'set new width and new height
If oldW > oldH Then
newH = Int((maxSize/100)*(oldH/oldW)*100)
newW = maxSize
'If image height is greater than image width
'calculate what percentage width is of height
ElseIf oldW < oldH Then
newW = Int((maxSize/100)*(oldW/oldH)*100)
newH = maxSize
'If image dimensions are equal
'set height and width to maxSize
ElseIf oldW = oldH Then
newH = maxSize
newW = maxSize
End If
'If image width and height are smaller than maxSize
'use original image dimensions
If oldW < maxSize Then
If oldH < maxSize Then
newH = oldH
newW = oldW
End If
End If
'Set object width, height, and picture
Desktopx.Object("thumbnail").Width = newW
Desktopx.Object("thumbnail").Height = newH
Desktopx.Object("thumbnail").states("").picture = images(curImg)
'Set object position
Desktopx.Object("thumbnail").left = (object.width/2)_
- (Desktopx.Object("thumbnail").width/2)
Desktopx.Object("thumbnail").top = ((object.height/2)_
- (Desktopx.Object("thumbnail").height/2)) - 10
End Sub
That’s it! Select all, export, and enjoy. :)
[edit] Notes & Tips
- Be sure to make everything but the background locked in position. Just open properties > relation and set movement to ‘locked’.
- For finishing touches, change the normal cursor for the buttons to a hand cursor, and add tool tips.



