Tag: The Wall

User interaction: GetItemAt and GetItemsAt

GetItemAt

The GetItemAt function returns the graphical item (text item, bar item, numeric item) that exists at a given position, in characters. If no item exists at the given position, the value Nothing will be returned (null). The GetItemsAt function also takes a position (X and Y) as argument but GetItemsAt will always return a collection object. If no graphical items exist at the given position, the collection will be empty. If more than one item exists at the given position, all of the items will be returned in that collection.

This first example will register two text items. Both of them will be static (that is, they will not auto update). The value of the first one will be Apples and the value of the second one will be Pears. Also, the program registers a callback for mouse clicking. If you click on Apples, a message box will show the word Apples, if you click on Pears, a message box will show the word Pears.

To start off, this code will register the items:

BackgroundColor = "#000000"

RegisterTextItem 0, "ApplesItem", 4, 2, "#ffffff", "InitApplesItem"
RegisterTextItem 0, "PearsItem", 4, 3, "#ffffff", "InitPearsItem"

Sub InitApplesItem(ByVal Item)
   Item.Value = "Apples"
End Sub

Sub InitPearsItem(ByVal Item)
   Item.Value = "Pears"
End Sub

And this is the complete source code. Here I register a callback function to detect clicks, and from there I use the GetItemAt function to see what item the user clicked on.

BackgroundColor = "#000000"

RegisterTextItem 0, "ApplesItem", 4, 2, "#ffffff", "InitApplesItem"
RegisterTextItem 0, "PearsItem", 4, 3, "#ffffff", "InitPearsItem"
RegisterClickCallback "Click"

Sub InitApplesItem(ByVal Item)
   Item.Value = "Apples"
End Sub

Sub InitPearsItem(ByVal Item)
   Item.Value = "Pears"
End Sub

Sub Click(ByVal X, ByVal Y)
	Set Item=GetItemAt(X, Y)
	If Not Item Is Nothing Then
		MsgBox Item.Value
	End If
End Sub

GetItemsAt

This is a constructed example to show how to use the GetItemsAt function. I am sure you can think of more and better examples.

This program holds a bar item and a text item overlaying the bar item. You want to detect clicks on any bar item in the program. This code adds the text and bar items, it also registers a click callback called Click. The click callback uses the GetItemsAt function to determine if the bar was clicked.

BackgroundColor = "#000000"

Bar=RegisterBarItem(1, "B", 3, 2, "#5599aa", "UpdateBar")
GetItem(Bar).Size = 11
GetItem(Bar).ValueVisible = False

RegisterTextItem 0, "T", 4, 2, "#ffffff", "InitText"
RegisterClickCallback "Click"

Sub InitText(ByVal Item)
   Item.Value = "Some text"
End Sub

Sub UpdateBar(ByVal Item)
   Item.Value=Round(Rnd() * 100)
End Sub

Sub Click(ByVal X, ByVal Y)
   Set Items=GetItemsAt(X, Y)
   For Each Item In Items
      If Item.TypeName = "BarItem" Then
         MsgBox "You have clicked on a bar named " & Item.Name & "."
      End If
   Next
End Sub

Note how the click callback function filters out any bar items from the collection, and displays the name of them (just one in this case).

Tweaking the wall, part 3/3: Startup script

The basic rule is that a VBScript file called TheWall.vbs that is placed in the same folder as TheWall.exe is loaded when TheWall.exe is started. Remember that you start TheWall.exe, not any script file – the script file is loaded by TheWall.exe. So if you are creating a shortcut, the shortcut should point to TheWall.exe.

You can manipulate this behavior by passing a filename as an argument to TheWall.exe. If a filename is passed, The Wall attempts to load that file instead of TheWall.vbs. There is no fallback, so the file you pass as an argument, must exist. The Wall cannot be started if no filename is passed as argument and the file TheWall.vbs is not present, or if a filename is passed as an argument and that file does not exist.

To check what file is running, use the ScriptFilename property.

MsgBox ScriptFilename

Just for the fun of it, this code will produce a line that is bouncing within a box. And now you know how to start it.

BackgroundColor = "#000000"

X1 = 0
Y1 = 0
X1Speed = 4
Y1Speed = 2

X2 = 30
Y2 = 190
X2Speed = 2
Y2Speed = 1

BeforeUpdate "Bounce"

