JobRunner 1.5

JobRunner är ett program som exekverar sekvenser av program. Det kan t.ex. användas av den som regelbundet genererar filer lokalt på datorn, som ska skickas upp till en server. I version 1.5 finns stöd i användargränssnittet för att arbeta med variabler. Om du vill modifiera vilka steg som ska exekveras, måste JobRunner startas som administratör. Mer information finns här.


Ladda hem JobRunner för Windows 10/11: JobRunner.exe (högerklicka, välj Spara som…)

JobRunner 1.4

Version 1.4 av JobRunner finns nu att ladda hem. Programmet låter dig lista upp processer som ska utföras i turordning som kan beläggas med vissa enkla villkor. Startas programmet som administratör kan dessa steg redigeras, annars kan de bara köras.

Den senaste versionen innehåller några mindre buggrättningar och introducerar möjligheten att manuellt stoppa en körning.

https://github.com/Anders-H/JobRunner

Skapa binära filer snabbt och enkelt

Ibland behöver man skapa binära filer, t.ex. för att testa en egenutvecklad file header. För att göra detta kan man starta HxD och peta in de bytes man vill ha i filen. Men om man vill trycka in tal större än 255 eller textsträngar så är det en del att hålla i huvudet. Programmet MkBin bygger en binärfil efter instruktioner i en textfil.

Programmet tar två argument. Först -source som anger textfilen som beskriver binärfilen och -target som anger den binära filen som ska skrivas.

Tal som anges i textfilen antas vara bytes (8-bitarstal mellan 0 och 255), men det går att skriva in kontrollord framför för att ändra datatyp, vilket exemplet i bilden ovan visar.

Om man vill laborera med vilka texter som ger vilket binära resultat, kan man starta programmet med växeln -prompt istället för -source och -target, bara genom att skriva:

MkBin.exe -prompt

Då kan man skriva text och få direkt feedback på vad som skulle hamna i en textfil. Kontrollord som byte, short, int och long, eller 8-bit, 16-bit, 32-bit eller 64-bit anger formatet på efterföljande tal och uttryck som anges inom citat antas vara strängar med UTF-8-kodning. Exempel:

MkBin finns att hämta här.

Mjukvaran SQLite skrivs av oresonliga idioter

SQLite är en mjukvara för datalagring, skriven i C, som fungerar på i princip vilken enhet som helst, från t.ex. Windows Phone till Linux. Mjukvaran är Public Domain, så företaget som utvecklar den försörjer sig istället på att sälja t.ex. support, tilläggsfunktioner eller drift.

Den utvecklare som ska bidra till den officiella produkten måste leva upp till en uppförandekod på 72 punkter som finns publicerad som en del av dokumentationen på deras hemsida (läst 2018-10-23). T.ex. får man inte mörda (punkt 3), vänsterprassla (punkt 4) eller vara stolt (punkt 34), samtidigt som man måste respektera äldre (punkt 68), älska sina fiender (punkt 31) och älska att fasta (punkt 13).

Jag kan ibland vara naiv och utgå ifrån att mina kompanjoner inte är mördare, och kan därför rentav tycka att det är lite nedlåtande att behöva be någon jag ska jobba med att skriva under på det. Och ska jag vara helt ärlig så har jag över huvudet taget svårt att vara kollega med den sortens människa som antas behöva ha en uppförandekod för att inte mörda. Men om jag kan se bortom det, så vill jag naturligtvis hellre jobba med en humanist än mördare. Så vad har fastan med saken att göra?

Det är nog ingen idé att försöka förstå, för det visar sig att SQLite utvecklas av vidskepliga idioter. T.ex. finns det ingen som bidrar till produkten som inte älskar en 2000 år gammal krigsgud från Mellanöstern (punkt 1) eller som inte ger denna övernaturliga entitet äran för sina egna insatser (punkt 42). Som mjukvaruutvecklare i behov av datalagring bör du fundera på om den som behöver denna uppförandekod, och vidare, den som lever efter denna uppförandekod, är någon som du vill ha att göra med? Över huvudet taget, på något tänkbart vis? I så fall har du problem.

