DesktopX: Creating a Slideshow Widget (Beginner)

From WinCustomize Wiki

Jump to: navigation, search
Creating a Slideshow Widget
Original Author:sViz
Date Created:November 10, 2007
Application:DesktopX
Programs Used:DesktopX


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:

Image:Dx_Slideshowprevious.png Image:Dx_Slideshownext.png Image:Dx_Slideshowload.png


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:

Paused Playing

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.

[edit] Further Reading