Sub Bounce(ByVal G)
   X1 = X1 + X1Speed
   Y1 = Y1 + Y1Speed
   If X1 > 200 Or X1 < 0 Then
      X1Speed = X1Speed * -1
   End If
   If Y1 > 200 Or Y1 < 0 Then
      Y1Speed = Y1Speed * -1
   End If

   X2 = X2 + X2Speed
   Y2 = Y2 + Y2Speed
   If X2 > 200 Or X2 < 0 Then
      X2Speed = X2Speed * -1
   End If
   If Y2 > 200 Or Y2 < 0 Then
      Y2Speed = Y2Speed * -1
   End If

   G.DrawBar "#555555", 0, 0, 200, 200
   G.DrawLine "#ffffff", X1, Y1, X2, Y2
End Sub

Tweaking the wall, part 2/3: Using the graphics drawing interface

The BeforUpdate and AfterUpdate callback functions are basically used to allow custom graphics to be drawn below or above it. The graphics drawing interface is passed as an argument to the function you register as a callback function. Again, this Is the Hello World application of The Wall:

BackgroundColor = "#445566"
RegisterTextItem 0, "A", 4, 4, "#aabbcc", "InitializeText"

Sub InitializeText(ByVal Item)
   Item.Value = "Hello World!"
End Sub

This is what we get:

Hello World!

No, let’s say that I want to draw something before and after the text item that I have registered in the above code, I would have to register these two callback methods too, like so:

BackgroundColor = "#000000"
RegisterTextItem 0, "A", 1, 1, "#00ff00", "InitializeText"

BeforeUpdate "MyBeforeFunction"
AfterUpdate "MyAfterFunction"

Sub MyBeforeFunction(ByVal G)
   'TODO: Use the graphics drawing interface here!
End Sub

Sub MyAfterFunction(ByVal G)
   'TODO: Use the graphics drawing interface here!
End Sub

Sub InitializeText(ByVal Item)
   Item.Value = "Hello World!"
End Sub

Any drawing done in MyBeforeFunction will appear behind the text Hello World! since MyBeforeFunction was registered using the built in BeforeUpdate function. Any drawing done in MyAfterFunction will appear in front of the text since it was registered using the built in AfterUpdate function.

This will give us a blue rectangle behind the text, and a yellow rectangle in front of the text.

BackgroundColor = "#000000"
RegisterTextItem 0, "A", 1, 1, "#00ff00", "InitializeText"

BeforeUpdate "MyBeforeFunction"
AfterUpdate "MyAfterFunction"

Sub MyBeforeFunction(ByVal G)
   G.DrawBar "#0000ff", 0, 0, 400, 60
End Sub

Sub MyAfterFunction(ByVal G)
   G.DrawBar "#ffff00", 0, 65, 400, 60
End Sub

Sub InitializeText(ByVal Item)
   Item.Value = "Hello World!"
End Sub

Like so:

The DrawLine function accepts a color (all colors are in string format), X1, Y1, X2 and Y2. The DrawBar function accepts a color, X, Y, Width and Height, just as the DrawRectangle function.

Tweaking the wall, part 1/3: Before and after update

The Wall has some support for free drawing. This can either be done before or after updating the screen. Any drawing that is done before updating will be displayed behind registered objects (se the Hello World example) and any drawing that is done after updating will be displayed on top of registered objects. The coordinate system of registered objects use characters, and by default a character is 25 pixels wide and 42 pixels high.

The Hello World application in The Wall Looks like this…

BackgroundColor = "#445566"
RegisterTextItem 0, "A", 4, 4, "#aabbcc", "InitializeText"

Sub InitializeText(ByVal Item)
	Item.Value = "Hello!"
End Sub

…and the result looks like this:

The code I add to illustrate how graphics can be added behind registered objects is red and bold in the following listing. BeforeUpdate “MyBeforeFunction” tells The Wall to call a function before drawing the registered items. The argument is the name of the function.

BackgroundColor = "#445566"
RegisterTextItem 0, "A", 1, 1, "#aabbcc", "InitializeText"

BeforeUpdate "MyBeforeFunction"

Sub MyBeforeFunction(ByVal G)
	G.DrawLine 0, 70, 100, 70
End Sub

Sub InitializeText(ByVal Item)
	Item.Value = "Hello!"
	Item.Shadowed = True
End Sub

The result is the word “Hello!” with a white line behind it. I added a shadow behind the text to make the effect more visible.

To draw graphics in front of the registered items, use the AfterUpdate function to register a callback for that. This code (new lines are red and bold) also draws a line in front of “Hello!”.

BackgroundColor = "#445566"
RegisterTextItem 0, "A", 1, 1, "#aabbcc", "InitializeText"

BeforeUpdate "MyBeforeFunction"
AfterUpdate "MyAfterFunction"