EaseUS Partition Master

If a hard disk partition suddenly disappears and shows up in Disk Manager as unallocated space, the program EaseUS Partition Master solve the problem. The program can repair the partition and assign a drive letter to it, so that your files become available again.

The program is free to use, but the installer would like to put a lot of junk in your computer. Also, the program will remain running after use, so remember to uninstall from the control panel when the program is no longer needed.

Download run.exe

It takes some clicking and fiddeling to install run.exe, the text based application starter. This post describes what you have to do and also how to use it. There are some arguments that are nice to know:

run -p

This displays all running processes together with an ID.

run -k 1234

This will kill process with ID 1234 (careful with this). And finally, to display your defined aliases, type:

run -a

Download run.exe from here.

A text based start menu

Since I have tried everything (including RocketDock), this is what it has come to. I have made a text based start menu! I have my little personal setup with a folder that is handled by Dropbox so that it is available on all my computers. It is also specified in the PATH system variable, so I can access the scripts and programs without specifying the full path to them. The EXE file is called run.

Now, I can start CDBurnerXP by typing:

run "C:\Program Files (x86)\CDBurnerXP\cdbxpp.exe"

Also, passing arguments to programs are also supported, so this will open the a specified web page in

run "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" https://www.winsoft.se/

This might feel a bit odd, because this command can already be executed from cmd.exe, so what does the run command actually provide?

In the configuration file, you can point out a file that define aliases. The alias file consists of aliases for any phrase you like. By defining an alias for the Firefox path like so:

#DEFINE ff "C:\Program Files (x86)\Mozilla Firefox\firefox.exe"

…you can start Firefox and open a specific address like so:

run ff https://www.winsoft.se/

And of course, you can add another line to your file to create an alias for the URL you want to visit, like so:

#DEFINE ff "C:\Program Files (x86)\Mozilla Firefox\firefox.exe"
#DEFINE winsoft https://www.winsoft.se/

Now, all you need to type to open WinSoft.se in Firefox is:

run ff winsoft

You can also use run to display running programs and close programs. More information and a download link to come.

Naming your images

I have been planning to do a PhotoName II for some while now, and here it is. Because of the different take on this application, I also decided to change it’s name from PhotoName II to RenameImg (short for Rename Image). The main difference is that this has no graphical user interface, you use it from your text console. It takes a few clicks to install this, but when it’s done, it is easy to upgrade and you have a friend for life.

If you are planning to run RenameImg from PowerShell, you must have given yourself the right to execute scripts, and to be able to do that, you must start PowerShell as an administrator. You only have to do this once, regardless of what scripts or programs you want to run from PowerShell. If you are planning to run this from your old command prompt (cmd.exe), you don’t have to do anything.

The next thing you have to do, is to unzip the exe file and give it a suitable location on your system. Your console must be able to reach the exe file. I have created a folder on my machine where I put all my console applications and cmdlets. That folder is then pointed out in the Path system variable. This makes it easy to start the application, because all I have to do, is to type renameimg in the console. When started without any arguments, RenameImg will rename all JPG images in the current folder Just like DIR lists the files in the current folder when executed without arguemnts, RenameImg will rename the files in the current folder when started without arguments. I will talk about the supported arguments you can pass to RenameImg in a later post.

Now, if it finds any JPG images that haven’t already been renamed using RenameImg, it will list them and ask you if you want them renamed, and if you answer yes, RenameImg will rename each image to a filename that looks something like this:

D20110504T204540_13045X32648P15591.jpg

The new name will consist of:

The capital letter D.

The date the image was taken according to the EXIF (YYYYMMDD).

The capital letter T.

The time of day the image was taken according the the EXIF (HHMMSS).

An underscore.

Up to five numeric digits from the original filename. If less than five numeric digits are available, random digits are used.
The capital letter X.

A random number (five digits).

