Blog

  • Query tool for XML

    Today I had to be able to query XML files using XPath and view the result clean and structured. Doing this from within Visual Basic is very easy, so making a tool was an easy option. This is the user interface:

    The top pane is used for writing XPath queries. Below, there are three panes. One displays the result as a tree structure, the next displays the attributes of the selected node in the tree view and the last display the source of the selected node.

    This is the Click event of the query button:

    Private Sub DoExecute(ByVal XPath As String)
    
        'Store the last executed query in case the user wants to refresh the query.
        Me.LastExecutedQuery = XPath
    
        'Clear the output textbox.
        txtOutput.Text = ""
    
        'Clear the elements tree view.
        tvElements.Nodes.Clear()
    
        'Clear the attribute list.
        lvAttributes.Items.Clear()
    
        If XPath.Trim() = "" Then
    
            'If no query is sent in, display the root element.
    
            'Display it in the tree (using a custom function not shown here).
            Me.AddNode(Dom.DocumentElement, tvElements.Nodes)
    
            'This is the status bar of the window.
            lblResult.Text = "Elements in result: 1"
    
        Else
    
            'The query might fail.
            Try
    
                Dim Result As Xml.XmlNodeList = Dom.DocumentElement.SelectNodes(XPath)
                If Result Is Nothing Then
                    lblResult.Text = "Elements in result: 0"
                Else
                    If Result.Count = 0 Then
                        lblResult.Text = "Elements in result: 0"
                    Else
                        Me.ResultList = Result
                        lblResult.Text = "Elements in result: " & Result.Count.ToString()
    
                        Dim ResultNode As TreeNode = tvElements.Nodes.Add(XPath.Trim())
                        ResultNode.Tag = "Query"
                        ResultNode.ImageIndex = 3
                        ResultNode.SelectedImageIndex = 3
    
                        'Populate the tree structure (using a custom function not shown here).
                        tvElements.BeginUpdate()
                        For Each Xn As Xml.XmlNode In Result
                            Me.AddNode(Xn, ResultNode.Nodes)
                        Next
                        tvElements.EndUpdate()
    
                        'Expand the root node that contains the result.
                        ResultNode.Expand()
    
                    End If
                End If
    
            Catch ex As Exception
    
                'If the query failed, extract the reason from the exception and display it.
                lblResult.Text = "Elements in result: [Error]"
                txtOutput.Text = "XPath failed." & ControlChars.CrLf & ControlChars.CrLf & ex.Message
    
            End Try
        End If
    
        'Select the first node. Other panes will be updated in the AfterSelect event of the treeview.
        If tvElements.Nodes.Count > 0 Then
            tvElements.SelectedNode = tvElements.Nodes(0)
            tvElements.SelectedNode.EnsureVisible()
        End If
    
    End Sub

    To use this, just open an XML file and click away in the tree view. You can also write XPath queries to browse a subset of the data. If you want to download this early version, the exe file (.NET Framework 3.5) is located here Since 17/1 2010, the program is can be downloaded from here.

  • Big integers in .NET 4.0

    The BigInteger structure becomes available if you add a reference to the System.Numerics namespace. BigInteger represents a positive or negative integer of any size.  This is great for doing arithmetic calculations with very large numbers, and is one of the problems you had to solve on your own in previous versions of .NET Framework.

    After the reference is added, you can create a BigInteger using the New keyword, and an initial value can be passed to the constructor, like so:

    Dim X As New System.Numerics.BigInteger(Long.MaxValue)
    Console.WriteLine(X.ToString())

    To do arithmetic operations, create the BigIntegers you need for the operation, and then call the static (shared) functions of the BigInteger structure to do the calculations. In this case, I call the static function Multiply.

    Dim X As New System.Numerics.BigInteger(Long.MaxValue)
    Dim Y As New System.Numerics.BigInteger(Long.MaxValue)
    Dim Z As System.Numerics.BigInteger = _
         System.Numerics.BigInteger.Multiply(X, Y)
    Console.WriteLine(Z.ToString())

    Just by adding a few of these lines to the above code, will give you one insanely large number.

    Z = System.Numerics.BigInteger.Multiply(Z, Z)
    Z = System.Numerics.BigInteger.Multiply(Z, Z)
    Z = System.Numerics.BigInteger.Multiply(Z, Z)
    Z = System.Numerics.BigInteger.Multiply(Z, Z)

    One way to serialize this number in SQL Server could be to store the underlying bytes of the number that the BigInteger instance represents. The BigInteger structure has a member function that returns these bytes as a byte array called GetByteArray. An existing byte array can be passed to the constructor of the BigInteger to reconstruct the number.

  • Getting the meta data for a table from Visual Basic

    The last time I did this, I needed to build a custom Visual Basic entity generator. After two hours of coding, I had a tiny Windows Forms application that took some connection information and a table name, and returned an entity class with some properties and methods, and a collection class. With initialization, database write-back and all.

    From the Management Studio, a call to the sp_help procedure and pass the name of the table you want to receive meta data about, like this:

    EXEC sp_help 'dbo.spt_values'

    (I still haven’t created any databases on the computer that I am writing this from, so I am grabbing the meta data from the spt_values table in the master database.

    The procedure returns a few sets, and the second one contains a list of the table columns.

    To call this from Visual Basic, you should know that the procedure is located in the sys namespace, and the parameter that it expects is called @objname. So, if you are using a dataset, the table with index 1 contains the column information. If you are using a data reader, you can call the NextResult function, like so (in a console application):

    Using Cn As New SqlClient.SqlConnection("Data Source=.;Initial Catalog=master;Integrated Security=True")
        Cn.Open()
        Using Cmd As New SqlClient.SqlCommand("[sys].[sp_help]", Cn)
            Cmd.CommandType = CommandType.StoredProcedure
            Cmd.Parameters.AddWithValue("@objname", "dbo.spt_values")
            Dim R As SqlClient.SqlDataReader = Cmd.ExecuteReader()
            R.NextResult()
            Dim ColumnNameColumn As Integer = R.GetOrdinal("Column_name")
            Dim ColumnTypeColumn As Integer = R.GetOrdinal("Type")
            Dim ColumnLength As Integer = R.GetOrdinal("Length")
            While R.Read()
                Console.WriteLine(R.GetString(ColumnNameColumn))
                Console.WriteLine(R.GetString(ColumnTypeColumn))
                Console.WriteLine(R.GetInt32(ColumnLength).ToString())
            End While
            R.Close()
        End Using
        Cn.Close()
    End Using

    If you are using this to create something like a code generator, remember that Length column holds the column size in bytes. This means that a nvarchar (Unicode string columns) with the length set to 10, only can hold 5 characters.

    The above code targets .NET Framework 3.5, but it would look exactly the same in the version above and below. It is written in Visual Basic 10 (VBx).

  • Grafikstacken kraschar ibland

    Idag drabbades jag av lite igenkänning mitt i spelprogrammeringen, som fick mig att skriva ett kort inlägg.

    Det händer nästan aldrig i XP, och väldigt sällan i Vista och 7, men ibland kraschar grafikstacken, troligen för att man har gjort något fel. När det väl händer i Windows, så blinkar skärmen till i ett par sekunder, och sedan är allt återställt. Nästan. Jag klagar inte, av XWindows i Linux blir det bara skit kvar om detta händer, men Windows Vista och Windows 7 hackar till och återställer systemet utan någon förlorad data.

    Men under mitt kodande på ninjaspelet på en Vista-dator har jag märkt att nätverket följer med ibland. I två situationer har jag noterat detta. Det ena var när jag klantade till det i XNA, och det andra är när Voddler klantar till det. Det kanske bara är på mitt system det blir så, men det är bra konstigt.

    Men i alla fall, här vill jag säga att jag är imponerad av Windows, som klarar att återgå efter att detta har hänt, vilket jag inte tror att något annat x86-operativ klarar.

  • Ninjaspelet lyfter snart

    Det har runnit en del vatten under broarna när det gäller ninjaspelet. Nu är jag äntligen igång och kodar. Istället för .NET 2.0/Allegro blev plattformen XNA Framework 3.1. Spelet skrivs i Visual Basic och brorsan bistår med grafik. Kvällens aktivitet har varit en sprite-klass.

  • Hardware accelerated graphics through XNA: Getting started

    There are some features of the XNA Framework that is unavailable from Visual Basic, but this should not stop you from writing descent games in Visual Basic. On my machine, I have installed XNA Game Studio 3.1 (a game developing environment from Microsoft) and I also have a beta of Visual Studio 2010 that I am going to use. This example will just contain the code necessary to get something on the screen, a sprite floating across.

    From VS2010, I am using a regular console application and the target platform for the project is .NET Framework 3.5.

    Now I must add two references: Microsoft.Xna.Framework and Microsoft.Xna.Framework.Game. I use version 3.1, the version that got installed when I installed XNA Game Studio 3.1.

    The next step is to create the game class. I call my class TestGame. TestGame should inherit from the Microsoft.Xna.Framework.Game class. In here I create a Main method to get the program started, and I select that method to be the starting point for the program in the Project Settings window. This is the code so far:

    Public Class TestGame
        Inherits Microsoft.Xna.Framework.Game
    
        Public Shared Sub Main()
    
        End Sub
    
    End Class

    In the Main method, I create my game (the TestGame class) and from the constructor, a graphics device manager for the game. I use the graphics device manager to set my preferred resolution (800×600) and to switch to fullscreen mode. Note that I want to keep the reference to the graphics device manager as a member of my game class.

    Public Class TestGame
        Inherits Microsoft.Xna.Framework.Game
    
        Private Gfx As Microsoft.Xna.Framework.GraphicsDeviceManager
    
        Public Shared Sub Main()
            Dim Game As New TestGame()
            Game.Run()
        End Sub
    
        Public Sub New()
            Me.Gfx = New Microsoft.Xna.Framework.GraphicsDeviceManager(Me)
            Me.Gfx.PreferredBackBufferWidth = 800
            Me.Gfx.PreferredBackBufferHeight = 600
            If Not Me.Gfx.IsFullScreen Then
                Me.Gfx.ToggleFullScreen()
            End If
        End Sub
    
    End Class

    The next thing to do is some overrides from the base class. These methods will be overloaded:

    Protected Overrides Sub Initialize()
        MyBase.Initialize()
    End Sub
    
    Protected Overrides Sub LoadContent()
        MyBase.LoadContent()
    End Sub
    
    Protected Overrides Sub UnloadContent()
        MyBase.UnloadContent()
    End Sub
    
    Protected Overrides Sub Update(ByVal gameTime As Microsoft.Xna.Framework.GameTime)
        MyBase.Update(gameTime)
    End Sub
    
    Protected Overrides Sub Draw(ByVal gameTime As Microsoft.Xna.Framework.GameTime)
        MyBase.Draw(gameTime)
    End Sub

    Just to make something happen on the screen, I am adding these members:

    Private Sb As Microsoft.Xna.Framework.Graphics.SpriteBatch
    Private SpriteTexture As Microsoft.Xna.Framework.Graphics.Texture2D
    Private SpriteX As Integer = 0
    Private SpriteY As Integer = 0

    The SpriteBatch will manage my sprites and the Texture2D is the sprite graphics. In the LoadContent function, I will load a sprite from my hard drive.

    Protected Overrides Sub LoadContent()
        Me.Sb = New Microsoft.Xna.Framework.Graphics.SpriteBatch(Me.Gfx.GraphicsDevice)
        Me.SpriteTexture = Microsoft.Xna.Framework.Graphics.Texture2D.FromFile(Me.Gfx.GraphicsDevice, _
             "mysprite.png")
        MyBase.LoadContent()
    End Sub

    The Update function is for changing the game scenery.

    Protected Overrides Sub Update(ByVal gameTime As Microsoft.Xna.Framework.GameTime)
        SpriteX += 1
        SpriteY += 1
        MyBase.Update(gameTime)
    End Sub

    And the Draw function is for screen rendering.

    Protected Overrides Sub Draw(ByVal gameTime As Microsoft.Xna.Framework.GameTime)
        Me.Gfx.GraphicsDevice.Clear(Microsoft.Xna.Framework.Graphics.Color.Black)
        Me.Sb.Begin(Microsoft.Xna.Framework.Graphics.SpriteBlendMode.AlphaBlend)
        Me.Sb.Draw(Me.SpriteTexture, New Microsoft.Xna.Framework.Rectangle(Me.SpriteX, Me.SpriteY, 32, 32), _
             Microsoft.Xna.Framework.Graphics.Color.Red)
        Me.Sb.End()
        MyBase.Draw(gameTime)
    End Sub

    This is the complete code that produces a sprite that floats over the screen in Visual Basic using XNA:

    Public Class TestGame
        Inherits Microsoft.Xna.Framework.Game
    
        Private Gfx As Microsoft.Xna.Framework.GraphicsDeviceManager
    
        Private Sb As Microsoft.Xna.Framework.Graphics.SpriteBatch
        Private SpriteTexture As Microsoft.Xna.Framework.Graphics.Texture2D
        Private SpriteX As Integer = 0
        Private SpriteY As Integer = 0
    
        Public Shared Sub Main()
            Dim Game As New TestGame()
            Game.Run()
        End Sub
    
        Public Sub New()
            Me.Gfx = New Microsoft.Xna.Framework.GraphicsDeviceManager(Me)
            Me.Gfx.PreferredBackBufferWidth = 800
            Me.Gfx.PreferredBackBufferHeight = 600
            If Not Me.Gfx.IsFullScreen Then
                Me.Gfx.ToggleFullScreen()
            End If
        End Sub
    
        Protected Overrides Sub Initialize()
            MyBase.Initialize()
        End Sub
    
        Protected Overrides Sub LoadContent()
            Me.Sb = New Microsoft.Xna.Framework.Graphics.SpriteBatch(Me.Gfx.GraphicsDevice)
            Me.SpriteTexture = Microsoft.Xna.Framework.Graphics.Texture2D.FromFile(Me.Gfx.GraphicsDevice, _
                  "mysprite.png")
            MyBase.LoadContent()
        End Sub
    
        Protected Overrides Sub UnloadContent()
            MyBase.UnloadContent()
        End Sub
    
        Protected Overrides Sub Update(ByVal gameTime As Microsoft.Xna.Framework.GameTime)
            SpriteX += 1
            SpriteY += 1
            MyBase.Update(gameTime)
        End Sub
    
        Protected Overrides Sub Draw(ByVal gameTime As Microsoft.Xna.Framework.GameTime)
            Me.Gfx.GraphicsDevice.Clear(Microsoft.Xna.Framework.Graphics.Color.Black)
            Me.Sb.Begin(Microsoft.Xna.Framework.Graphics.SpriteBlendMode.AlphaBlend)
            Me.Sb.Draw(Me.SpriteTexture, New Microsoft.Xna.Framework.Rectangle(Me.SpriteX, Me.SpriteY, 32, 32), _
                    Microsoft.Xna.Framework.Graphics.Color.Red)
            Me.Sb.End()
            MyBase.Draw(gameTime)
        End Sub
    
    End Class
    
  • The ups and downs of Visual Studio 2010: Auto list members

    In Visual Studio 2010, the auto list members feature is much more intelligent than in previous versions. For example, assuming that X is an object with a visible function called DoSomeWork, in earlier versions of Visual Studio, you would have to know that the method started with Do to find it in the list. If you didn’t know that, you would have to scroll through the list of members and try to recall what you are looking for, or search in the object browser. Now, if you type X.Work, Visual Studio lists DoSomeWork as a suggestion, because matching is done within the name, not only from the beginning of the name. Also, you type an acronym of the function name. DSW would match DoSomeWork.

    Previous versions of Visual Studio applied a “suggest and complete” policy, which is the default in Visual Studio 2010. This is usually the most effected mode. If you are aiming to call the DoSomeWork function, you can type something like X.DoSo and then what ever character you was going to type thereafter, likely an opening parenthesis. The problem with the “suggest and complete” policy shows up when you’re trying to call a function that isn’t implemented yet. The text editor will force your typing to be a call to something other than you are aiming at, something that already exists, at least if the not-yet-existing member has a name that is a subset of an existing name. I always end up grabbing my computer mouse when this happens. This is one example where the “suggest only” policy can be useful. This mode lets you type whatever you want, because it will not force you to choose from something in the list.

    To toggle completion mode, press Ctrl+Alt+Space or look at the IntelliSense sub menu under the Edit menu. Just as the call hierarchy feature, this feature is available no matter what language you’re using, but (at least in the Beta) it only works in the C# editor, not the Visual Basic editor.

    Now, there is no reason to have a mouse connected to the computer anymore. Thank you, Microsoft!

  • The stamping program

    To start this year and decennium, I have dug up my old Windows Forms control for command line interfacing with a user in a Windows environment, a control that I still think allows the programmer to accomplish complex interfacing with hardly any coding at all.

    This program consist of one form only, and the only added control is the CLI control. The name of the CLI control instance is simply Cli1. I have loaded four images as project resources; a background image and three different colored icons. One is red, one is blue and one is green.

    Click on the image to view it in full size.

    This is how the program works: Type Red, Green or Blue to select which color you want to “draw” with. Click on an empty space on the CLI control to place a red, green or blue symbol. Click on an existing symbol to remove it. The complete source code for this:

    Public Class Form1
    
        Private Enum Colors
            None
            Red
            Green
            Blue
        End Enum
    
        Private CurrentColor As Colors = Colors.None
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Cli1.BackgroundImage = My.Resources.Background
            Cli1.WriteLine("Type Red, Green or Blue. Then click!")
        End Sub
    
        Private Sub Cli1_Click(ByVal Source As Object, _
        ByVal PixelX As Integer, ByVal PixelY As Integer, ByVal CharX As Integer, ByVal CharY As Integer) _
        Handles Cli1.Click
            'What symbol did the user click on?
            Dim S As CLIControl.GraphicalElement = Cli1.GraphicalElements.GetElement(PixelX, PixelY)
            'If any, remove it. Else add a new one.
            If S Is Nothing Then
                'Add a symbol.
                Select Case Me.CurrentColor
                    Case Colors.Red
                        Cli1.GraphicalElements.Add(New CLIControl.Picture("", _
                        My.Resources.Circle_Red, PixelX - 16, PixelY - 16))
                    Case Colors.Green
                        Cli1.GraphicalElements.Add(New CLIControl.Picture("", _
                        My.Resources.Circle_Green, PixelX - 16, PixelY - 16))
                    Case Colors.Blue
                        Cli1.GraphicalElements.Add(New CLIControl.Picture("", _
                        My.Resources.Circle_Blue, PixelX - 16, PixelY - 16))
                End Select
            Else
                'Remove a symbol.
                Cli1.GraphicalElements.Remove(S)
            End If
        End Sub
    
        Private Sub Cli1_UserTyped(ByVal Source As Object, ByVal Command As String) Handles Cli1.UserTyped
            If Not Command = "" Then
                Select Case Command.ToLower()
                    Case "red"
                        Me.CurrentColor = Colors.Red
                    Case "green"
                        Me.CurrentColor = Colors.Green
                    Case "blue"
                        Me.CurrentColor = Colors.Blue
                    Case Else
                        Cli1.WriteLine("Nah!")
                End Select
            End If
        End Sub
    
    End Class
    

    The CLI control can be downloaded from this page, and this program (compiled) is located here.

  • Some visual aid

    To conclude, click on an organism to zoom in on it. When an organism is zoomed in, some details about it is shown together with the DNA string of the parent organisms (if the parents are still alive).

    Download: Drifting.exe

    Happy new year!

    If you are interested in looking at the source code, a VS2010 Visual Basic solution can be downloaded here. The solution targets .NET Framework 2.0.

  • Pythonscript för gratis musik

    Som bekant kan man ladda hem hur mycket upphovsrättsskyddad musik som helst, helt gratis och (om så önskas) helt anonymt från Google. Om du är förtjust i scriptingspråket Python, har Nick Jensen filat till ett script som du kan använda för att hämta hem din favoritmusik i MP3-format. Nick Jensen’s script finns att ladda hem här.

  • Using regions

    Regions are used to define a path or an area for later use. The Region instruction takes any number of coordinates (3 or more), and stores them in memory. The region can then be used for drawing. The following example is done in Notepad. I have created a text-file, changed the file ending from .txt to .mob. In the file, I have added these three lines of text:

    Clear #ffffff 70x70
    Region (10,10) (60,10) (60,60) (10,60)
    Line Region #ff00ff

    When loaded in the Monkeybone viewer, this is the result:

    When regions are created using the MonkeyboneWriter class, they are much easier to manipulate. This example defines a shape, writes it, manipulates it, and writes it again.

    Module Module1
    
        Sub Main()
    
            'Create a Monkeybone stream.
            Using W As New Monkeybone.MonkeyboneWriter("C:\regions.mob", 130, 130,
                System.Drawing.Color.Black)
    
                'Define a region.
                Dim R As New Monkeybone.Instructions.Region()
                R.AddPoint(10, 110)
                R.AddPoint(60, 10)
                R.AddPoint(110, 110)
    
                'Write the region to the stream.
                W.WriteLine(R)
    
                'Write an instruction to draw the region outline in green.
                Dim L As New Monkeybone.Instructions.Line()
                L.Color = Drawing.Color.Lime
                L.UseRegion = True
                W.WriteLine(L)
    
                'Modify the region (move it 10 pixels to the
                   left and 10 pixels down) and write it again.
                R.Move(10, 10)
                W.WriteLine(R)
    
                'Write an instruction to draw the region outline in yellow.
                L.Color = Drawing.Color.Yellow
                W.Write(L)
    
                'Flush and close the stream.
                W.Flush()
                W.Close()
            End Using
    
        End Sub
    
    End Module

    The code produces the following mob file:

    Clear #000000 130x130
    Region (10,110) (60,10) (110,110)
    Line Region #00FF00
    Region (20,120) (70,20) (120,120)
    Line Region #FFFF00

    This is the result when it is loaded into the Monkeybone viewer:

  • Some changes made to the viewer

    Some changes are made to the Monkeybone viewer, that is not related to the Monkeybone format (*.mob files). These changes are made just to make the viewer more decent.

    Not only Monkeybone images can be opened. Now, you can open PNG and JPG files as well. Features such as viewing the error log, viewing the source or saving, is only available when a Monkeybone image is loaded.

    When an image is loaded, no matter if it is a Monekybone image or not, the viewer checks the directory for other images. You can use the file menu to load the next or previous image in the folder, or just press F11 for the previous image and F12 for the next.

    Again, these changes are made just to make viewing easier. The Monkeybone viewer is designed to display Monkeybone images. If you are in to serious image viewing, I recommend IrfanView instead. But if you are looking for a viewer of the powerful and editable Monkeybone fomat, the Monkeybone viewer is it.

  • Counting the DNA differences

    The following adjustment is done to the drifting game. In the first version, DNA differences were counted sequentially, meaning that within each group each organism was compared to its neighbor. By changing this so that every organism is compared to every other organism, and then divided to the number of comparisons done within each group, the number of DNA differences within each group is much more accurate. This makes the increasing differences, the drifting, much more obvious.

    The screenshot displays the number of differences just a few years after separation of the groups.

    Download the drifting game here.

  • This is the drifting game!

    The drifting game does not illustrate evolution or the power of natural selection, but change over time and our ability to tell that about relationship to other spices, such as chimpanzees. The board consists of 285 placeholders (19 x 15). Each placeholder can hold one organism. This is an organism.

    The blue number indicates the age in years of the organism. The red number shows the number of offspring the organism has produced. An organism cannot produce offspring on its own; it must mate with another organism of the opposite gender. Light blue rectangle represent male organisms, pink represent female. What else? 😉 The lines are drawn between parents with the child in between.

    In the middle, the DNA of the organism is displayed. The red amino acid pairs with red or yellow amino acid. The green amino acid pairs with green or blue amino acid. A DNA string consists of 24 pairs. The effect of this demonstration will be better if the number of pairs is greater, but it makes the visual overview poorer.

    When organisms breed, the offspring will have a mixture of the parents DNA. Sometimes, mutations occur. Mutations cannot be traced from either parent. A mutation can sometimes be easy to spot, because in a mutation, any amino acid can pair with any amino acid. So a red could pair with a red, but it could also pair with a green. A pair of red and yellow could be a mutation, a pair of red and green is a mutation.

    An organism that isn’t too young or too old might breed and an organism of high age might die and leave room for younger individuals.

    To control: Press Space to pause and press F12 to separate the group in to two groups (can be done once). The expected effect after the split is that the number of DNA differences between individuals in the group will remain the same as the previous total, but the DNA differences between the groups will increase over time, even though no selection is done. The DNA differences are counted for sequentially and divided by the number individuals in a group. So, not every individual is compared with every individual. Correction here.

    Before the population is splitted into two groups (press F12 to do that), the total number of DNA differences is shown. After the population is splitted into two groups, the total number of DNA differences is shown together with the number of DNA differences within each group. Now you can compare the differences within each group (expected to be smaller) with the total number of differences (expected to be larger since the groups are drifting in different directions).

    Download the drifting game here.

  • PhotoName improvements, December 2009

    The following changes are made to PhotoName.

    The Options dialog (click Behaviour and Other settings) lets you control what will happen if you double click an image in the list.

    A new drop down menu (Edit) is added to the menu bar. From there you can change what images are selected in the list. You can choose to select all images, no images or toggle the selection.

    Also, you can view all images as thumbnails, and click on the images you want to select or deselect. To do this, click Edit and Select from thumbnails.

    This is very effective if you want to export images as a gallery, because you have a good overview of what pictures you have in the selected directory and which of them will be included in the gallery.

    You can download PhotoName from here.

  • The Monkeybone writer

    The Monkeybone Viewer takes a mob file and displays its content on screen. The file stores instructions, such as Bar and Line, as Unicode text. These files can be created by hand using any text editor, such as Notepad (shown here, here, here and here).

    To automate the generation of the Monkeybone file, you can write a program that creates a file with instructions (with mob as file ending), and writes the instructions to that file. If you do this using the .NET Framework, you might create a StreamWriter and write lines of text to that writer.

    To ensure that the output file is formatted the correct way, and to make this process easier, you can download and use the Monkeybone library that contains the MonkeyboneWriter class. The MonkeyboneWriter class inherits from the StreamWriter class, and it provides overloads of the WriteLine function that takes objects that represent Monkeybone instructions. To make a Bar instruction appear in the file, create a Monkeybone.MonkeyboneWriter object, create a Monkeybone.Bar object and set the properties of the object. Pass the Monkeybone.Bar object to the WriteLine function of the Monkeybone.MonkeyboneWriter object. To make another Bar instruction appear in the file, you can create a new Bar object or modify the Bar object you already have, and pass it to the WriteLine function again, like so:

    Module Module1
    
        Sub Main()
    
            'Create a Monkeybone stream.
            Using W As New Monkeybone.MonkeyboneWriter("C:\mypicture.mob", _
                200, 170, System.Drawing.Color.Black)
    
                'Create a vertical Monkeybone bar.
                Dim B As New Monkeybone.Instructions.Bar(10, 10, 20, 100)
                B.Orientation = Monkeybone.Instructions.Bar.BarOrientation.Vertical
                B.Color = Drawing.Color.Red
    
                'Write the bar to the stream.
                W.WriteLine(B)
    
                'Modify it, and write it again.
                B.X += 10
                B.Y += 20
                B.Color = Drawing.Color.Yellow
                W.WriteLine(B)
    
                'Modify it, and write it again.
                B.X += 10
                B.Y += 20
                B.Color = Drawing.Color.Green
                W.WriteLine(B)
    
                'A nice sine effect on top of everything!
                Dim SineBar As New Monkeybone.Instructions.Bar(0, 5, 1, 160, Drawing.Color.White)
                SineBar.Orientation = Monkeybone.Instructions.Bar.BarOrientation.Vertical
                For I As Integer = 0 To 31
                    SineBar.X += 6
                    SineBar.BarFillPercent = 60 + CType((Math.Sin(I / 5) * 40), Integer)
                    W.WriteLine(SineBar)
                Next
    
                'Flush and close the stream.
                W.Flush()
                W.Close()
            End Using
    
        End Sub
    
    End Module

    (The code requires a reference to the Monkeybone library.)

    Monkeybone pictures can created using Notepad, from any program that creates a Unicode text file with the mob file ending, or from a .NET application using the MonkeyboneWriter class of the Monkeybone library.

    This is the output from the example program (the contents of the mypicture.mob file):

    Clear #000000 200x170
    Bar #FF0000 X:10 Y:10 W:20 H:100
    Bar #FFFF00 X:20 Y:30 W:20 H:100
    Bar #008000 X:30 Y:50 W:20 H:100
    Bar #FFFFFF X:46 Y:5 W:5 H:160 VFill:60%
    Bar #FFFFFF X:52 Y:5 W:5 H:160 VFill:68%
    Bar #FFFFFF X:58 Y:5 W:5 H:160 VFill:76%
    Bar #FFFFFF X:64 Y:5 W:5 H:160 VFill:83%
    Bar #FFFFFF X:70 Y:5 W:5 H:160 VFill:89%
    Bar #FFFFFF X:76 Y:5 W:5 H:160 VFill:94%
    Bar #FFFFFF X:82 Y:5 W:5 H:160 VFill:97%
    Bar #FFFFFF X:88 Y:5 W:5 H:160 VFill:99%
    Bar #FFFFFF X:94 Y:5 W:5 H:160
    Bar #FFFFFF X:100 Y:5 W:5 H:160 VFill:99%
    Bar #FFFFFF X:106 Y:5 W:5 H:160 VFill:96%
    Bar #FFFFFF X:112 Y:5 W:5 H:160 VFill:92%
    Bar #FFFFFF X:118 Y:5 W:5 H:160 VFill:87%
    Bar #FFFFFF X:124 Y:5 W:5 H:160 VFill:81%
    Bar #FFFFFF X:130 Y:5 W:5 H:160 VFill:73%
    Bar #FFFFFF X:136 Y:5 W:5 H:160 VFill:66%
    Bar #FFFFFF X:142 Y:5 W:5 H:160 VFill:58%
    Bar #FFFFFF X:148 Y:5 W:5 H:160 VFill:50%
    Bar #FFFFFF X:154 Y:5 W:5 H:160 VFill:42%
    Bar #FFFFFF X:160 Y:5 W:5 H:160 VFill:36%
    Bar #FFFFFF X:166 Y:5 W:5 H:160 VFill:30%
    Bar #FFFFFF X:172 Y:5 W:5 H:160 VFill:25%
    Bar #FFFFFF X:178 Y:5 W:5 H:160 VFill:22%
    Bar #FFFFFF X:184 Y:5 W:5 H:160 VFill:20%
    Bar #FFFFFF X:190 Y:5 W:5 H:160 VFill:20%
    Bar #FFFFFF X:196 Y:5 W:5 H:160 VFill:22%
    Bar #FFFFFF X:202 Y:5 W:5 H:160 VFill:25%
    Bar #FFFFFF X:208 Y:5 W:5 H:160 VFill:29%
    Bar #FFFFFF X:214 Y:5 W:5 H:160 VFill:35%
    Bar #FFFFFF X:220 Y:5 W:5 H:160 VFill:41%
    Bar #FFFFFF X:226 Y:5 W:5 H:160 VFill:49%

    If you load the mypicture.mob file in the Monkeybone viewer, this would be the result:

  • Making fun things from the knowledge of evolution

    Evolution is a powerful mechanism, and the powerful source that is behind it is decent with modification plus selection. In nature, it has taken us from simple chemical reactions to complex self-aware organism over billions of years. The structure of any living mammal is very complex, and biology is filled with complicated concepts, and nothing would make any sense if we didn’t know about the very simple concept of evolution. In nature, evolution explains why fossils of different ages look different, and it explains the origin of very complex structures like the cell, the immune system and the human brain, and this knowledge casts light over areas that doesn’t have anything to do with biology, like computer science and computer programming.

    Designed structures are usually simple and have one or a few purposes, while evolved structures usually are complex and have multiple functions. Designed structures usually are things. Obstacles, roads, walls, jugs. Evolved structures usually work as things. Pipes, connections, obstacles, skeletons. This is because evolved structures come about without a given purpose, but are maintained and further developed if the structure is useful.

    Can we use the knowledge of our origin get some fun out of our computer? Yes! I have mentioned John Conway’s game of life earlier.

    This is EvoLisa. It is a program that draws polygons and compares them to a picture. Then it changes the polygons slightly, and again compares them to a picture. Changes that make the polygons look more like the picture are kept, other changes are discarded. The result is a computer generated vector based pictures that looks like the original picture. More generations of change and selection, gives a computer generated picture that is more like the original picture. Here, selection is based on comparison to the original picture, in nature, selection is based on what organisms till survive and reproduce.

  • The simplest query tool ever

    A colleague wanted to do a database query from a computer without any database client. He needed a tool that allowed him to type in a SQL query, and receive a sortable grid with the result set. All of these features are built-in in the .NET Framework, and it didn’t take me more than 2 minutes to do an exe file with these features using Visual Studio 2010. I used .NET 2.0 because these basic features are available in that version, and he did not want to install a newer version of the .NET Framework.

    This is the user interface: A tab strip with three tabs. One for a connection string, one for the query and one for the result grid. The first two contains a textbox each, and the third contains a DataGridView control. Also, the program has a status bar with a label and a toolstrip with two buttons; one for testing the connectionstring that the user enters in the textbox of the first tab, and one for executing the query and presenting the result in the grid.

    The program consist one variable and four event handlers in one form. The variable holds the result set.

    Private Ds As DataSet

    The first function responds to the Load event of the form. This function restores the last values that from the textboxes. This is just for user convenience.

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
    Handles MyBase.Load
        txtCn.Text = CType(Application.UserAppDataRegistry.GetValue("Cn", ""), String)
        txtQuery.Text = CType(Application.UserAppDataRegistry.GetValue("Query", ""), String)
    End Sub

    The second function responds to the Close event of the form. This function saves the values from the textboxes so that they can be restored (in the Load event) in the next session. Also, if needed, it disposes the dataset variable.

    Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) _
    Handles Me.FormClosed
        Application.UserAppDataRegistry.SetValue("Cn", txtCn.Text)
        Application.UserAppDataRegistry.SetValue("Query", txtQuery.Text)
        If Not Ds Is Nothing Then
            Ds.Dispose()
        End If
    End Sub

    This is the handler for the test button. It simply connects to the given data source, and tells if it succeeds or fails.

    Private Sub btnTestConnection_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
    Handles btnTestConnection.Click
        'Jump to the connection tab (the first one).
        TabControl1.SelectedTab = tabConnection
    
        'Do the test.
        Me.Cursor = Cursors.WaitCursor
        Dim Success As Boolean = False
        Try
            Using Cn As New SqlClient.SqlConnection(txtCn.Text)
                Cn.Open()
                Success = (Cn.State = ConnectionState.Open)
                Cn.Close()
            End Using
        Catch ex As Exception
        End Try
        Me.Cursor = Cursors.Default
        If Success Then
            lblStatus.Text = "Connection test succeeded."
            MessageBox.Show("Connection test succeeded.", Me.Text, _
                MessageBoxButtons.OK, MessageBoxIcon.Information)
        Else
            lblStatus.Text = "Connection test failed."
            MessageBox.Show("Connection test failed.", Me.Text, MessageBoxButtons.OK, _
                MessageBoxIcon.Error)
        End If
    End Sub

    Finally, this is the handler for the execute button.

    Private Sub btnExecute_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
    Handles btnExecute.Click
        'Remove the current data table as data source of the grid.
        DataGridView1.DataSource = Nothing
    
        If Not Me.Ds Is Nothing Then
            'If there is an old data set in memory, dispose that.
            Me.Ds.Dispose()
            'To remember that no data is present, set the variable to NULL.
            Me.Ds = Nothing
        End If
      
        'Jump to the result tab (the third one).
        TabControl1.SelectedTab = tabResult
    
        'Do the query and bind the result. Quick and dirty error "handling".
        Me.Cursor = Cursors.WaitCursor
        Try
            Using Cn As New SqlClient.SqlConnection(txtCn.Text)
                Cn.Open()
                Using Cmd As New SqlClient.SqlCommand(txtQuery.Text, Cn)
                    Using Da As New SqlClient.SqlDataAdapter(Cmd)
                        Ds = New DataSet()
                        Da.Fill(Ds)
                        If Ds.Tables.Count > 0 Then
                            DataGridView1.DataSource = Ds.Tables(0)
                            If Ds.Tables.Count > 1 Then
                                Me.Cursor = Cursors.Default
                                MessageBox.Show("More than one dataset was returned.", "Query", _
                                    MessageBoxButtons.OK, MessageBoxIcon.Information)
                            End If
                        Else
                            Me.Cursor = Cursors.Default
                            MessageBox.Show("No dataset was returned.", "Query", _
                                MessageBoxButtons.OK, MessageBoxIcon.Information)
                        End If
                    End Using
                End Using
                Cn.Close()
            End Using
            lblStatus.Text = "Success."
        Catch ex As Exception
            lblStatus.Text = "Failed. " & ex.Message
                Me.Cursor = Cursors.Default
            MessageBox.Show(ex.Message, "Failed", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
        Me.Cursor = Cursors.Default
    End Sub

    So, making a personal query tool doesn’t have to take more than a couple of minutes in .NET.

  • ASP.NET 4.0: Diagrams

    To get your hands on this new and cool feature, create an ASP.NET 4.0 application or web site from within Visual Studio 2010. Check the Data section of the Toolbox window for a new control called Chart. Dragging out a Chart onto a web page creates the following code:

    <asp:Chart ID="Chart1" runat="server">
      <Series>
        <asp:Series Name="Series1">
      </asp:Series>
      </Series>
        <ChartAreas>
          <asp:ChartArea Name="ChartArea1">
        </asp:ChartArea>
      </ChartAreas>
    </asp:Chart>

    There is a huge amount of properties available for the chart. They control the look of the chart, the chart type among other things. I don’t have any databases installed on this computer, so to get some data to do a chart from; I connect the control to a data source that represents the system database master. I use the following query to get a bunch of large numbers:

    SELECT [name],[number] FROM dbo.spt_values WHERE [number]>17000

    I use number as Y value member.

    This is what I have to do to get the fully functional chart! Fooling around with chart types and visual properties is dangerously amusing.

    If you haven’t got a database server at all, you can quickly create an object data source in Visual Basic, and assign that to your chart. Connection this code…

    Public Class MyChartData
    
        Private mValue As Integer
    
        Public Sub New(ByVal Value As Integer)
            Me.mValue = Value
        End Sub
    
        Public ReadOnly Property Value() As Integer
            Get
                Return Me.mValue
            End Get
        End Property
    
        Public Shared Function GetItems() As MyChartData()
            Dim Ret As New List(Of MyChartData)()
            Ret.Add(New MyChartData(10))
            Ret.Add(New MyChartData(20))
            Ret.Add(New MyChartData(15))
            Ret.Add(New MyChartData(25))
            Return Ret.ToArray()
        End Function
    
    End Class

    …gives you this beautiful result:

    Ah, the simplicity! Aaaaah, the power!

  • Lite tramsande med GDI+ i Visual Basic

    Detta ser inte speciellt vackert ut, men jag är mycket imponerad över vad man kan göra med namnrymden System.Drawing och lite GDI+ i Visual Basic.

    Detta är några futtiga kodrader som ritar på två image-objekt. Det ena ritas ny grafik på ovanpå den befintliga (lite sinuskurvor), och den andra bilden rensas innan en gul boll, en svart text och en vit text ritas på. Innan bilden med sinuskurvorna sparas, ritas bilden med texterna och bollen ovanpå den första. Om inte annat kan man fundera på vilka möjligheter System.Drawing egentligen har.

  • The ups and downs of Visual Studio 2010: Fonts and scaling

    The first time I head of the zoom feature of VS2010 was in a talk by Dag König at Microsoft. The level of readability is a very important question for me, and the font rendering of Windows (Clear Type) is superb compared to the blurry font rendering that Macintosh has. The big question, does the zoom feature affect the font rendering of the text editor? To the left, Visual Studio 9 with Consolas 8. To the right, Visual Studio 2010 with Consolas 8.

    VS2010 still uses clear type, and the readability is still there. The hue is slightly reduced, if the anti aliasing is too gray, the text will appear blurry as it does on a Macintosh that only uses a gray scale for smoothing edges. The upper side of reducing the hue is that smoothing works better with text in different colors.  In VS2010, the default color for a class keyword in Visual Basic is cyan as opposed to black in VS9.

    And the zooming feature: Hold down Ctrl and use your mouse wheel. Not a feature I use every day – I use a font size that I can read without zooming, but really cool to use in presentations.

    The .NET Framework lets you control how text is rendered in your programs. The property of the Graphics object you use to control this is called TextRenderingHint. Examine this code:

    Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) _
        Handles Me.Paint
        Using B As New System.Drawing.Bitmap(300, 300)
            Using G As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(B)
                Using F As New System.Drawing.Font("Consolas", 10)
                    G.FillRectangle(Brushes.White, 0, 0, 300, 300)
    
                    'Regular smoothing
                    G.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
                    G.DrawString("Hello", F, Brushes.Black, 10, 10)
    
                    'Regular smoothing with grid fit
                    G.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAliasGridFit
                    G.DrawString("Hello", F, Brushes.Black, 10, 25)
    
                    'Clear Type smoothing with grid fit
                    G.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit
                    G.DrawString("Hello", F, Brushes.Black, 10, 40)
    
                End Using
            End Using
            e.Graphics.DrawImage(B, 0, 0)
        End Using
    End Sub

    The option called AntiAlias renders text in a similar way to the Macintosh. The text appears blurry, but the outcome has true proportions, meaning that what you see on screen is a blurrier version of what you would see on a printed version. This option works best in high resolutions and for print previewing.

    The AntiAliasGridFit makes the text less blurry, because letters align to the pixel grid of the screen. The downside is that character spacing is incorrect, but readability is much higher. This option works best with CRT screens.

    The ClearTypeGridFit also aligns characters to the pixel grid, but it uses clear type. This option works best with a flat screen.

    The output from the above code is shown here:

  • The ups and downs of Visual Studio 2010: Call Hierarchy

    The function that finds all references to a function or a variable has been in Visual Studio for a few versions now. VS2010 has a similar feature called Call Hierarchy. Right click on any function definition or function call, and click View Call Hierarchy. This shows the Call Hierarchy window with a tree structure that displays what other functions are called from the function you clicked on, and who is calling it. This can help discover unused code and understanding the call stack of a program. In C#, not in Visual Basic. The View Call Hierarchy isn’t there if you right click on a Visual Basic function in VS2010 Beta 2. A quick look at Microsoft Connect tells me that the subject has been brought up, but nothing else has happened yet.

    One thing that does work, is the automated generation of sequence diagrams. VS2010 not only does this automatically, but the output is also editable. Objects on the diagram can be resized, moved or deleted, and new items can be added. All you have to do is click Generate Sequence Diagram.

  • Make a HTML gallery from your photos

    The latest feature in PhotoName: Make a HTML gallery from a bunch of photos!

    Download PhotoName from here. If you have a previous version installed, remember to uninstall that first (from the Windows Control Panel).

  • PowerShell and Windows 7

    I should have posted this long ago, but here it is. I did not manage to install PowerShell 2.0 on Windows 7. Windows complained about a newer version that already was supposed to exist on the system. And yes, just open the Run dialog (Win+R) and type powershell, and there it is.

    To start the graphical version, type powershell_ise in the Run dialog.

    If you want to be able to start it without doing any typing, you can right click on it in the taskbar, and select Pin this program to taskbar.

  • Dual coordinate systems

    This picture illustrates the different coordinate systems that Monkeybone is using. Both lines are drawn from 0, 0 to 30, 30. The yellow line is drawn using the coordinate system of the image itself, and the green line is drawn using the coordinate system of the diagram.

    The syntax is the same for DiagramLine and Line, the coordinate system is the only difference. This means that you can choose to use named arguments or points encapsulated by parenthesis. This is the source for the above image:

    //Set size and background color.
    Clear 320x200 #667788
    
    //Just to make it more visible, set line thikness to 3 pixels.
    Set Line Thikness To 3
    
    //Create a diagram.
    Diagram #8899aa X:20 Y:20 W:280 H:160
    
    //Draw a yellow line on the image from 0,0 to 30,30.
    Line #ffff00 (0,0) (30,30)
    
    //Draw a green line on the diagram from 0,0 to 30,30.
    DiagramLine #00ff00 (0,0) (30,30)

    Note: A line can be anything from one to 1000 pixels wide.

  • Compressing Genesis

    From here, I have downloaded Genesis to see what the GZip stream is good for. GZip is suitable for compressing text, because the file format is totally clean (uncompressed) and the Deflate algorithm manages therefore to compress text to a high ratio. And I like the simile that deflating Genesis leaves very little left. It sort of works with my naturalistic worldview.

    The function, CompressText is unchanged, so I only show the Main subroutine.

    Sub Main()
    
        'Load genesis.
        Dim S As String
        Using Sr As New System.IO.StreamReader("genesis.txt", System.Text.Encoding.UTF8)
            S = Sr.ReadToEnd()
            Sr.Close()
        End Using
    
        Console.WriteLine("{0} characters, {1} bytes.", S.Length, S.Length * 2)
    
        'Compress it, and display the result.
        Dim B() As Byte = CompressText(S)
        Console.WriteLine("Compressed to {0} bytes.", B.Length.ToString())
    
        Console.WriteLine("Difference: {0}%", (((S.Length * 2) / B.Length) * 100).ToString("n0"))
    End Sub

    In this case, the uncompressed version is 588% of the size of the compressed version.

  • Compressing text

    I had a situation today when I had to fit about 12.000 bytes of text in 5.000 byte storage. In .NET, this is so easy to do. Just a few lines of code is required to convert a long String to a short Byte array. Examine the CompressText function. This particular example, compresses 252 characters to 287 bytes, but on larger text pieces, the effect is better. Enjoy!

    Module Module1
    
        Sub Main()
    
            'For the example, create some text!
            Dim S As New System.Text.StringBuilder()
            S.Append("This is some text that I want to compress. ")
            S.Append("Uncompressed, this text of 252 characters ")
            S.Append("consumes 504 bytes of memory with UTF-8 ")
            S.Append("encoding. The effect of the compression ")
            S.Append("is much better with a larger piece of text. ")
            S.Append("Compressing XML this way is very effective.")
    
            'Compress it, and display the result.
            Dim B() As Byte = CompressText(S.ToString())
            Console.WriteLine("Compressed to {0} bytes.", B.Length.ToString())
    
        End Sub
    
        Private Function CompressText(ByVal T As String) As Byte()
            Dim B() As Byte = System.Text.Encoding.UTF8.GetBytes(T)
            Using MemStream As New System.IO.MemoryStream()
                Using GZStream As New System.IO.Compression.GZipStream(MemStream, _
                 IO.Compression.CompressionMode.Compress)
                    GZStream.Write(B, 0, B.Length)
                    GZStream.Close()
                    Return MemStream.ToArray()
                End Using
            End Using
        End Function
    
    End Module
    
  • Installation

    The installation program can be downloaded from here or from the Monkeybone page. If you have a previous version of Monkeybone Viewer installed, don’t forget to uninstall that (from the Control Panel) before installing a new version. The installation program registers the MOB file ending with the viewer, so if you double click a Monkeybone picture (*.mob-file), it will open in Monkeybone Viewer.

    Check the Monkeybone tag for news on Monkeybone.

  • Collection initializers

    Now I have had the opportunity to try out the new collection initializers of Visual Basic 10. This is good stuff and I am very happy about being able to do line breaks when I use this (just as C programmers can do whenever they want). Examine this simple example that consist of a ContactPerson class, and a generic collection that I initialize using the collection initializer.

    Module Module1
    
        Public Class ContactPerson
            Public FirstName As String
            Public LastName As String
            Public EMail As String
    
            Public Overrides Function ToString() As String
                Return Me.FirstName & " " & Me.LastName & " " & Me.EMail
            End Function
        End Class
    
        Sub Main()
    
            Dim L As New List(Of ContactPerson) From {
             {New ContactPerson With {.FirstName = "Anders", .LastName = "Andersson", .EMail = "anders@some.thing"}},
             {New ContactPerson With {.FirstName = "Bertil", .LastName = "Bengtsson", .EMail = "bertil@some.thing"}},
             {New ContactPerson With {.FirstName = "Calle", .LastName = "Ceder", .EMail = "calle@some.thing"}}
             }
    
            For Each P As ContactPerson In L
                Console.WriteLine(P.ToString())
            Next
    
        End Sub
    
    End Module

    Note that the element type does not require any special constructor, I can provide a constructor and target that, but here I am using the object initializer that was introduced in Visual Basic 9.

    Instead of the parenthesis that I would use to call the List constructor, I use the From keyword with a curly bracket, and each element is surrounded by curly brackets, separated by a comma. Finally, I have to use another set of curly brackets because I use the object initializer for each element, instead of a regular constructor.

    If I adapt this code to use a constructor for each element, this is how it could look. This uses the new collection initializer and traditional constructors (and therefor less curly brackets).

    Module Module1
    
        Public Class ContactPerson
            Public Sub New(ByVal FirstName As String, ByVal LastName As String, ByVal EMail As String)
                Me.FirstName = FirstName
                Me.LastName = LastName
                Me.EMail = EMail
            End Sub
            Public FirstName As String
            Public LastName As String
            Public EMail As String
    
            Public Overrides Function ToString() As String
                Return Me.FirstName & " " & Me.LastName & " " & Me.EMail
            End Function
        End Class
    
        Sub Main()
    
            Dim L As New List(Of ContactPerson) From {
             {New ContactPerson("Anders", "Andersson", "anders@some.thing")},
             {New ContactPerson("Bertil", "Bengtsson", "bertil@some.thing")},
             {New ContactPerson("Calle", "Ceder", "calle@some.thing")}
             }
    
            For Each P As ContactPerson In L
                Console.WriteLine(P.ToString())
            Next
    
        End Sub
    
    End Module
  • Drawing lines

    The basic syntax for drawing lines is this: Use the Line instruction, pass a start coordinate (X1 and Y1) and an end coordinate (X2 and Y2) and a color. This example draws a line across the picture:

    //Set image size and background color.
    Clear 400x300 #ffffff
    
    //Simple line.
    Line #000000 X1:0 Y1:0 X2:400 Y2:300

    The coordinates can be given in an alternative nameless format. This is useful when drawing multiple lines with one single line instruction. This code draws a red U-shape.

    //Set image size and background color.
    Clear 400x300 #ffffff
    
    //Polyline
    Line #ff0000 (10,10) (10,290) (390,290) (390,10)

    To close this shape,  you can add the (10,10) coordinate to the end of this line, telling Monkeybone to draw a line from (390,10) to the startpoint at (10,10), or you can add the AutoClose argument. This code draws a red rectangle:

    //Set image size and background color.
    Clear 400x300 #ffffff
    
    //Polyline
    Line #ff0000 (10,10) (10,290) (390,290) (390,10) AutoClose

    To draw a filled rectangle instead of a rectangle contour, use the Filled argument instead of the AutoClose argument. This code draws a yellow box with black outline:

    //Set image size and background color.
    Clear 400x300 #ffffff
    
    //Polyline
    Line #ffff00 (10,10) (10,290) (390,290) (390,10) Filled
    Line #000000 (10,10) (10,290) (390,290) (390,10) AutoClose
  • Monkeybone: Creating a bar diagram using Notepad part 4/4

    Continued from here.

    To finish this, I want to add some effects, and save it as a png file.

    Adding shadows
    To add shadows behind each bar, just add the Shadowed argument to each bar. Example:

    DiagramBar #ff0000 X:25  Y:0 W:20 H:200 Label="Apples"  Value="1" Shadowed

    Adding gradient background
    To give the image a gradient background, replace the color argument with a VGrad or HGrad. VGrad does a vertical gradient and HGrad does a horizontal. Example:

    The changes I have made is marked with bold font.

    //Set image size and background color.
    Clear 400x300 VGrad:#d0d0d0-#f0f0f0
    
    //Create a white diagram.
    Diagram #ffffff X:25 Y:40 W:350 H:230 "Some fruit"
    
    //Create 5 bars.
    DiagramBar #ff0000 X:25  Y:0 W:20 H:200 Label="Apples"  Value="1" Shadowed
    DiagramBar #00ff00 X:95  Y:0 W:20 H:50  Label="Pears"   Value="2" Shadowed
    DiagramBar #0000ff X:165 Y:0 W:20 H:150 Label="Oranges" Value="3" Shadowed
    DiagramBar #ff00ff X:235 Y:0 W:20 H:180 Label="Peaches" Value="4" Shadowed
    DiagramBar #f2f200 X:305 Y:0 W:20 H:100 Label="Grapes"  Value="5" Shadowed

    This is the result:

    If your pictures didn’t come out as expected, you can check the error log in the View window. This video shows these steps. Also, the png export feature is shown.

  • Monkeybone: Creating a bar diagram using Notepad part 3/4

    Continued from here.

    Text can be added below and above each bar. To add text below, use the Label argument. To add text above, use the Value argument. I show the complete file content below; the latest additions are highlighted with bold font. The text below each bar is a fruit name, and the text above are numbers. As diagram title, I have chosen Some fruit. The diagram title is a nameless argument. The code so far:

    //Set image size and background color.
    Clear 400x300 #e0e0e0
    
    //Create a white diagram.
    Diagram #ffffff X:25 Y:40 W:350 H:230 "Some fruit"
    
    //Create 5 bars.
    DiagramBar #ff0000 X:25  Y:0 W:20 H:200 Label="Apples"  Value="1"
    DiagramBar #00ff00 X:95  Y:0 W:20 H:50  Label="Pears"   Value="2"
    DiagramBar #0000ff X:165 Y:0 W:20 H:150 Label="Oranges" Value="3"
    DiagramBar #ff00ff X:235 Y:0 W:20 H:180 Label="Peaches" Value="4"
    DiagramBar #f2f200 X:305 Y:0 W:20 H:100 Label="Grapes"  Value="5"

    This is the result:

    To be concluded.

  • Monkeybone: Creating a bar diagram using Notepad part 2/4

    Continued from here.

    Bars can be added to a diagram using the DiagramBar instruction. DiagramBar differs from the Bar instruction in that it use a virtual coordinate system (from a previous Diagram instruction) with its zero position in the left bottom corner, as opposed to the image itself that has its zero position in the top left corner. Like the Bar instruction, the DiagramBar instruction takes a color, position and size. Adding these lines (bold) will create five bars on the diagram.

    //Set image size and background color.
    Clear 400x300 #e0e0e0
    
    //Create a white diagram.
    Diagram #ffffff X:25 Y:40 W:350 H:230
    
    //Create 5 bars.
    DiagramBar #ff0000 X:25  Y:0 W:20 H:200
    DiagramBar #00ff00 X:95  Y:0 W:20 H:50
    DiagramBar #0000ff X:165 Y:0 W:20 H:150
    DiagramBar #ff00ff X:235 Y:0 W:20 H:180
    DiagramBar #f2f200 X:305 Y:0 W:20 H:100

    Your picture should now look like this.

    Unlike the Bar instruction, the DiagramBar instruction does not understand the HFill or the VFill argument.

    If you are doing this in notepad, you might want to make use of automatic X positioning. By changing the X position to X:Auto/5, Monkeybone calculates the X position for you, assuming that 5 bars will be added. I don’t recommend that you use this feature when you are automating the diagram creation, but it is a time saver when you are working with notepad. Just enter X:Auto/n where n is the total number of bars. Example:

    DiagramBar #334455 X:Auto/2 Y:0 W:30 H:120
    DiagramBar #556677 X:Auto/2 Y:0 W:30 H:130

    Continued here.

  • Monkeybone: Creating a bar diagram using Notepad part 1/4

    To make a diagram by hand using Notepad, start Notepad, click File and Save as. Change the filter from txt to All files. Provide a filename that ends with .mob (I will use bardiagram.mob in my example) and change the encoding to UTF-8. Then, click save. Keep Notepad open and write your instructions there.

    Open the Monkeybone Viewer and open the bardiagram.mob file (you can use Open in the file Menu or just drag and drop bardiagram.mob onto the Monkeybone Viewer window). Note that the filename of your mob file is now showing in the title bar of Monkeybone viewer.

    First, we specify the size and background color of the image using the Clear instruction. This will make a light gray image 400 pixels wide and 300 pixels high.

    Clear 400x300 #e0e0e0

    This video shows these steps.

    To position the diagram on the picture, use the Diagram instruction. The arguments are it’s position, size and background color. This line create a white diagram.

    Diagram #ffffff X:25 Y:40 W:350 H:230

    The result of this, might look very much like a light gray image with a white Bar on it, but unlike a Bar, a Diagram has a coordinate system on it’s own. The image has it’s 0,0 at the top left and higher values are located to the right (X) and below (Y). Anything that is drawn on a Diagram, will be drawn using the Diagrams coordinate system. 0,0 is at the bottom left and higher values are located to the right (X) and above (Y). Adding a Bar and a DiagramBar with the same arguments, will not place them on top of each other, because the Bar will be drawn on the image using the images coordinate system, and the DiagramBar will be drawn on the Diagram, using the diagrams coordinate system.

    Part 2.

  • Drawing bars

    To do bars, the Bar instruction is used. It takes the color, position and size as arguments. This code…

    //Set image size and background color.
    Clear 100x100 #003366
    
    //Draw a dark blue bar that covers most of the image.
    Bar #225599 X:10 Y:10 W:80 H:80

    …produces this blue rectangle:

    To do a bar that is only party filled; you can specify the percentage of the filling as an additional argument. In this example, I draw a white rectangle over the blue rectangle, on the exact same place as it. Also, I use the VFill argument to specify that the height will be only 75% of the full rectangle. This code…

    //Set image size and background color.
    Clear 100x100 #003366
    
    //Draw a dark blue bar that covers most of the image.
    Bar #225599 X:10 Y:10 W:80 H:80
    
    //Draw a white bar on over the dark blue bar.
    //Let it be a horizontal bar, 75% filled.
    Bar #ffffff X:10 Y:10 W:80 H:80 VFill:75%

    …produces this white bar over the blue rectangle:

    The argument used for doing a bar that is partly filled horizontally, use HFill instead of VFill.

  • Short introduction to Monkeybone

    The posts that I am doing on Monkeybone might only be interesting if you are develop programs that do charting or if you want to be able to produce nice looking charts. Monkeybone is a vector image format, mainly designed for producing bar charts and line charts. Monkeybone images are text files (UTF-8) that are interpretated using Regular Expressions. Each line is a drawing instruction (linefeed, \n, terminates each instruction) and arguments are separated using space. The first part of each line is the name of the drawing instruction, but arguments has no order. The format of the argument determines what the argument is. I have given the Monkeybone format an own section on the site, and I will post some examples in the blog. The image shows a simple Monkeybone image (exportet to PNG for display on this site).

  • Mobil version av Evolutionsteori.se

    In short: I am working on a mobile theme for my Swedish site on natural science.

    Efter att ha installerat en addon för att få en mobil version av WinSoft.se tänkte jag fumla runt lite med Evolutionsteori.se för att få en iPhone-vänlig version av den också. Nu byter Evolutionsteori.se till ett enklare mobilt tema, endast om klienten är just en iPhone. När temat är färdigt, har jag som ambition att utöka detta till alla mobila enheter. Jag är i stort behov av tips kring detta.

  • Vanliga missförstånd om evolution

    Vi fick den stora äran att publicera ett svar på en insändare om evolutionsteorin som publicerades i tidningen Dagen. Det som vänds emot evolutionsteorin i insändaren, är sådant som de flesta betraktar som avhandlat och färdigbemött, som t.ex. Piltdown-mannen, och detta svar borde avfärda denna kritik för sista gången.

    Svaret är skrivet författaren Patrik Lindenfors, och här på Evolutionsteori.se kan du läsa både insändaren i sin helhet och Patrik Lindenfors svar.

  • PhotoName improvements, October 2009

    A new dialog for manipulating the programs behavior is added. From there, you can tell PhotoName what to do with images that lacks an embedded photo date.

    Download PhotoName from this page, but remember to uninstall any previous version first. For more posts on this application, check the PhotoName tag.

  • Make your blog rock on the iPhone

    You might have noticed that my blog looks absolutely great when you read it in your iPhone. Many thanks to the ContentRobot company. I use their add-on for WordPress called iWPhone. It is a add-on, an adaptation and theme, and installs really easy. You have to upload a file, a folder and finally do a few clicks in the administration tool, and you are done. Impressing.

  • How to download a file, the PowerShell way

    If you want to try this out, please read this first. There, I did an upload using FTP with network credentials (username and password). This time, I want to show how to download a file using HTTP. I am using PowerShell 2.0.

    #Load the System.Net namespace.
    [System.Reflection.Assembly]::Load
    ("System.Net, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
    
    #Load the System.IO namespace.
    [System.Reflection.Assembly]::Load
    ("System.IO, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
    
    #The target filename on the local system.
    $Target =  "C:\downloaded.wav"
    
    #Full source path.
    $RemoteSource = "http://www.mysite.com/myfile.wav"
    
    #Use the static method Create to create a web request.
    #Pass the destination as an argument, and cast it to a HttpWebRequest.
    $R=[System.Net.HttpWebRequest][System.Net.WebRequest]::Create($RemoteSource)
    
    #If not anonymous requests are allowed, you can
    #add a System.Net.NetworkCredential to the Credentials
    #property of the request object ($R).
    
    #What kind of method it will represent? A http request.
    $R.Method = "GET"
    
    #Execute and grab the response object (System.Net.WebResponse).
    $Resp = $R.GetResponse()
    
    #Get a reference to the response stream (System.IO.Stream).
    $RespStream = $Resp.GetResponseStream()
    
    #Create a stream to write to the file system.
    $Wrt = [System.IO.File]::Create($Target)
    
    #Create the buffer for copying data.
    $Buffer = New-Object Byte[] 1024
    
    #In an iteration...
    Do {
    
    #...attemt to read one kilobyte of data from the web response stream.
    $BytesRead = $RespStream.Read($Buffer, 0, $Buffer.Length)
    
    #Write the just-read bytes to the target file.
    $Wrt.Write($Buffer, 0, $BytesRead)
    
    #Iterate while there's still data on the web response stream.
    } While ($BytesRead -gt 0)
    
    #Close the stream.
    $RespStream.Close()
    $RespStream.Dispose()
    
    #Flush and close the writer.
    $Wrt.Flush()
    $Wrt.Close()
    $Wrt.Dispose()
    

    Happy coding!

  • Referring to a function

    Delegates are used to refer to a function. You define a delegate class (one row) using the keyword Delegate, and when it is created, or instantiated, the instance refers to a function. The code that reaches the delegate instance, can call the function it refers to, no matter if it reaches the function itself. This is a very simple example in a form:

    Public Class Form1
    
        Friend Delegate Sub MyDelegateClass()
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim X As New MyDelegateClass(AddressOf Me.DoSomething)
            X()
            X()
        End Sub
    
        Private Sub DoSomething()
            MessageBox.Show("Hello!")
        End Sub
    
    End Class
    

    The result of this code is of course that the message box is shown twice. In this example, I don’t accomplish anything with the delegate, because I could have called the function DoSomething directly, but delegates can be used to pass functions as parameters or for thread shifting (se the InvokeRequired property).

    If I want, I can use the Function keyword to add a anonymous function to the delegate constructor instead of a the name of a existing function.

    Public Class Form1
    
        Friend Delegate Sub MyDelegateClass()
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim X As New MyDelegateClass(Function() MessageBox.Show("Hello"))
            X()
            X()
        End Sub
    
    End Class
    

    The limitation of anonymous functions in Visual Basic 9 is that they only can contain one statement. It can still be used to do pretty good functional programming. Parameters are supported.

    If I was to pass a function as a parameter to another function, the type of the parameter would be the delegate class, like this:

    Public Class Form1
    
        Friend Delegate Sub MyDelegateClass()
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim X As New MyDelegateClass(Function() MessageBox.Show("Hello"))
            Me.CallSomething(X)
        End Sub
    
        Private Sub CallSomething(ByVal X As MyDelegateClass)
            X()
            X()
        End Sub
    
    End Class
    

    Again, the result will be that two message boxes are shown.

  • Web 2.0 at its best

    Jeana Lee Tahnk is using a beautiful addon by Meebo on her WordPress blog (and yes, it does work with Internet Explorer 8). Take a look at this post about free iPhone applications. Let’s say that I want to share this content with my friends.

    Place your mouse over it, to get the direct responce that this can be shared.

    Just start dragging, to get the available drop targets nicely presented to you.

    And just by dropping it, you have shared the content that you were dragging. As a user, I have not much to complain about! I consider this a nice hint of what the future of HTML and the World Wide Web might look like.

  • Functions: Passing by value and by reference

    This is really one of the simplest concepts ever, but since this is something that you need to know as well as something you can benefit from knowing, I think it can be worth a post. Consider this this code:

    Class MyProgram
    
        Shared Sub Main()
            Dim X As Integer = 10
            DoSomething(X)
            Console.WriteLine(X)
        End Sub
    
        Private Shared Sub DoSomething(ByVal X As Integer)
            X += 1
        End Sub
    
    End Class
    

    The output you get here is of course 10. X in DoSomething is different from X is Main, and the variable X in DoSomething is just initialized with the value 10, and then it is increased by one to 11 and thereafter it is destroyed, leaving X in main with the value 10. This is because the parameter is passed by value (ByVal).

    If I was to change the parameter in DoSomething to be passed by reference instead, as in the following code, the output would be 11.

    Class MyProgram
    
        Shared Sub Main()
            Dim X As Integer = 10
            DoSomething(X)
            Console.WriteLine(X)
        End Sub
    
        Private Shared Sub DoSomething(ByRef X As Integer)
            X += 1
        End Sub
    
    End Class
    

    This is because DoSomething no longer holds an own integer variable, just a reference to the variable that is passed by the caller, Main. When X in Main is passed to DoSomething, and DoSomething is manipulating that value, the value is changed.

    When I work with objects, the rules are the same, but the effect is different. If I was to pass a bitmap to a function, and the function then is manipulated, the original bitmap will be affected no matter if it is passed by value or by reference (ByRef). This is because the value of the bitmap object variable is a reference to the actual object, and a reference to a object variable also is a reference to the same actual object.

    Consider this code:

    Class MyProgram
    
        Shared Sub Main()
            Dim B As New System.Drawing.Bitmap(100, 100)
            DoSomething(B)
            Console.WriteLine(B.Width.ToString())
        End Sub
    
        Private Shared Sub DoSomething(ByVal B As System.Drawing.Image)
            B = New System.Drawing.Bitmap(200, 200)
        End Sub
    
    End Class
    

    The output will be 100, because when you change the value of an object variable (the value of an object variable is the reference to the actual object) the passing variable is not affected, because the code holds two variables: B in Main and B in DoSomething. Changing the value of B in DoSomething will not affect B in Main.

    Changing the ByVal in DoSomething to ByRef, would give an output of 200, since the code then only would contain one variable: B in Main. DoSomething will simply refer to that variable.

  • Functions: Shadowing

    Over the years, functions has grown to become a quite complex and flexible feature in Visual Basic. The striking flexibility of the parameters, the modifiers that can apply a function and the function attributes, gives you great possibilities when you are coding. Some of the techniques include multiple return values and recursion and some of the features include passing by value, passing by reference, parameter arrays and shadowing. Shadowing is a feature that I find very useful when designing dialogs.

    The ShowDialog function, that is inherited from the Form class, is a common subject of shadowing for me. It holds two overloads, one parameterless and one that takes the owner form. Shadowing lets you create a new version of a function, no matter if it is overridable or not, and at the same time block all current overloads. So any form that I want to add a mandatory parameter to, I shadow the ShowDialog function. This is a typical function declaration in my Windows applications:

    Public Shadows Function ShowDialog(ByVal Owner As IWin32Window, _
    ByVal CustomerID As Integer) As DialogResult

    By automagic, the current versions of ShowDialog in my form disappears, and this function (the function that does the shadowing) is the one that can be called to display the form as a dialog. A implementation could look like this:

    Public Shadows Function ShowDialog(ByVal Owner As IWin32Window, _
    ByVal CustomerID As Integer) As DialogResult
       Me.mCustomerID = CustomerID
       Return MyBase.ShowDialog(Owner)
    End Function

    The initialization would then be done in the Load event.

    Shadowing is one of the killer features that from what I know is quite unique for Visual Basic.

  • Calling a function

    The parenthesis are important when you are calling a function in PowerShell. The parenthesis tells PowerShell that you intend to call the method, not acquire a reference to it. This code illustrates this.

    $random = New-Object System.Random
    $response1 = $random.next
    $response2 = $random.next()

    The $response1 variable will contain a reference to the function next, and the $response2 variable will contain an integer value, like 1611459187. The type of $response1 is System.Management.Automation.PSMethod and the type of $response2 is int32. If you want to use the reference to the function, use its Invoke method:

    Write-Output $response1.Invoke()

    To call static function, type the path to the function (namespaces and classes) followed by a double colon (::), and then the name of the function. Parenthesis are required, even if the function doesn’t take any parameters.

    [System.Reflection.Assembly]::Load
    ("System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
    
    [System.Windows.Forms.MessageBox]::Show("Hello!")

  • How to upload a file, the PowerShell way

    If you haven’t activated scripting in PowerShell, do that first.

    To access the System.Net namespace, I have to load it using the Load method (System.Reflection.Assembly.Load). To know what version and public key you must refer to, check the System.Net item in Explorer (C:\Windows\assembly).

    This is the code, directly converted from the Visual Basic version:

    #Load the System.Net namespace.
    [System.Reflection.Assembly]::Load
    ("System.Net, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
    
    #The full path to the source file.
    $Source =  "C:\MyFiles\SourceFile.txt"
    
    #The full destination path (will be created).
    $Destination = "ftp://www.myserver.com/myfolder/destination.txt"
    
    #Use the static method Create to create a web request.
    #Pass the destination as an argument, and cast it to a FtpWebRequest.
    $R=[System.Net.FtpWebRequest][System.Net.WebRequest]::Create($Destination)
    
    #Tell the request how it will login (using a NetworkCredential object)
    $R.Credentials = New-Object System.Net.NetworkCredential("myUsername", "P@ssw0rd")
    
    #...and what kind of method it will represent. A file upload.
    $R.Method = "STOR"
    
    #Here I use the simplest method I can imagine to get the
    #bytes from the file to an byte array.
    $FileContens = [System.IO.File]::ReadAllBytes($Source)
    
    #Finaly, I put the bytes on the request stream.
    $S = $R.GetRequestStream()
    $S.Write($FileContens, 0, $FileContens.Length)
    $S.Close()
    $S.Dispose()

    This code gives a good example on PowerShell syntax and it clearly illustrates the power and versatility of the language.

    I used Graphical Windows with PowerShell 2.0 to do this example.

    This example shows how to download a file using PowerShell.

  • EnsureMaximumSize and GetThumbnail

    The WsImage class wraps a System.Drawing.Bitmap object. It has two methods to control size called EnsureMaximumSize and GetThumbnail. These are the differences:

    EnsureMaximumSize transforms the bitmap that is encapsulated in the WsImage object, GetThumbnail returns a bitmap and leaves the encapsulated bitmap unchanged.

    EnsureMaximumSize maintains the aspect ratio of the picture and the bitmap object, GetThumbnail returns a rectangular bitmap object with a the original picture drawn onto it. The picture still has maintained aspect radio. You can pass a brush object to control the background, or pass null (Nothing) if you want the background to be transparent.

    The similarity is that both EnsureMaximumSize and GetThumbnail only takes one integer parameter to control size. That integer represents the width if the width is larger than the height, otherwise it represents the height.

    If you load an image sized 800×600 and pass 700 to the EnsureMaximumSize function, it will return True and the image will be sized 700×525. If you load an image sized 300×400 and pass 350 to the EnsureMaximumSize function, it will return True and the Image will be sized 262×350 pixels. If you load an image sized 300×400 and pass 450 to the EnsureMaximumSize function, it will return False and the image will not be resized.

    Download WsImage.

  • My and Microsoft.VisualBasic namespaces

    I never use the Microsoft.VisualBasic namespace, and I don’t think that it is there for other purposes than backwards compatibility with Visual Basic 6, with the possible exception of flirting with people who think this (C#)…

    Interaction.MsgBox(Strings.Mid("Hello", 2, 2),MsgBoxStyle.OkOnly,"Extract [el]");

    …for some reason makes more sense than this:

    MessageBox.Show("Hello".Substring(1, 2), "Extract [el]");

    The Microsoft.VisualBasic namespace is a part of the .NET Framework, but perhaps not your main focus if you don’t have some old converted VB6 code that you are managing. The My namespace however, is made me throw away parts of my own code libraries, because the My namespace gives you functions to call in your application that does common tasks, like uploading a file or playing a sound. The My namespace is only available in Visual Basic, as apposed to the Microsoft.VisualBasic namespace that can be used from any .NET language.

    Extending the My namespace

    Like any namespace in your application (and your application is where My belongs), just encapsulate your class in a namespace with the same name as you want to append your class to. This code adds Class1 to the My namespace (vb.net).

    Namespace My
       Public Class Class1
    
       End Class
    End Namespace

    But what if you want to extend the existing classes, like My.Computer, with new functions? If you add a new class called Computer in the My namespace, you are actually shadowing the existing Computer class, making it unavailable. But there is a compiler trick here. Add a class called MyComputer to the My namespace. The prefix My of the class name, tells the compiler that you are extending the My.Computer class. Also, set the access level of the MyComputer class to Friend, like so:

    Namespace My
       Friend Class MyComputer
          Public Sub Hello()
    
          End Sub
       End Class
    End Namespace

    Now, the Hello method is added to the My.Computer class.

    If you like, you can create hidden modules instead of classes when you are extending the My namespace.

  • The splat operator

    I must admit that I am not completely up to date with PowerShell 2.0 (PS2), even though the CTP (community technology preview) has been out for a while. The first thing that you will notice, is that you are no longer bound to the old console window. PS2 comes with a graphical editor that separates runspaces in tabs, and each tab has three sections; a script editor, an output window and a direct window that executes what you type, in the same way that the console window did. Since this is a WPF application (as apposed to a console application), you can use the regular cut and paste features in Windows.

    Some of the other new features includes the splat operator, remoting, Add-Type and ScriptCmdlets.

    The splat operator allows you to pass multiple pairs of keys and values to one single parameter.

    This is the basic idea of hash tables in PowerShell:

    Here, I want a function that can take one parameter. That parameter will be a hash table. The only line in the function write outs the value that is assigned to the key “test”:

    function splatMe($arg) { write-output $arg["test"] }

    When that function is added to the runspace, I create a hash table using the splat operator (@):

    $hello = @{"test"="1"; "tjo"="2"}

    I can now call the splatMe function, passing $hello (my hash table) as a parameter like so:

    splatMe $hello

    The result will be “1”. I also have the option of creating the hash table on the fly:

    splatMe @{"x"="hello"; "test"="Mr. Bean"; "z"="yepp!"}

    The output will be “Mr. Bean”.

    Remoting allows execution of cmdlets and scripts on remote machines.

    Add-Type lets you compile and use fragments of code from any .NET language.

    ScriptCmdlets lets you build new cmdlets using PowerShell script, as regular cmdlets had to be written in Visual Basic or C# and had to be compiled.