Sub MyBeforeFunction(ByVal G)
	G.DrawLine "#ffffff", 0, 60, 300, 60
End Sub

Sub MyAfterFunction(ByVal G)
	G.DrawLine "#ffffff", 0, 62, 300, 62
End Sub

Sub InitializeText(ByVal Item)
	Item.Value = "Hello!"
	Item.Shadowed = True
End Sub

This is the result:

A demo is available

The Wall is an intelligent home component that can display and update text items, numeric values and bars. Also, The Wall can react to mouse clicks from a computer mouse or from a touch screen. The demo has all the functionality of the full version, but adds an overlay. This is the “Hello world” of The Wall:

BackgroundColor = "#445566"
RegisterTextItem 0, "A", 4, 4, "#aabbcc", "InitializeText"

Sub InitializeText(ByVal Item)
   Item.Value = "Hello!"
End Sub

The demo will display “Hello!” at position 4 x 4 with an overlay, like so:

The MSI file is available for download from here. If you are using Windows Vista or Windows 7, you might need to download the Microsoft Script Control, since The Wall is powered by VBScript.

Handling user input from The Wall

Please read this first. This post shows how detect mouse input in The Wall.

The Wall provides functionality for displaying data on a screen, an important component for anyone building an intelligent home. The system relies on the user’s ability use VBScript to collect data he or she wants to display, but there are some built in functions for simplifying this. I will cover these functions later. Finally, it has a very simple mechanism for detecting clicks or touch screen activity, demonstrated here.

To activate click detection, call the RegisterClickCallback function and pass the name of the function that will be called when a click is detected, “ClickCallback” in this case.

The following code will register a text item for displaying the current date and time, a numeric item for displaying the number of detected clicks, and another text item for displaying the coordinate of the click (in characters):

'Blueish background color.
BackgroundColor = "#334499"

'The background grid can be useful when designing the screen.
BackgroundGrid = True

'Every 60 seconds, display the current date and time.
RegisterTextItem 60, "DateAndTime", 0, 0, "#00ffff", "UpdateDateAndTime"

'For the fun of it, a click counter updated each second.
RegisterNumericItem 1, "Counter", 0, 2, "#ffff00", "UpdateCounter"
Set Item=GetItem("Counter")
Item.CharacterCount=3

Dim ClickCounter
ClickCounter=0

'And a string that displays the coordinates.
RegisterTextItem 1, "Coordinates", 0, 4, "#ff88ff", "UpdateCoordinates"

Dim LastX
Dim LastY
LastX = -1
LastY = -1

'This is the magic: Activate a callback for each click.
RegisterClickCallback "ClickCallback"

'Callback: Display date and time.
Sub UpdateDateAndTime(ByVal Item)
   Item.Value = "Date: " & GetDate() & " Time: " & GetShortTime()
End Sub

'Callback: Display the click counter.
Sub UpdateCounter(ByVal Item)
   Item.Value = ClickCounter
End Sub

'Callback: Display the coordinates where the click occured.
Sub UpdateCoordinates(ByVal Item)
   Item.Value = LastX & ", " & LastY
End Sub

'This callback is not called on a given interval, but
'when the user clicks (or points at the touch screen).
Sub ClickCallback(ByVal X, ByVal Y)
   'Save the coordinates and increase the counter.
   ClickCounter = ClickCounter + 1
   LastX = X
   LastY = Y
End Sub

The result might look like this after 7 clicks:

Bars in The Wall

Please read this first. This post shows how to display bars using The Wall.

Bars are created using the RegisterBarItem function. These are the arguments:

Parameter 1: UpdateFrequency (32 bit integer) tells how often the text should be updated (that is, how often the callback function will be called) in seconds. 0 means that the item never will be updated. All callback functions are called at startup, and if the UpdateFrequency parameter is greater than 0, it will be called again and again until The Wall is closed. In the example above, CallbackA will be called once, CallbackB will be called each second and CallbackC will be called every two seconds.

Parameter 2: Name (string) is the name of the item for later reference.

Parameter 3 and 4: The X and Y position in characters for the item.

Parameter 5: The color of the item in HTML format.

Parameter 6: The name of the callback procedure. All callback procedures take one object parameter. The type of the object that is passed depend on the type of item you add.

In the following example, I create four bars, and I then use the GetItem function to get a reference to each bar so that I can set some properties of the bar.

HighAlarmLevel gets or sets how high value the Value property can be before it causes the bar to enter alarm state.

LowAlarmLevel gets or sets how low the value of the Value property can be before it causes the bar to enter alarm state.