The capital letter P if the date and time actually is taken from the EXIF. If not, the capital letter C indicates that the date is the file creation date.

Finally, before the file ending, a serial number, that is previous image’s number plus one, or a random number if the image is first in the batch (five digits).

The file ending is .jpg (lowercase).

By using this naming standard on your images, you can store all your images in one single folder on your hard drive. Also, you can use the name as the unique identifier if you are storing your images in a database. Finally, pictures are always displayed chronologically in media players and you can know when the picture is taken just by looking at the name of the file.

You can download RenameImg from here.

The Wall is discontinued

Since VBScript isn’t the way of the future, I’ve decided to discontinue the “The Wall” project. Something similar for so called intelligent homes is in planning stage. It will be based on the open source Jint project. Check this out:

Dim X As New Jint.JintEngine()
Dim Script As New System.Text.StringBuilder()
Script.AppendLine("var x=10;")
Script.AppendLine("return x;")
Dim Response As Object = X.Run(Script.ToString())
Console.WriteLine(Response.GetType()) '(Double)
Console.WriteLine(Response.ToString()) '(10)

Jint is a fully managed open source JavaScript interpreter.

Drawing a HTML5 heart with Monkeybone

This demonstration shows how you can create a Monkeybone picture from scratch and to export it as a HTML5 vector image. The required software is Monkeybone Viewer version 1.5 or later.

Step 1: Create the file. To do this in Windows, you must make sure that you can see the file ending of known file types. Right click on an empty area on your desktop, create a text file, change the file ending from .txt to .mob. Start Notepad and drag the file to Notepad.

Another way to accomplish this, is to start Notepad, click File and Save as, change to “All files” in the filter box, and finally, type in a file name with a .mob ending. Click the Save button.

Step 2: Initialize the picture and open it in the Monkeybone Viewer. Enter a Clear instruction as the first line in the text file. The Clear instruction will specify the image background color and the size of the image. I will make it 300 x 300 pixels and pink. This is the source:

Clear 300x300 #ff9999

Save it using Notepad, drag it from the desktop to the Monkeybone Viewer (version 1.5 or later). Now you should see a pink square 300 pixels wide and 300 pixels high in the viewer.

Step 3: Define the heart. Add Spline instructions to your document. You can re-save it in Notepad, switch to the viewer and press Ctrl+Shift+F5 to make the changes appear. Adjust your code and repeat until you are satisfied. This is my code (including the first Clear instruction):

Clear 300x300 #ff9999
Spline #ff0000 X1:150-100 Y1:50-100 X2:10+0 Y2:70-10
Spline #ff0000 X1:10-20 Y1:70+60 X2:150+10 Y2:290+0
Spline #ff0000 X1:150+100 Y1:50-100 X2:290+0 Y2:70-10
Spline #ff0000 X1:290+20 Y1:70+60 X2:150-10 Y2:290+0

Step 4: Export the picture. In Monkeybone Viewer, click File and Save as. Change the format to HTML5. Click the Save button. To view, double click the HTML file to open it in your default browser or drag it to a open web browser. If you are using Internet Explorer, version 9 or later is required. This is the result:

Download the Monkeybone Viewer from this page.

My first look at Internet Explorer 9

The first thing is to fly off to the ACID3 test (that of course is overloaded now when the IE9 BETA is released), so I will have to get back to this. All modern browsers do 100% in the ACID3 with IE8 as the only exception. IE8 isn’t close.

The next thing that I want to try out is how well tabbing works. This is perhaps the one flaw that I just can’t stand in earlier versions of IE. As a FireFox user and Chrome user, I am so spoiled with good response times, and I am very intolerant to the half second freeze that IE7 and 8 does when I middle-click on a link. And dammit, Microsoft have fixed that! My major complain is gone!

The interface is nice. They have stolen the Google Chrome look, with a thumbnail start page, no status bar (status messages pop up at the bottom) and the Chrome tab style. Well done.