Orientation gets or sets the bar orientation. It can be Horizontal or Vertical.

Size gets or sets the height of a vertical bar or the length of a horizontal bar.

ValueVisible gets or sets whether the value of the bar will be printed out on the bar. If so, ValueColor control the color and DecimalCount controls the number of decimals that will be used.

Finally, the script holds the callback functions for the four bars. I have chosen to call them UpdateFirstBar, UpdateSecondBar, UpdateThirdBar and UpdateFourthBar.

'Grey background color.
BackgroundColor = "#666666"

'Register 4 bars, each with one second interval.
RegisterBarItem 1, "Bar1", 3, 1, "#00ff00", "UpdateFirstBar"
RegisterBarItem 1, "Bar2", 7, 1, "#00ff00", "UpdateSecondBar"
RegisterBarItem 1, "Bar3", 1, 5, "#00ff00", "UpdateThirdBar"
RegisterBarItem 1, "Bar4", 1, 6, "#00ff00", "UpdateFourthBar"

Dim B

'Do some initialization of the first bar:
Set B = GetItem("Bar1")
B.HighAlarmLevel = 10
B.DecimalCount = 2
B.Orientation = Vertical
B.ValueColor = "#ffffff"
B.Size = 4

'Do some initialization of the second bar:
Set B = GetItem("Bar2")
B.Orientation = Vertical
B.ValueVisible = False
B.Size = 4

'Do some initialization of the third bar:
Set B = GetItem("Bar3")
B.Orientation = Horizontal
B.ValueVisible = False
B.Size = 9

'And the fourth:
Set B = GetItem("Bar4")
B.HighAlarmLevel = 10
B.DecimalCount = 2
B.Orientation = Horizontal
B.ValueColor = "#ffffff"
B.Size = 9

'The callbacks. Item.Value is a double that represents the fill percentage.

Sub UpdateFirstBar(ByVal Item)
   Item.Value = (Item.Value + 0.31)
End Sub

Sub UpdateSecondBar(ByVal Item)
   Item.Value = (Item.Value + 0.5)
End Sub

Sub UpdateThirdBar(ByVal Item)
   Item.Value = (Item.Value + 2)
End Sub

Sub UpdateFourthBar(ByVal Item)
   Item.Value = (Item.Value + 1)
End Sub

This is a screenshot of The Wall running the above script:

Numeric values in The Wall

Please read this first. This post shows how to display text numeric using The Wall.

To register a numeric item, call the RegisterNumericItem function. It takes the same arguments as the RegisterTextItem function, but you might want to set some properties to the numeric item.

In this example, I add one text item and one numeric item. I then use the GetItem function to get a reference to the numeric item, so that I can set some of its properties.

The numeric items have properties for setting the expected range of the numeric value. These properties are called LowAlarmLevel and HighAlarmLevel. In this example, I set the HighAlarmLevel to 20, making the item flash if the Value property holds a value that equals to 20 or is higher.

Since the callback function HandleNumber is called each second (see the first argument in the RegisterNumericItem call) the value property will be out of range after 20 seconds, and the numeric item will start flashing on the screen.

Here is the VBScript code for this (must be located in TheWall.vbs):

'Make full screen on primary screen.
'Exclude this line for windowed mode.
MakeFullscreen 0

'Grey background color.
BackgroundColor = "#666666"

'Register a static text item.
RegisterTextItem 0, "MyStaticText", 1, 1, "#bbccdd", "InitTextItem"

'Register a numeric item with one update per second.
RegisterNumericItem 1, "MyNumericItem", 38, 1, "#00ff00", "HandleNumber"

'Do some initialization of the numeric item. Get a reference...
Dim N
Set N = GetItem("MyNumericItem")

'...set the upper alarm threshold...
N.HighAlarmLevel = 20

'...the number of characters positions I want to display...
N.CharacterCount = 3

'...and the number of decimals I want to display. None.
N.DecimalCount = 0

'The callback for the text item. Called once.
Sub InitTextItem(ByVal Item)
   Item.Value = "An increasing number with alarm at 20:"
End Sub

'The callback for the numeric item. Called once a second.
Sub HandleNumber(ByVal Item)
   Item.Value = (Item.Value + 1)
End Sub

You should see something like this on your screen:

 An increasing number with alarm at 20: 17

Note that the Value property of a text item is a String (as in the InitTextItem callback function) but for a numeric item, the Value property is a Double (as in the HandleNumber callback function).

The most basic panel for The Wall

Please read this first. This post shows how to display text values using The Wall.