Since I am working on my Monkeybone image format and my Monkeybone Viewer that supports HTML5 canvas export, I also had to try that out in IE9. In IE8, I would get an ActiveX warning and an incorrect render. IE9 still gives the ActiveX warning, but renders the HTML5 output from my application perfectly. The ActiveX warning only apply to local documents, not remote. I can live with that. The HTML5 implementation of Asteroids also works perfectly. Ironically, the site states that Chrome, FireFox, Safari or Opera is required. Screw them!

The developer tools have been greatly improved too. My first impression is that IE9 feels like a modern browser version 1.0, and I hope that we can forget IE8 and earlier as fast as possible. I already use IE (IE8) with Visual Studio at work, and I will wait for the golden release for updating my job computer. At home, I am happy with Chrome, but I will make sure that the stuff I produce looks nice in IE9. It is a good web browser.

Monkeybone: The Spline instruction

Using notepad
The Spline instruction has syntax similar to the Line instruction when named arguments are used, but each value has a magnet attached to it. The line will bend to the magnet. This will draw a red line on a black image, from the upper left to the lower right:

Line #ff0000 X1:0 Y1:0 X2:200 Y2:200

This will draw a green line, also from the upper left to the lower right, but it will be bent, like an S (but mirrored).

Spline #00ff00 X1:0+100 Y1:0+0 X2:200-100 Y2:200+0

Not how X1 has its value set to 0 and its magnet set to +100. This means that the curve will bend off 100 pixels to the left. Note that I don’t want to use the magnet on Y1, so I just add +0. I want X2 to bend 100 pixels to the left, so -100 is added.

This is a working example:

//Create a black picture.
Clear 200x200 #000000

//Set line thikness.
Set Line Thikness To 3

//Draw a red line.
Line #ff0000 X1:0 Y1:0 X2:200 Y2:200

//Draw a green spline.
Spline #00ff00 X1:0+100 Y1:0+0 X2:200-100 Y2:200+0

And this is the result:

Using the .NET library
If you are using the .NET library, this Visual Basic code below, the output will be a .MOB file with exactly the same image. This requires a reference to Monkeybone.dll.

Dim OutputPath As String = System.IO.Path.Combine( _
   System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop), _
   "Spline.mob")
Using Sw As New Monkeybone.MonkeyboneWriter(OutputPath, 200, 200, _
   Drawing.Color.Black)

   'Set line thikness to 3.
   Sw.WriteLineThikness(3)

   'Draw a red line across the picture.
   Dim Line As New Monkeybone.Instructions.Line(0, 0, 200, 200)
   Line.Color = System.Drawing.Color.FromArgb(255, 0, 0)
   Sw.WriteLine(Line)

   'Draw a green spline
   Dim Spline As New Monkeybone.Instructions.Spline(0, 100, 0, 0, 200, _
      -100, 200, 0)
   Spline.Color = System.Drawing.Color.FromArgb(0, 255, 0)
   Sw.WriteLine(Spline)

End Using

Using the Monkeybox control
The Monkeybox control (resides in Monkeybox.dll) is capable of displaying the image on screen and exporting the image to a .MOB file. Given that you are writing a Windows Forms application in Visual Basic, and you have a Monkeybox control named MBox1 on your form, this code will produce the exact same image as shown above:

Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) _
   Handles Me.Shown
   'Size is normaly set in the designer, but here I set it manually.
   MBox1.Width = 200
   MBox1.Height = 200

   'Set the background color and the line thikness.
   MBox1.BackColor = Color.Black
   MBox1.SetLineThikness(3)

   'Draw a red line.
   MBox1.AddLine(Color.FromArgb(255, 0, 0), 0, 0, 200, 200)

   'Draw a green spline.
   MBox1.AddSpline(Color.FromArgb(0, 255, 0), 0, 100, 0, 0, 200, -100, 200, 0)

   'Redraw is not trigged by adding and instruction.
   MBox1.Invalidate()
End Sub

Synchronizing subtitles using the SRT Tool

My aim with SRT Tool is to make synchronization easy. Imagine a scenario where you have an Xvid movie that you want to view. The source might be an imported DVD or something, the point is that you don’t have the subtitles for your particular language, so you download it in SRT format from the web. The usual way to connect a SRT file with an AVI file is to place the files in the same directory and to give the two files the same filename, making the file ending the only difference in the name. Now, when you start the movie (let’s say in VLC) you notice that the subtitles are out of sync. This is how you fix that:

Start the movie. Make a note when the first line is being said. Hour, minute, second and millisecond. Also, write down when the last line is being said. Close your media player.

Start SRT Tool and open the SRT file.

The text file might begin or end with information about who wrote the subtitles or perhaps who ripped it. This has to be deleted, so that the first and the last item of the subtitle file is movie translation (of dialog or other). Let’s say that you want to delete the last item. Do this by pressing End on your keyboard, followed by clicking Delete current in the Edit menu.

Click on the time stamp labeled “First in” to be able to edit it. Correct it with the time you wrote down. Click OK.

Do the same with time stamp labeled “Last in”. Correct it and click OK.

Finally, click Save in the File menu to save your changes to the SRT file. Now, when you start the movie, the subtitles are displayed correctly in sync with the dialogs.

User interaction: GetItemAt and GetItemsAt

Edit: This post concerns “The Wall”, a discontinued project.

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

Edit: This post concerns “The Wall”, a discontinued project.

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

Edit: This post concerns “The Wall”, a discontinued project.

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

Edit: This post concerns “The Wall”, a discontinued project.

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

Edit: This post concerns “The Wall”, a discontinued project.

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.

Photoname 2.0

I haven’t done much coding the last few days. I have spent my time with my family, working with my podcast, changing employer requires some attention after office hours as well. However, I am working on a version 2.0 of Photoname. I have decided to use a much more Explorer like appearance and I imagine that this change will reduce the number of questions I get on the application. I imagine that people actually like Photoname, but the outdated GUI might be an unnecessary obstacle.

Tonight, I will start editing episode 7 of the pod cast and tomorrow is first day at my new job.

Monkeybone: The Line instruction

There are two alternative ways to use the Line instruction in a Monkeybone image (a text file with .mob ending). You can either use named arguments or a list of coordinates. This example demonstrates both alternatives. The first V symbol is drawn using named arguments, the rest of the symbols are drawn using coordinate lists.

Clear 290x200 #a0a0a0
//Draw a V symbol using named arguments.
Line #000000 X1:10 Y1:10 X2:40 Y2:190
Line #000000 X1:40 Y1:190 X2:70 Y2:10
//Draw a V symbol using a polyline.
Line #000000 (80,10) (110,190) (140,10)
//A closed triangle.
Line #000000 (150,10) (180,190) (210,10) AutoClose
//A filled triangle.
Line #000000 (220,10) (250,190) (280,10) Filled

If you are using the Monkeybone .NET library, this code is used to produce a .mob file that contains one simple line and a polyline. To view the picture, open the output file in Monkeybone Viewer. The code requires a reference to the Monkeybone.dll.

Using Sw As New Monkeybone.MonkeyboneWriter("C:\Lines.mob", 200, 200, Drawing.Color.White)

   'Create a line by passing X1, Y1, X2 and Y2 to the constructor of the Line class.
   Dim SimpleLine As New Monkeybone.Instructions.Line(10, 190, 190, 190)
   SimpleLine.Color = Drawing.Color.Black
   Sw.WriteLine(SimpleLine)

   'Create a line by passing an array of coordinates to the constructor.
   Dim Points() As System.Drawing.Point = {New System.Drawing.Point(20, 20), _
      New System.Drawing.Point(180, 20), _
      New System.Drawing.Point(180, 180)}
   Dim PolyLine As New Monkeybone.Instructions.Line(Points)
   PolyLine.Color = Drawing.Color.Red
   Sw.WriteLine(PolyLine)

End Using

Finally, if you are using the Monkeybox control (named MBox1 in the example below) to display graphics directly on the screen, the following code displays one simple line on screen, together with the Monkeybone source code in a message box.