This is a very simple panel. To run it, place this code in a file called TheWall.vbs, place it next to TheWall.exe and start TheWall.exe. If you are running a single display system, you must delete the first line or change it so that it says MakeFullscreen 0.

'Make full screen on secondary screen (0 = primary screen).
'Exclude this line for windowed mode.
MakeFullscreen 1

'Black background color.
BackgroundColor = "#000000"

'Register three text items.
RegisterTextItem 0, "A", 0, 0, "#00ff00", "CallbackA"
RegisterTextItem 1, "B", 1, 1, "#0000ff", "CallbackB"
RegisterTextItem 2, "C", 2, 2, "#00ffff", "CallbackC"

Sub CallbackA(ByVal Item)
   'For a text item, value (what the item is displaying) is a string.
   Item.Value = "Some green text"
End Sub

Sub CallbackB(ByVal Item)
   Item.Value = "Some blue text"
End Sub

Sub CallbackC(ByVal Item)
   Item.Value = "Some cyan text"
End Sub

This is the result:

Each item you want The Wall to display has two parts: The registration and the callback function. In the example above, the registration is represented by three calls to the RegisterTextItem function, each call for every item. The registration tells The Wall what items it should display, the callback function tells The Wall the value that the item should display. These are the arguments of the RegisterTextItem function:

Parameter 1: UpdateFrequency (32 bit integer) tells how often the text should be updated (that is, how often the callback function will be called) in seconds. 0 means that the item never will be updated. All callback functions are called at startup, and if the UpdateFrequency parameter is greater than 0, it will be called again and again until The Wall is closed. In the example above, CallbackA will be called once, CallbackB will be called each second and CallbackC will be called every two seconds.

Parameter 2: Name (string) is the name of the item for later reference.

Parameter 3 and 4: The X and Y position in characters for the item.

Parameter 5: The color of the item in HTML format.

Parameter 6: The name of the callback procedure. All callback procedures take one object parameter. The type of the object that is passed depend on the type of item you add.

If this program gets to run for 71 seconds, the output will be A=1, B=71 and C=36 because CallbackA is called once at startup, CallbackB is called every second and CallbackC is called each other second (you might need to adjust the first line):

MakeFullscreen 1
BackgroundColor = "#000000"

RegisterTextItem 0, "A", 0, 0, "#00ff00", "CallbackA"
RegisterTextItem 1, "B", 1, 1, "#0000ff", "CallbackB"
RegisterTextItem 2, "C", 2, 2, "#00ffff", "CallbackC"

Dim A
A = 0

Dim B
B = 0

Dim C
C = 0

Sub CallbackA(ByVal Item)
   A = A + 1
   Item.Value = ("A=" & CStr(A))
End Sub

Sub CallbackB(ByVal Item)
   B = B + 1
   Item.Value = ("B=" & CStr(B))
End Sub

Sub CallbackC(ByVal Item)
   C = C + 1
   Item.Value = ("C=" & CStr(C))
End Sub

The reason for using callback functions for collecting the values that should be displayed is that the value might be likely to change. The reason for using VBScript for this is that you might want to display values that The Wall doesn’t know how to collect. Can you grab the value using VBScript, you can feed it to The Wall. No limits!

Introducing The Wall

The Wall is an important component for anyone who is designing or building an intelligent home. The Wall takes care of collecting and displaying data and optionally handling touch screen input.

What does The Wall do?
It displays any value on the screen, and it responds to touch screen input (optionally). The Wall run in full screen mode on any screen (the primary screen or any other) until it is closed. You close it by pressing Alt+F4. If you are using one single screen, you might need to activate the program just by clicking the mouse before pressing Alt+F4 (depending on what you have done while the program has been running). If you are multitasking on multiple displays, you might need to activate it by pressing Alt+Tab before pressing Alt+F4.

Programming The Wall
TheWall.exe loads the file TheWall.vbs from the same directory it is started from. You need to know a few commands and techniques to be able to build it. I will show how this is done by posting examples here. You can’t choose a script from within The Wall – your script must be located in a file called TheWall.vbs and it must be located next to TheWall.exe. Many posts will be dedicated to this topic.

Get The Wall
As for now, I cannot give away The Wall for free. A demo version will be available for download. The demo version has the same functionality as “real” version, but with a text overlay.

Where is the mouse cursor?
In the current version: If you are using one single screen, The Wall hides the mouse cursor. If you are using multiple screens, the mouse cursor remains visible. This might change.

Requirements
You must have the MSScriptControl installed.

Check the The Wall tag for new posts on this subject.