'Set the background color.
MBox1.BackColor = Color.White

'Add a red line to the monkeybox.
MBox1.AddLine(Color.Red, 10, 10, 90, 90)

'Redraw is not trigged by adding and instruction.
MBox1.Invalidate()

'Display the source code.
MessageBox.Show(MBox1.GetSource())

Switch between connections in QTool

I have added a new feature to the simple portable SQL Server query tool, QTool, that I made some time ago (here). Now, you can enter several connections strings in the Connection String tab, and use a drop down list to choose what connection you want your query to run on.

Additionally, you can add a name to the connection by typing a name followed by a colon in front of the connection string for a more clean display in the drop down list.

You can download it from here.

Photoname Portable, the command line arguments

These are the command line arguments that control the actions of pnp.exe, that you can send to it:

-fld [folder]

Renames all images in a specific folder. Specify the folder with images you want to rename, or type start to search for images in the same folder that pnp.exe is started from. Starting pnp.exe like this (from the command prompt):

pnp.exe -fld start

…has the same effect as double clicking it and type:

Rename Folder Start

Also, starting pnp.exe like this:

pnp.exe -fld “C:\Temp”

…has the same effect as double clicking it and type:

Rename Folder “C:\Temp”

-fle [filename]   Gives the specified file a new name. The file must be a jpg file that isn’t already renamed according to the Photoname convention.
-h Shows the available command line arguments.

Download Photoname Portable (25kb).

Photoname Portable

The portable version of Photoname (pnp.exe) doesn’t have a GUI, but it is pretty simple to use anyway. You can either start it from the command interface and pass arguments to it to tell it what to do, or you can double click on it, and then tell it what to do. If you want to control pnp.exe from another application, you must know what arguments you can pass to it.

So, pnp.exe is a portable, lightweight GUI-less version of Photoname.
Some of the commands that you can run if you start it without arguments, that is, just by double clicking it:

Load {Filename} loads an image into memory. If the path or filename contains a space, you need quotation marks around it. Example:

Load "C:\Images\CW005132.jpg"

To view information about the loaded image, type Info. If you provide a filename, that file is loaded and info about that file is displayed. Example:

Info

Info "C:\Images\CW005133.jpg"

To rename one single file, use Rename File {Filename}. Example:

Rename File "C:\Images\CW005134.jpg"

If you ignore the filename, the currently loaded file will be renamed. To rename all files, use Rename Dir {Directory name}. Example:

Rename Dir "C:\Images"

Files that already match the RegEx pattern \d{14}_\d*\.(jpg|jpeg) will be ignored. If photodate is missing in the file, the change date will be used instead. The renamed file will be unloaded from memory in the process of renaming.

Photoname Portable can only handle full path, not relative paths.

For each file that Photoname Portable tries to rename, the output will be a text line that starts with “Ok.” for successful name change and “Rename failed.” for unsuccessful name change.

If you want to use the portable version to rename all images that need renaming, without any tricky typing, you can just type Dir? in the command prompt. Photoname Portable will ask you for a directory, do the name changes and then exit. Example:

Dir?

If you are automating Photoname Portable from another application, consider not sending “Dir?” to it. 😉 The folder browser might show up behind the console window.

Download Photoname Portable (25kb).

Photoname Portable soon introduced

I haven’t done much coding the last few weeks. I am in the process of changing jobs, and the new podcast is of course taking much of my time. My next update however, will be about my new portable lightweight version of Photoname. The portable version doesn’t have a GUI, but a rich set of command line arguments and a simple command line interface of its own.

In the meantime, this is something I can totally relate to: Top 10 Things That Annoy Programmers

Handling user input from The Wall

Edit: This post concerns “The Wall”, a discontinued project.

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

Edit: This post concerns “The Wall”, a discontinued project.

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

Edit: This post concerns “The Wall”, a discontinued project.

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

Edit: This post concerns “The Wall”, a discontinued project.

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

Edit: This post concerns “The Wall”, a discontinued project.

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.