Blog

  • 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.

  • IE6 and HTML5

    Now, Internet Explorer version 6 and above, has HTML5 support, through Google Chrome Frame. If you for any reason don’t want to change the browser you are using, you can just install Google Chrome Frame. Web designers activate it using one single tag. An ACID3 page with this tag, will give Internet Explorer 6 100% on the test.

    <meta-http-equiv="X-UA-Compatible" content="chrome=1">

    So what is more likely? That IE users will upgrade using Windows Update to IE9, a browser that, when available, has HTML5 support, or that they will “fix” Internet Explorer with this kit from Google? I have no idea. I like the effort put in, but I am not sure that all IE-users will go for this.

    Update: OSNews calls this story "Google Fixes IE For Microsoft, Adds HTML5, Fast JS and More".

    Update 23/9: Microsoft points out that Chrome Frame makes IE less secure.

    The release of Google Chrome Frame, a new open source plugin that injects Chrome’s renderer and JavaScript engine into Microsoft’s browser, earlier this week had many web developers happily dancing long through the night. Finally, someone had found a way to get Internet Explorer users up to speed on the Web. Microsoft, on the other hand, is warning IE users that it does not recommend installing the plugin. What does the company have against the plugin? It makes Internet Explorer less secure.

    Update: A great joke on Twitter by Scott Hanselman: IE Frame brings the power of the IE rendering engine to Google Chrome. #ScottGuAnnouncement

  • PhotoName improvements, September 2009

    Two changes have been made.

    PhotoName does a more effective image caching to be able to display thumbnails faster, and a directory list is added.

    The directory list can be used to navigate to any child directory or to the parent directory, without having to open the folder browser. Also, the directory list tells you if any child directory has own child directories or images.

    Download PhotoName from this page, but remember to uninstall any previous version first.

  • Google easter eggs

    Try google "recursion". Google in pig latin. My code hero, Ken Perlin, has contributed with a easter game. And finally, use the features of Google to download music! Also, check out these strange search suggestions.

  • How to upload a file

    First I must mention that this is my first ever blog post using Windows Live Writer. The topic was inspired by a question that was raised on the MSDN forums. How do I upload a file, and how can I control the remote filename? This is how it could be done:

    'The full path to the source file.
    Dim Source As String = "C:\MyFiles\SourceFile.txt"
    
    'The full destination path (will be created).
    Dim Destination As String = "ftp://www.myserver.com/myfolder/destination.txt"
    
    'Use the static (shared) method Create to create a web request.
    'Pass the destination as an argument, and cast it to a FtpWebRequest.
    Dim R As System.Net.FtpWebRequest = CType(System.Net.WebRequest.Create(Destination), _
    System.Net.FtpWebRequest)
    
    'Tell the request how it will login (using a NetworkCredential object)
    R.Credentials = New System.Net.NetworkCredential("myUsername", "P@ssw0rd")
    
    '...and what kind of method it will represent. A file upload.
    R.Method = System.Net.WebRequestMethods.Ftp.UploadFile
    
    'Here I use the simplest method I can imagine to get the
    'bytes from the file to an byte array.
    Dim FileContens() As Byte = System.IO.File.ReadAllBytes(Source)
    
    'Finaly, I put the bytes on the request stream.
    Using S As System.IO.Stream = R.GetRequestStream()
       S.Write(FileContens, 0, FileContens.Length)
       S.Close()
    End Using

    You could increase the level of control by replacing the ReadAllBytes call with some own code to read the bytes. This might be interesting if you’re for example are handling larger files, and want to show progress. To give away all control, you can use the already build function My.Computer.Network.UploadFile.

  • Evolution debate, Fria Tidningen

    This Saturday, I had the honor to write a reply in an ongoing debate on evolution in a Swedish magazine, Fria Tidningen. Check it out here (in Swedish)!

  • Using the BuildString class

    This might be a bit geeky, but I just love it. Do you have some old CRT screen lying around at home? That is your new debug window! The CodeProject user Tomzhu has made a class for easy message sending and receiving between Windows programs, the BuildString class. So, I did the simplest ever fullscreen application (ScreenOut.exe) that uses the BuildString class as it is, to display incoming messages. (Yes, it is the simplest fullscreen application ever – consider it a proof of concept, nothing more.)

    ScreenOut.exe asks for a screen to use at startup. To the left, I have my CRT running ScreenOut, and to the right I have Visual Studio (and some RSS reader). All I have to do, is make sure ScreenOut is running, if it isn’t nothing will happen.

    In the program that I want to send data from, I add the BuildString class, and I do some changes to adapt it to my ScreenOut. First, I change the scope of the existing PostString function from Public to Private. Then I add a new static (Shared in Visual Basic) function, SendString, that will use the PostString function.

    Public Shared Sub SendString(ByVal Text As String)
      Dim hwnd As Integer = FindWindow(vbNullString, "ScreenOut")
      If Not hwnd = 0 Then
        Dim Bs As New BuildString()
        Bs.PostString(hwnd, 1024, 0, Text)
      End If
    End Sub

    This function asks for the ScreenOut application, and will find it by its name if it’s running. And if so, it will use the original PostString function to send data to ScreenOut. Note that I have to declare the FindWindow function.

    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
    (ByVal lpClassName As String, ByVal lpWindowName As String) _
    As Integer

    And now, as if by magic, I have my own CRT screen that I can dump any junk onto, from multiple instances of Visual Studio. Whenever I want to send a message, I just call the SendString function.

    #If DEBUG Then
       BuildString.SendString("Hello, external screen!")
    #End If

    Just for the fun of it, if you use the #err prefix, the text will come out in red color.

    #If DEBUG Then
       BuildString.SendString("#err Oh no!")
    #End If

    Have fun!

  • Mitt sista ord om IE

    Mitt sista ord om IE – lite gnäll innan jag går vidare. Jag använder Internet Explorer 8 i detta klipp. Förra inlägget finns här.

    En vacker dag kommer jag antingen titta tillbaka på detta med ett leende, eller få äta upp min dumdristighet. 😉

    Internet Explorer 8 och Acid2.

    Internet Explorer 8 och Acid3.

    Internet Explorer 8 och HTML 5.

  • F# functions

    Functions are declared using the let keyword, followed by a name, a parameter list and a definition.

    This creates a function that adds to values and returns the result (first line). The two middle lines calls the function.

    let myFunction x y = x + y
    
    let result1 = myFunction 10 20
    let result2 = myFunction 15 25
    
    printfn "%d %d" result1 result2

    The last line prints the result to the screen. It should be 30 40.

    To specify the type of a parameter, you encapsulate it in parentheses, together with the type name. In this example, only the first parameter has a given type:

    let myFunction (x:int) y = x + y

    To specify the return type, add a colon followed by a type name. The following function divides a value in three. The first line is the function declaration, the second line is a call (note that I cast a int constant to a float), and the third line prints the result to the screen.

    let divInThree (t:float) = t / (float)3 : float
    let result = divInThree ((float)18)
    printfn "%f" result

    The result should be 6.

  • Conditions and iterations in F#

    Conditions
    This code will first assign a value to a and b, and print the values out. Thereafter, it will assign a value to c, that depends on the value of a. The value will be 20. Finally, it will print out both a, b and c.
    A programmer at NASA.

    let a=1
    let b=2
    printfn "%d %d" a b

    let c=
    if a=0 then 10
    elif a=1 then 20
    else 30

    printfn "%d %d %d" a b c

    Iterations
    This code will print eleven numbers on screen, from 10 to 20:

    for x in 10..20 do printfn "%d" x

    Unlike Visual Basic and C#, indentations actually means something in F#. Look at this iteration. The output is one two one two one two:

    for x in 1..3 do
    printfn "one"
    printfn "two"

    But just by changing the indentation (removing the indentation before the second prinfn), the output is changed to one one one two. The second printfn is no longer a part of the iteration.

    for x in 1..3 do
    printfn "one"
    printfn "two"

    You can also do while-iterations, that is, iterations that executes while a condition is true.

  • Using the framework from F#

    Just by typing the open statement, you can use the .NET Framework, or any other referenced libraries. To access the Console type, just add the following line to your source code:

    open System

    This program uses the built-in library function printfn, and then the WriteLine function to write “Hello world” to the screen.

    printfn "Hello world"
    open System
    Console.WriteLine("Hello world")

    So, displaying a message box, is just a matter of adding a reference to System.Windows.Forms, and this is how it could be done:

    let x=System.Windows.Forms.MessageBox.Show("Hello world")

    Or like so:

    open System.Windows
    let y=Forms.MessageBox.Show("Hello world")

    Or even:

    open System.Windows.Forms
    let z=MessageBox.Show("Hello world")

  • Things to know about F# before getting started and mutable variables

    F# is a .NET enabled functional programming language that has features that you would expect such a language to have (lists, tuples, pattern matching and so on), as well as the features you would expect from a .NET language such as preemptive multitasking, dynamic linking and Unicode strings. The program starts from the top of your source file instead of in a main function (as C# or Visual Basic), and the language is case sensitive, like C#. The editor support in Visual Studio 2008 slightly more limited than for C# or Visual Basic; you can still work with breakpoints and the locals window but perhaps not with code suggestions or code tips.
    This example creates an integer, initialized with the value 10, and prints it out:

    let x = 10
    printfn "x=%d" x

    If I wanted to assign a new value to x like below (complete source is shown, not just changes), a compile error will occur, telling me that x is not mutable – it can not change it’s value.

    let x=10
    printfn "x=%d" x
    x <- 11
    printfn "x=%d" x

    The keyword mutable at declaration, gives x the capability to chainge.

    let mutable x=10
    printfn "x=%d" x
    x <- 11
    printfn "x=%d" x

  • An evening with my wife, for once

    After work with my colleges was canceled, but my wife’s meeting this afternoon was also canceled, so we used this opportunity to grab a few beers and some food at our local restaurant. It is new, so this was the first time. Only the food was a smaller fortune, so perhaps it will be a while before I visit them again, but I will have an after work with my friends at VoF tomorrow (Vetenskap och Folkbildning – a Swedish pro-science association). I am looking forward to that. My children are downtown, to the cinema.

    Office hours are now used for programming a new business system, I am very excited about that. We are using all the cool stuff in this application; a SQL Server database, a great web service and a thick client (Windows Forms). Evenings spent looking at F# examples. I am not sure that I will be using it, but I feel that I need to know it and to be able to work it.

  • F# and PhotoName

    I have just decided to look in to F#, the new functional .NET language by Microsoft. It installs with Visual Studio 2010, and it can be installed for Visual Studio 9. I use Visual Studio 9 for my everyday work, so I installed it from here (click on the word MSI in the first paragraph under “F# Compiler versions”). After installation, a couple of new project templates are available, including a good tutorial. Thanks for that, Microsoft!

    And now for something less positive. I got a comment today on PhotoName on a never-do-this-thing in my source code. I was storing values in the registry under HKEY_LOCAL_MACHINE, something that you might want to do in an installation process, but never in an installed program. Back in the Windows 2000 days (or even XP), I thought of the Local Machine hive key as an alternative to the Current User hive key, with bigger scope. This is not good practice, and by default in Vista, Windows prevents programs from doing this. This is good, of course, and bringing this old mistake up to the surface, so that it could be fixed. I am a Vista user myself, but I actually use PhotoName on an old XP machine, so I am very thankful that this issue was brought up, so that I could update my code. If you have an older project, that you develop on a XP machine, you should make sure that you’re not using Application.CommonAppDataRegistry.SetValue but Application.UserAppDataRegistry.SetValue instead.

    If you have an older version of PhotoName installed, uninstall it from the Control Panel before installing the new version.

  • Link detection in my Twitter script

    I’ll just get on with my ASP3 Twitter reader written in VBScript so that I can leave the past behind me again. The first part is here.

    VBScript version 5 has simple and good Regex support. Some features are missing, but it’s good. It is available through a class called RegExp, like so:

    Set R=New RegExp

    This is the basic concept (to run it, just add these lines and the line above to a vbs-file):

    'What do I want to search for? Use the Pattern property.
    R.Pattern="a"
    
    'Case insensitive.
    R.IgnoreCase=True
    
    'Do the replacement and show the result in a message box.
    MsgBox R.Replace("String to search", "(new value)")
    
    'Case insensitive.
    R.IgnoreCase=True
    
    'Do the replacement and show the result in a message box.
    MsgBox R.Replace("String to search", "(new value)")

    To do the detection, I’ll use this script, downloaded from here:

    (ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?

    And here is the working code:

    <%
    'Create and configure the DOM Document.
    Set D = Server.CreateObject("MSXML2.DOMDocument.3.0")
    D.async = False
    D.setProperty "ServerHTTPRequest", True
    D.validateOnParse = True
    D.preserveWhiteSpace = False
    
    'Download XML data (pointing to the user's RSS feed).
    Rss="http://twitter.com/statuses/user_timeline/33177615.rss"
    If Not D.Load(Rss) Then
    
     'Download failed.
     Response.write "<p>We can not connect to Twitter right now.</p>"
    
    Else
    
     'Downloading went well. Extract the tweets.
     Set TweetList = D.getElementsByTagName("item")
    
     'Keep track on tweet count - I want to display five of them.
     TweetCount = 0
    
     'Create the Regex object and set the pattern.
     Set R = New RegExp
     R.Pattern = "(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?"
    
     For Each TweetNode In TweetList
      TweetCount = TweetCount + 1
    
      'Extract the items from the tweet node.
      Dt = TweetNode.childNodes(2).text
      Text = TweetNode.childNodes(1).text
    
      'If I want it, the feed contains the URL to the tweet.
      Url = TweetNode.childNodes(4).text
    
      'This is one of the ugly bits - I don't parse the date, I just grab the part that I want.
      Dt = Server.HtmlEncode(Mid(Dt,1,22))
    
      'The tweet starts with my username followed by a colon. I don't want that either.
      Text = Server.HtmlEncode(Mid(Text,13,Len(Text)))
    
      'Link detection!
      Set Matches = R.Execute(Text)
      If Matches.Count > 0 Then
       For I = 0 To Matches.Count - 1
        Text = R.Replace(Text, "<a href=""" & Matches(I) & """>" & Matches(I) & "</a>")
       Next
      End If
    
      'Display it!
      Response.Write "<p><b>" & Dt & "</b><br />" & Text & "</p>"
    
      'And just quit when five tweets are displayed.
      If TweetCount>=5 Then
       Exit For
      End If
     Next
    
     'Release reference to tweet list.
     Set TweetList = Nothing
    
    End If
    
    'Release reference to DOM object.
    Set D = nothing
    %>
  • Intermission

    Before jumping on to the URL detection in Classic ASP (using VBScript), I would like to point out Mikael Söderström’s piece on named arguments and optional parameters in C# 4. Both features are old Visual Basic possessions.

    Again, thanks for a great MCT/MVP Summit, Johan Lindfors. Dag König is a skillful educationalist, and there are lots of things to say about the news in Visual Studio 2010 and the .NET Framework 4.0.

  • Old meets new: Twitter and ASP3

    I had a business case to display a Twitter feed on an ASP3 (VBScript based) page. The code contains a few sticky passages, but all in all it went very well many thanks to the enormous COM toolkit that Microsoft provides. This is how it can be done:

    <%
    'Create and configure the DOM Document.
    Set D = Server.CreateObject("MSXML2.DOMDocument.3.0")
    D.async = False
    D.setProperty "ServerHTTPRequest", True
    D.validateOnParse = True
    D.preserveWhiteSpace = False
    
    'Download XML data (pointing to the user's RSS feed).
    Rss="http://twitter.com/statuses/user_timeline/33177615.rss"
    If Not D.Load(Rss) Then
    
      'Download failed.
      Response.write "<p>We can not connect to Twitter right now.</p>"
    
    Else
    
      'Downloading went well. Extract the tweets.
      Set TweetList = D.getElementsByTagName("item")
    
      'Keep track on tweet count - I want to display five of them.
      TweetCount = 0
    
      For Each TweetNode In TweetList
        TweetCount = TweetCount + 1
    
        'Extract the items from the tweet node.
        Dt = TweetNode.childNodes(2).text
        Text = TweetNode.childNodes(1).text
    
        'If I want it, the feed contains the URL to the tweet.
        Url = TweetNode.childNodes(4).text
    
        'This is one of the ugly bits - I don't parse the date, I just grab the part that I want.
        Dt = Server.HtmlEncode(Mid(Dt,1,22))
    
        'The tweet starts with my username followed by a colon. I don't want that either.
        Text = Server.HtmlEncode(Mid(Text,13,Len(Text)))
    
        'Display it!
        Response.Write "<p><b>" & Dt & "</b><br />" & Text & "</p>"
    
        'And just quit when five tweets are displayed.
        If TweetCount>=5 Then
          Exit For
        End If
      Next
    
      'Release reference to tweet list.
      Set TweetList = Nothing
    
    End If
    
    'Release reference to DOM object.
    Set D = nothing
    %>

    This code does not take care of URL detection and such things. I will look into that too (here).

  • The maintainer might be a maniac serial killer

    Most of the times when I code, I actually think that it is good that the language is structured the way it is, because the purpose of the code is so obvious, so I don’t have to worry about the person who will maintain it. I don’t know about you, but sometimes I really get struck by the feeling that some particular piece of code, will be a problem for the one that is going to understand what is going on, to be able to maintain. Maybe the code is segmented in the wrong way or for the wrong reason, or maybe the code is an invention that might as well be credited to Dr. Horrible. I stumbled upon this tip-of-the-day, and realized that I’m not alone:

    Always code as the if the person who will maintain your code is a maniac serial killer that knows where you live.

  • Execute a cmdlet or PS1 script from Visual Basic

    The cmdlets in PowerShell can easily be executed from within Visual Basic. I have done this in a few Visual Basic 8 projects, and the code for doing this from Visual Basic 8 can be somewhat ugly, but in Visual Basic 9 (and .NET Framework 3.5) it is very straight forward. You will need a reference to System.Management.Automation. If you don’t have it, you will get it when you install the Windows SDK for Windows Server 2008 and .NET Framework 3.5 from here. System.Management.Automation.dll installs to C:\Program\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0.

    The Runspace object will host the Pipeline object, and the Pipeline object is used to execute cmdlets or PS1 scripts.

    Some preparations: I have activated script execution and I have created a script file (C:\script.ps1) that contains one simple line: Write-Output 10+2

    'Create the runspace.
    Using R As System.Management.Automation.Runspaces.Runspace = _
    System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace()
    
       'Create the pipeline
       Using P As System.Management.Automation.Runspaces.Pipeline = R.CreatePipeline()
    
          'Open the runspace.
          R.Open()
    
          'Create each command (in this case just one)...
          Dim Cmd As New System.Management.Automation.Runspaces.Command("C:\script.ps1", True)
    
          '...and add it to the pipeline.
          P.Commands.Add(Cmd)
    
          'Execute the commands and get the response.
          Dim Result As System.Collections.ObjectModel.Collection(Of _
          System.Management.Automation.PSObject) = P.Invoke()
    
          'Close the runspace.
          R.Close()
    
          'Display the result in the console window.
          For Each O As System.Management.Automation.PSObject In Result
             Console.WriteLine(O.ToString())
          Next
    
       End Using
    End Using

    Output: 12

  • Hyckleriet kring arternas uppkomst

    Ett debattinlägg på hyckleriet kring arternas uppkomst är publicerat på Newsmill.

  • Ett vykort

    Ett vykort

    Eftersom jag inte kommer hinna med att blogga något denna vecka, så bjuder jag på ett vykort istället. Min minsta var imponerad över att man såg sig själv på skärmen när man filmade med Windows Movie Maker, så han bjöd på en riktig teater. Gissa om jag ska visa honom detta om 15 år.

    Edit: I wonder when those Twitter guys will get their things together and do something that works…?

  • Another moderate introduction to deep support for xml

    This post is more of a reminder to my self to start to deep xml support more seriously. I have mentioned it before, but not really examined it yet. For some reason, being free from work, leaves me with less time to just code for fun, compared to when I am working. Perhaps it’s good that my vacation soon is over.

    To start off this “reminder”, I want to show how to create and manipulate an element. This creates and initializes an System.Xml.Linq.XElement:

    Dim X = <myNode>MyValue</myNode>

    To access the child value, I can use the Value property of X. I can read it or change it.

    MessageBox.Show(X.Value)

    Children are added to (called X in my example) using the Add method. This code:

    X.Add(<child name=”child1″>Hello, mate!</child>)
    X.Add(<child name=”child2″>Hello again, mate!</child>)

    Results to this xml:

    <myNode>MyValue
     <child name="child1">Hello, mate!</child>
     <child name="child2">Hello again, mate!</child>
    </myNode>

    (It is not good practice to mix child elements with text values, but this is just an example.)

    I use the ToString method to see the xml source of the XElement. To access my new children, I could get a reference using the Element method. This give me the first child (I pass the element name as an argument):

    Dim Child = X.Element(“child”)

    And to step to the next element, I could use the NextNode property:

    Child = Child.NextNode

    I hope to be able to give a practical example of this soon, but for now, I am still impressed with the deep support (meaning that the compiler detects syntax error in the xml code).

  • First CLI control demo

    To demonstrate the CLI control, I have made a simple guessing game. The source code is below. If you want to run it yourself, place the exe file and a copy of CLIControl.dll in the same folder.

    CLI Control
    CLI Control demo
    Public Class Form1
    
    	'How many times has the user guessed?
    	Private GuessCount As Integer = 0
    
    	'The correct answer (can be 1 to 1000).
    	Private CorrectAnswer As Integer
    
    	'A random number generator is needed.
    	Private Rnd As New Random()
    
    	'Game flag.
    	Private GameOn As Boolean = False
    
    	'At startup, set some properties of the CLI control.
    	Private Sub Form1_Load(ByVal sender As System.Object, _
                ByVal e As System.EventArgs) Handles MyBase.Load
    
    		'Create a background for the control. If you have a
                    'file, use LoadBackgroundFromFile.
    		Dim Background As New System.Drawing.Bitmap(20, 50)
    		Using G As System.Drawing.Graphics = Graphics.FromImage(Background)
    			Using Blue1 As New SolidBrush(Color.FromArgb(255, 20, 40, 60))
    				G.FillRectangle(Blue1, 0, 0, 20, 50)
    			End Using
    			Using Blue2 As New SolidBrush(Color.FromArgb(255, 40, 60, 80))
    				G.FillRectangle(Blue2, 0, 10, 20, 10)
    			End Using
    		End Using
    		'Assign the background (not needed if you use LoadBackgroundFromFile).
    		Cli1.BackgroundImage = Background
    
    		'Create and assing a brush for the text font.
    		Cli1.TextBrush = New System.Drawing.Drawing2D.LinearGradientBrush( _
    		 New Point(0, 0), _
    		 New Point(0, Cli1.Height), _
    		 Color.FromArgb(100, 255, 255, 255), _
    		 Color.FromArgb(255, 255, 255, 255))
    
    		'Add a shadow to the text.
    		Cli1.TextShadow = True
    
    		'The number that the user is trying to find (1 to 1000).
    		Me.CorrectAnswer = Me.Rnd.Next(1, 1001)
    
    		'Say something to the user, and add some lines for decoration.
    		Cli1.WriteLine("Welcome! Guess a number between 1 and 1000!")
    		Cli1.WriteLine()
    		Dim P As New System.Drawing.Pen(Color.Yellow, 2)
    		Cli1.GraphicalElements.AddLine("", P, 0, 304, Cli1.Width, 0)
    		Cli1.GraphicalElements.AddLine("", P, 0, 323, Cli1.Width, 0)
    
    		'Go!
    		Me.GameOn = True
    	End Sub
    
    	Private Sub Cli1_UserTyped(ByVal Sender As Object, _
            ByVal Command As String) Handles Cli1.UserTyped
    		'If the game is running, assume that the user is guessing
                    'on the correct number.
    		If GameOn Then
    			Try
    				Dim I As Integer = Integer.Parse(Command)
    				If I < 1 Or I > 1000 Then
    					Cli1.WriteLine("The number must be between 1 and 1000!")
    				Else
    
    					'Increase the number of guesses.
    					Me.GuessCount += 1
    
    					'Display the guess count as an image.
    					Me.AddGuessCountImage()
    
    					If I = CorrectAnswer Then
    
    						'Correct!
    						Cli1.WriteLine("Correct in " & Me.GuessCount.ToString() & _
                                                            " guesses!")
    						Cli1.WriteLine()
    						'Add a green line.
    						Cli1.GraphicalElements.AddLine("", Pens.Green, 0, _
                                                             323, Cli1.Width, 0)
    						Me.GameOn = False
    
    					ElseIf I < CorrectAnswer Then
    
    						Cli1.WriteLine("I am thinking of a larger number.")
    
    					ElseIf I > CorrectAnswer Then
    
    						Cli1.WriteLine("I am thinking of a smaller number.")
    
    					End If
    
    				End If
    			Catch ex As Exception
    				Cli1.WriteLine("You must type a number between 1 and 1000!")
    			End Try
    		Else
    			Console.WriteLine("Game over!")
    		End If
    	End Sub
    
    	Private Sub AddGuessCountImage()
    		Dim B As New System.Drawing.Bitmap(70, 70)
    		Using F As New System.Drawing.Font("Times New Roman", 30, FontStyle.Regular)
    			Dim GuessCountString As String = Me.GuessCount.ToString()
    			Using G As Graphics = Graphics.FromImage(B)
    				G.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
    				G.FillEllipse(Brushes.Black, 0, 0, 69, 69)
    				G.DrawEllipse(Pens.Red, 0, 0, 69, 69)
    				Dim StringSize As SizeF = G.MeasureString(GuessCountString, F)
    				Dim X As Single = 35 - (StringSize.Width / 2)
    				Dim Y As Single = 35 - (StringSize.Height / 2)
    				G.DrawString(GuessCountString, F, Brushes.White, X, Y)
    			End Using
    		End Using
    		Cli1.GraphicalElements.AddPicture("", B, 400 + Me.Rnd.Next(200), 250)
    	End Sub
    
    End Class
  • Vector graphics in CLI control

    This post is done from the middle of nowhere and I am using my 3G phone as a modem. I hope that I manage to upload everything.

    I have added support for vector graphics in my CLI control to make the control more versatile. A collection named GraphicalElement holds the graphics to be drawn. Graphical elements in the collection can be manipulated and changes are reflected when the control is redrawn (you can call the Invalidate method to flag the control as dirty). When scrolling occurs, all graphical elements also are moved up. Elements are deleted when they scroll out of view.

    This simple example shows how to add graphics (it draws 60 bars in a nice pattern):

    For I As Integer = 1 To 60
    Cli1.GraphicalElements.AddBox(“”, Brushes.Yellow, I * 10, 10, 8, _
    CType(50 + (Math.Sin(I / 3) * 50), Integer))
    Next

    Because elements are deleted automatically when they scroll out of view, items will get new index numbers. Therefore, you should either save a reference to the item (a reference can be created manually using the Box constructor, but a reference to a Box is also given as return value from the AddBox method) or give the element a name, and then acquire a reference when a reference is needed using the FindElementByName method of the GraphicalElement collection.

    When I have the opportunity, I will do some more examples and some illustrations.

  • Ut till torpet

    I morgon bitti flyttar jag och familjen ut på torpet för det som är kvar av sommaren. Med undantag av några utflykter, är det där vi kommer att spendera sommaren. Jag hoppas att komma loss till min kompis Björn B. för lite gaming (det brukar bli Heroes III eller IV och något Xbox. Detta innebär för min del att jag blir ganska frånvarande på nätet. Jag har konfigurerat datorn så att min telefon kan jobba som 3g-moden, men det är arbetsgivaren som betalar detta kalas per megabyte, så jag kommer troligen vara försiktig med att följa bloggarna under denna tid. 1-2 gånger per dag kommer jag att snegla på mailen.

  • More on late binding

    How about an example on how to use scripting capabilities in your application, if the script control is available, without setting any references?

    'Attempt to get the type for the script control.
    Dim ScType As System.Type = System.Type.GetTypeFromProgID( _
    "MSScriptControl.ScriptControl")
    
    'If the prog ID is missing, Null is returned (Nothing in Visual Basic).
    If ScType Is Nothing Then
    
        MessageBox.Show("The Script Control is not available.")
    
    Else
    
        Dim Sc As Object = System.Activator.CreateInstance(ScType)
    
        'All is well. Configure the script control: Set language.
        Dim LanguageParameterValue() As Object = {"VBScript"}
        ScType.InvokeMember("Language", Reflection.BindingFlags.SetProperty, Nothing, Sc, _
              LanguageParameterValue, Nothing)
    
        'Allow UI operation (such as MsgBox).
        Dim AllowUIParameterValue() As Object = {True}
        ScType.InvokeMember("AllowUI", Reflection.BindingFlags.SetProperty, Nothing, Sc, _
              AllowUIParameterValue, Nothing)
    
        'Finally, set timeout to [forever].
        Dim TimeoutParameterValue() As Object = {-1}
        ScType.InvokeMember("Timeout", Reflection.BindingFlags.SetProperty, Nothing, Sc, _
              TimeoutParameterValue, Nothing)
    
        'Create a script.
        Dim S As New System.Text.StringBuilder()
        S.AppendLine("For A=1 To 10")
        S.AppendLine("MsgBox A")
        S.AppendLine("Next")
    
        'Execute the script. Error in the script will raise an exception. Use Try/Catch here.
         Dim Code() As String = {S.ToString()}
         ScType.InvokeMember("AddCode", Reflection.BindingFlags.InvokeMethod, Nothing, Sc, _
              Code, Nothing)
    
    End If

    In this example, I showed how to use the script control, if it is available. When you are writing applications that use for example Word or Excel, you might want your application to features from Word, if Word is available, but still be able to run; this is the way. Have fun!

  • Internet Explorer 8

    Jag älskar verkligen Microsoft och (nästan) alla deras produkter. Det måste alltid sägas för att slippa en onödig politisk diskussion som annars följer lika säkert som solen går upp, när man sagt något negativt. Jag tolkar det som ett tecken på att företaget har många fans, vilket glädjer mig. Ok? Bra. Till saken. Internet Explorer har mer och mer utvecklats till ett hån mot sina användare. Ni som kör den, vet att den inte är speciellt svarsbenägen (små irriterande fördröjningar när man mittenklickar på länkar och att inbakade script tynger ner sidan) och att den inte kan visa nyare hemsidor. Är man van IE-användare är det inte konstigt att man blir riktigt glad över att IT-stressen släpper när man surfar med t.ex. Chrome 3 eller FireFox 3.5 – webbläsare som fungerar snabbt och visar sidorna snyggt. Tydligen är inte bra webbläsare något konstigt, de flesta som finns idag är bra, men man tänker inte på det eftersom man är van med IE8. Och som dessa tester visar, är inte IE8 “i kölvattnet” eller “lite sämre”. Det är skit, och det är märkligt att man inte lagt ner denna produkt. Att jämföra IE8 med FireFox 3.5 är betydligt löjligare än att kalla Edit för MS-DOS för en ordbehandlare och jämföra den med Microsoft Office 2007. Samtidigt illustrerar IE slutanvändarnas flexibilitet. Den finns där och den fungerar (med lite god vilja), och för de som inte tagit sig besväret att testa något annat, är IE dörren ut till World Wide Web. Min personliga uppfattning är att Microsoft antingen bör träda åt sidan eller göra sen entré med något nytt, något bra. Ni som kör IE förtjänar så mycket bättre. Avslutning här.

  • Hur ser min blogg ut egentligen?

    Så här renderas den i FireFox 3.5:

    (Shiretoko 3.5, Chrome 3.0 och Minefield 3.6 visar sidan på exakt samma sätt som FireFox 3.5.)

    Så här renderas den i Internet Explorer 8, aningen plattare och kantigare än FireFox:

    (Avant 11 och K-Melon 1.5 visar sidan på exakt samma sätt som Internet Explorer 8.)

    Notera att Seamonkey 2 visar skuggor, men inte runda hörn:

    (Opera 11 visar sidan på exakt samma sätt som Seamonkey 2.)

  • VbsEdit

    Detta är kanske lite löjligt att ta upp halvägs in på år 2009, men jag har märkt att det finns personer som producerar grafik med scripting, en del riktigt komplexa saker med typ MathLab eller liknande.

    Eftersom jag ändå tänker ta lite bloggpaus nu, för att njuta av solen tillsammans med familjen, så kan jag berätta att jag i min naivitet tror att man kan komma ganska långt med VbsEdit och ett välskrivet COM-bibliotek. VbsEdit är ganska trevlig att jobba med. Den läser lydigt in typbiblioteken när den stöter på en CreateObject, den har auto list members, och den uppdaterar när man komplerar om inne i Visual Studio.

    Det andra som jag redan plockar med, som ska bli mitt semesterprojekt, är en image hosting-tjänst på svenska, med ett API man kan ladda hem för att bygga egna applikationer på tjänsten. Det hela består av en hemsida och en web service mot en SQL-databas på serversidan, och en .NET-dll på klientsidan.

    Jag hoppas att min nästa post här blir en bild på mig själv där jag njuter i solen.

  • Randomness

    I might be wrong here, but the Random class in the .NET Framework looks fairly random to me. I tried this code to generate an image to see if any patterns would show up:

    Using B As New System.Drawing.Bitmap(400, 400)
    	Dim R As New Random()
    	For Y As Integer = 0 To (B.Height - 1)
    		For X As Integer = 0 To (B.Width - 1)
    			Dim C As Integer = R.Next(0, 256)
    			B.SetPixel(X, Y, Color.FromArgb(C, C, C))
    		Next
    	Next
    	B.Save("RandomClass.png")
    End Using

    The generated image looks fine to me.

    For referense, I tried to do the same thing with “true random generator” by the user Phill64 (from here) and the result look quite the same. This is the function:

    Private Function GetRandomInt() As Integer
    	Dim r As New Security.Cryptography.RNGCryptoServiceProvider()
    	Dim bt(15) As Byte
    	r.GetNonZeroBytes(bt)
    	Dim d As Double = bt(0)
    	For i As Integer = 1 To 15
    		d *= bt(i)
    	Next
    	d /= (10 ^ (Math.Floor(d).ToString.Length))
    	d -= Math.Floor(d)
    	Return CType(d * 255, Integer)
    End Function

    This is my adapted code to generate an image using this function instead of the .NET Random class:

    Using B As New System.Drawing.Bitmap(400, 400)
    	For Y As Integer = 0 To (B.Height - 1)
    		For X As Integer = 0 To (B.Width - 1)
    			Dim C As Integer = Me.GetRandomInt()
    			B.SetPixel(X, Y, Color.FromArgb(C, C, C))
    		Next
    	Next
    	B.Save("Custom.png")
    End Using

    No predictable patterns here either, but it the code was much slower.

    The GetRandomInt function is a true random number generator, so if randomness matters, something like that is what you should use, but the Random class is fine most of the times. True randomness is much more important for Java programmers since the java.util.Random class produces obvious patterns.

  • Images: EnsureMaximumSize

    I have added a new function for resizing with maintained proportions to my image class WsImage.Image. The name is EnsureMaximumSize, and it takes one integer (the maximum width or height) and returns a boolean. The return value is True if the image size changed, otherwise the return value is False.

    Imagine that you load an image that is 600 pixels high, and 400 pixels wide. If you call the EnsureMaximumSize function and pass 500 to the parameter, the image will be resized so the new height is 500, and the width is changed so that the width/height ratio is maintained. The return value will be True.

    If you would have passed the value 1000 in this situation, the image would not be resized, and the return value would be False.

    This code will produce a 800×600 pixel image, and draw both the 800×600 version and the 640×480 version of it. (I wrote this code in the Click event of a Form.)

    'In the Click event of a form, create an image.
    Dim X As New WsImage.Image(800, 600)
    
    'Create a Graphics object to enable drawing on the image.
    Using G As Graphics = X.CreateGraphics()
    
    	'Draw a white background and a black ellipse.
    	G.FillRectangle(Brushes.White, 0, 0, 800, 600)
    	G.FillEllipse(Brushes.Black, 0, 0, 800, 600)
    
    End Using
    
    'Create a Graphics object to be able to draw on the form.
    Using G As Graphics = Me.CreateGraphics()
    
    	'Draw the original bitmap to the form.
    	G.DrawImage(X.GetBitmap(), 0, 0)
    
    	'Tint the background.
    	Using Tint As New SolidBrush(Color.FromArgb(127, 0, 0, 0))
    		G.FillRectangle(Tint, 0, 0, 800, 600)
    	End Using
    
    	'Do a 640 x 480 version, and draw it.
    	X.EnsureMaximumSize(640)
    	G.DrawImage(X.GetBitmap(), 40, 40)
    End Using

    Check the WsImage tag for more information on this class. You can download it here (if you use it, give me credit).

  • Collection initializers

    There are only a few new changes and additions made to the language Visual Basic in version 10. Changes in version 7, 8 and 9 were huge, and from version 9, I really like what it has become, and all that is needed in version 10 is some polishing. I will spend a few posts on some of the features.

    In version 9, we got object initializers and in Visual Basic 10 the initializers will work for arrays and collections. Microsoft call them Collection Initializers. This is a good example of polishing, because the object initializers did not help that much, especially not if you have implemented the constructors that you desire.

    A Collection Initializer is a different story. Here, we actually accomplish something useful.

    Now, we can create a collection and initialize it with some elements that also are initialized, all in one single line!

    The syntax is:

    Dim Variable = New CollectionClass = {{element initialization}, {element initialization}, …}

    If you want to initialize a collection of objects, and each object is initialized with two integer values (this could be a polygon with points), the could would look like this (if I use the generic collection):

    Dim C = New List(Of MyPoint) From {{10, 20}, {15, 25}, {30, 40}}

    This would require 4 lines in Visual Basic 9. One to create the collection, and one for each element. If you like, you can break the line at a comma in Visual Basic 10. Good for formatting.

  • Console controls, the concept

    To illustrate what I was talking about here, I made a simple list box to show the concept. The picture illustrates what it looks like, and the code follows.

    The Module1 module is the console application with the Main method (startup).

    The ConsoleControl class is an abstract base for console controls. This class is for now incredible trivial, and I just built it to make this point.

    Then, the ListBox class is the “control” itself and the ListBox item is a pair of a Long (the value) and a String (the visible representation).

    I might be way out here, but I’d love to have something like this.

    Module Module1
    
        Sub Main()
    
    		'Create a listbox.
    		Dim Lb As New ListBox()
    
    		'Set some properties.
    		Lb.Height = 4
    
    		'Add some items
    		Lb.Add(4, "One")
    		Lb.Add(542, "Two")
    		Lb.Add(9, "Three")
    		Lb.Add(10, "Four")
    		Lb.Add(11, "Five")
    		Lb.Add(12, "Six")
    		Lb.Add(13, "Seven")
    
    		'Let the user make a selection.
    		Dim Answer As Integer = Lb.Ask()
    
    		'Just for testing: Pause to make sure that the console window is restored.
    		Console.ReadLine()
    
    		'Write out the answer and pause again.
    		Console.WriteLine(Answer.ToString())
    		Console.ReadLine()
    
        End Sub
    
    End Module
    
    Public MustInherit Class ConsoleControl
    
    	Private m_X As Integer
    	Private m_Y As Integer
    	Private mWidth As Integer
    	Private mHeight As Integer
    
    	Private mBackgroundColor As System.ConsoleColor
    	Private mForegroundColor As System.ConsoleColor
    	Private mHighlightedBackgroundColor As System.ConsoleColor
    	Private mHighlightedForegroundColor As System.ConsoleColor
    	Private mInactiveForegroundColor As System.ConsoleColor
    
    	Public Sub New()
    		Me.m_X = 1
    		Me.m_Y = 1
    		Me.mWidth = 20
    		Me.mHeight = 10
    		Me.mBackgroundColor = ConsoleColor.Blue
    		Me.mForegroundColor = ConsoleColor.White
    		Me.mHighlightedBackgroundColor = ConsoleColor.White
    		Me.mHighlightedForegroundColor = ConsoleColor.Blue
    		Me.mInactiveForegroundColor = ConsoleColor.Gray
    	End Sub
    
    	Public Property X() As Integer
    		Get
    			Return Me.m_X
    		End Get
    		Set(ByVal value As Integer)
    			Me.m_X = value
    		End Set
    	End Property
    
    	Public Property Y() As Integer
    		Get
    			Return Me.m_Y
    		End Get
    		Set(ByVal value As Integer)
    			Me.m_Y = value
    		End Set
    	End Property
    
    	Public Property Width() As Integer
    		Get
    			Return Me.mWidth
    		End Get
    		Set(ByVal value As Integer)
    			Me.mWidth = value
    		End Set
    	End Property
    
    	Public Property Height() As Integer
    		Get
    			Return Me.mHeight
    		End Get
    		Set(ByVal value As Integer)
    			Me.mHeight = value
    		End Set
    	End Property
    
    	Public Property BackgroundColor() As ConsoleColor
    		Get
    			Return Me.mBackgroundColor
    		End Get
    		Set(ByVal value As ConsoleColor)
    			Me.mBackgroundColor = value
    		End Set
    	End Property
    
    	Public Property ForegroundColor() As ConsoleColor
    		Get
    			Return Me.mForegroundColor
    		End Get
    		Set(ByVal value As ConsoleColor)
    			Me.mForegroundColor = value
    		End Set
    	End Property
    
    	Public Property HighlightedBackgroundColor() As ConsoleColor
    		Get
    			Return Me.mHighlightedBackgroundColor
    		End Get
    		Set(ByVal value As ConsoleColor)
    			Me.mHighlightedBackgroundColor = value
    		End Set
    	End Property
    
    	Public Property HighlightedForegroundColor() As ConsoleColor
    		Get
    			Return Me.mHighlightedForegroundColor
    		End Get
    		Set(ByVal value As ConsoleColor)
    			Me.mHighlightedForegroundColor = value
    		End Set
    	End Property
    
    	Public Property InactiveForegroundColor() As ConsoleColor
    		Get
    			Return Me.mInactiveForegroundColor
    		End Get
    		Set(ByVal value As ConsoleColor)
    			Me.mInactiveForegroundColor = value
    		End Set
    	End Property
    
    End Class
    
    
    Public Class ListBox
    	Inherits ConsoleControl
    
    	Private mItems As List(Of ListBoxItem)
    	Private mViewOffset As Integer
    	Private mSelectedIndex As Integer
    	Private mSpacer As String = Nothing
    
    	Public Sub New()
    		MyBase.New()
    		Me.mItems = New List(Of ListBoxItem)()
    		Me.mSelectedIndex = -1
    		Me.mViewOffset = 0
    	End Sub
    
    	Friend ReadOnly Property Items() As List(Of ListBoxItem)
    		Get
    			Return Me.mItems
    		End Get
    	End Property
    
    	Public Function Add(ByVal Value As Integer, ByVal DisplayText As String) As Integer
    		Dim Item As New ListBoxItem(Me, Value, DisplayText)
    		Item.Index = mItems.Count
    		mItems.Add(Item)
    		Return Item.Index
    	End Function
    
    	Public Property SelectedIndex() As Integer
    		Get
    			Return Me.mSelectedIndex
    		End Get
    		Friend Set(ByVal value As Integer)
    			Me.mSelectedIndex = value
    		End Set
    	End Property
    
    	Public Function Ask() As Integer
    		Return Me.Ask(0)
    	End Function
    
    	Public Function Ask(ByVal DefaultValue As Integer) As Integer
    		If Me.mItems.Count > 0 Then
    
    			Me.mSpacer = Space(Me.Width)
    
    			Dim CursorVisible As Boolean = Console.CursorVisible
    			Dim FG As ConsoleColor = Console.ForegroundColor
    			Dim BG As ConsoleColor = Console.BackgroundColor
    			Console.CursorVisible = False
    
    			Me.SelectedIndex = ValueToIndex(DefaultValue)
    			Do
    				Me.DrawRegular()
    				Dim Key As ConsoleKeyInfo = Console.ReadKey(True)
    				If Key.Key = ConsoleKey.Escape Then
    					Me.SelectedIndex = -1
    					Exit Do
    				ElseIf Key.Key = ConsoleKey.Enter Then
    					Exit Do
    				Else
    					Select Case Key.Key
    						Case ConsoleKey.UpArrow
    							If Me.SelectedIndex = 0 Then
    								Me.SelectedIndex = Me.mItems.Count - 1
    							Else
    								Me.SelectedIndex -= 1
    							End If
    						Case ConsoleKey.DownArrow
    							If Me.SelectedIndex < (Me.mItems.Count - 1) Then
    								Me.SelectedIndex += 1
    							Else
    								Me.SelectedIndex = 0
    							End If
    					End Select
    				End If
    			Loop
    			Me.DrawDead()
    
    			Console.CursorVisible = CursorVisible
    			Console.ForegroundColor = FG
    			Console.BackgroundColor = BG
    			Dim CursY As Integer = (Me.Y + Me.Height)
    			If CursY >= Console.WindowHeight Then
    				CursY = Console.WindowHeight - 1
    			End If
    			Console.CursorTop = CursY
    			Console.CursorLeft = 0
    			Return Me.mItems(Me.SelectedIndex).Value
    		Else
    			Return -1
    		End If
    	End Function
    
    	Private Function ValueToIndex(ByVal Value As Integer) As Integer
    		'This is only called from the Ask function, and the Ask funktion will only run if mItems.Count>0. No need for extra check.
    		For I As Integer = 0 To Me.mItems.Count - 1
    			If Me.mItems(I).Value = Value Then
    				Return I
    			End If
    		Next
    		Return 0
    	End Function
    
    	Private Sub DrawRegular()
    		'Make sure that the selection is inside the visible area.
    		If Me.mViewOffset > Me.SelectedIndex Then
    			While Me.mViewOffset > Me.SelectedIndex
    				Me.mViewOffset -= 1
    			End While
    		ElseIf (Me.mViewOffset + Me.Height) <= Me.SelectedIndex Then
    			While (Me.mViewOffset + Me.Height) <= Me.SelectedIndex
    				Me.mViewOffset += 1
    			End While
    		End If
    
    		'Draw the visible items.
    		For I As Integer = 0 To Me.Height - 1
    			Dim IndexToDisplay As Integer = I + Me.mViewOffset
    			Console.CursorLeft = Me.X
    			Console.CursorTop = Me.Y + I
    			If IndexToDisplay < Me.mItems.Count Then
    
    				If Me.mItems(IndexToDisplay).Selected Then
    					Console.ForegroundColor = Me.HighlightedForegroundColor
    					Console.BackgroundColor = Me.HighlightedBackgroundColor
    				Else
    					Console.ForegroundColor = Me.InactiveForegroundColor
    					Console.BackgroundColor = Me.BackgroundColor
    				End If
    
    				Console.Write(Me.mItems(IndexToDisplay).DisplayString)
    			Else
    				Console.ForegroundColor = Me.InactiveForegroundColor
    				Console.BackgroundColor = Me.BackgroundColor
    				Console.Write(Me.mSpacer)
    			End If
    		Next
    	End Sub
    
    	Private Sub DrawDead()
    		'Draw the visible items as inactive.
    		For I As Integer = 0 To Me.Height - 1
    			Dim IndexToDisplay As Integer = I + Me.mViewOffset
    			Console.CursorLeft = Me.X
    			Console.CursorTop = Me.Y + I
    			If IndexToDisplay < Me.mItems.Count Then
    
    				If Me.mItems(IndexToDisplay).Selected Then
    					Console.ForegroundColor = Me.ForegroundColor
    					Console.BackgroundColor = Me.BackgroundColor
    				Else
    					Console.ForegroundColor = Me.InactiveForegroundColor
    					Console.BackgroundColor = Me.BackgroundColor
    				End If
    
    				Console.Write(Me.mItems(IndexToDisplay).DisplayString)
    			Else
    				Console.ForegroundColor = Me.InactiveForegroundColor
    				Console.BackgroundColor = Me.BackgroundColor
    				Console.Write(Me.mSpacer)
    			End If
    		Next
    	End Sub
    
    End Class
    
    Friend Class ListBoxItem
    
    	Private mListBox As ListBox
    	Private mValue As Integer
    	Private mText As String
    
    	Private mIndex As Integer = 0
    	Private mDisplayString As String = Nothing
    
    	Friend Sub New(ByVal Owner As ListBox, ByVal Value As Integer, ByVal DisplayText As String)
    		Me.mListBox = Owner
    		Me.mValue = Value
    		Me.mText = DisplayText.Trim()
    	End Sub
    
    	Public Property Index() As Integer
    		Get
    			Return Me.mIndex
    		End Get
    		Friend Set(ByVal value As Integer)
    			Me.mIndex = value
    		End Set
    	End Property
    
    	Friend ReadOnly Property OwnerListBox() As ListBox
    		Get
    			Return Me.mListBox
    		End Get
    	End Property
    
    	Public ReadOnly Property Value() As Integer
    		Get
    			Return Me.mValue
    		End Get
    	End Property
    
    	Public ReadOnly Property Text() As String
    		Get
    			Return Me.mText
    		End Get
    	End Property
    
    	Public Property Selected() As Boolean
    		Get
    			Return (Me.OwnerListBox.SelectedIndex = Me.Index)
    		End Get
    		Set(ByVal value As Boolean)
    			If value Then
    				Me.OwnerListBox.SelectedIndex = Me.Index
    			Else
    				Me.OwnerListBox.SelectedIndex = -1
    			End If
    		End Set
    	End Property
    
    	Friend ReadOnly Property DisplayString() As String
    		Get
    			If Me.mDisplayString Is Nothing Then
    				'This code will only run once per item, but it still needs rewriting. Risk for multiple memory reallocations.
    				Me.mDisplayString = " " & Me.Text
    				If Me.mDisplayString.Length > Me.OwnerListBox.Width Then
    					Me.mDisplayString = Me.mDisplayString.Substring(0, Me.OwnerListBox.Width)
    				Else
    					While Me.mDisplayString.Length < Me.OwnerListBox.Width
    						Me.mDisplayString &= " "
    					End While
    				End If
    			End If
    			Return Me.mDisplayString
    		End Get
    	End Property
    
    End Class
    
  • Where are the console controls?

    For me, quick and dirty tools that just have to be built, but you can’t really allocate the time for it, are console applications. From time to time, they require some user input that I usually handle with the ReadLine function. When the user has to make a selection, I do the usual routine including google for some console controls or information on what controls are out there for console applications, and then ending up doing a fast hack that allows the user to pick something from a list.

    I can’t understand why someone haven’t published something like this. Perhaps I am using the completely wrong search terms. I have reluctantly started to program a list box, but if someone points one out for me, I will run away from this immediately. I can see that controls in a console application is in itself is conceptually wrong (it will probably ruin the possibilities to extend the application by redirecting the input and output stream), but I have had the need for this a few times.

    Anyone?

  • PhotoName improvements, June 2009

    A smaller update of the graphical user interface is done. I have also changed the screen shot on the program page, to reflect this change.

  • Can a cat give birth to a dog?

    Again a post in Swedish. A reply to the argument that evolution is wrong because cats don’t give birth to dogs, used by Kent Hovind among others.

    Artbildning: Kan en katt föda en hund?

  • Late binding when Option Strict is On

    Once you have an object, you can dynamically decide what method to call, or property to use, by calling the InvokeMember function of the object’s type. In this example, I call the ShowDialog method of the object. Note that object members (non static) must have target instance, in my case X.

    Dim X As New Form1()
    Dim T As Type = X.GetType()
    T.InvokeMember(“ShowDialog”, Reflection.BindingFlags.InvokeMethod, Nothing, X, Nothing)

    How you do things with COM objects that you don’t have a reference to, depends on if you are using Visual Basic in strict mode or not. If option strict is off, this code will actually run:

    Dim X As Object = Microsoft.VisualBasic.Interaction.CreateObject(“ADODB.Connection”)
    X.ConnectionString = “Hej”

    If option strict is on, you will get an error telling you that you can’t do late binding when option strict is on. You can, you just have to do it through the InvokeMember function of the type.

    Dim X As Object = Microsoft.VisualBasic.Interaction.CreateObject(“ADODB.Connection”)
    Dim Args() As String = {“Hej”}
    X.GetType().InvokeMember(“ConnectionString”, Reflection.BindingFlags.SetProperty, Nothing, X, Args)

    With this, you can build programs that use for example Microsoft Word if it is installed, but still can run if it isn’t.

  • WsImage.Image

    For quite some time, I have had the need for some extra high level functionality on top of the .NET Bitmap class. I want to be able to do some basic image manipulation and I want the typical functionality that you would expect from a content management system, like cropping and resizing. This is why I have started to build the WsImage.Image class. And I mean that I really just have started. Today. It is written in Visual Basic, but I have avoided the “VB only” features, like parameterized properties, so it works perfectly in a C#-project or Managed C++-project.

    It is a disposable object, use the Using keyword to create it (as you would with any disposable object). One constructor takes a desired with and height, and another takes the filename of an existing image.

    The WsImage.Image class wraps the .NET Bitmap class, and here is the current API (believe me, this is going to change in the future):

    CreateGraphics
    Returns a Graphics object.

    CropToRectangle
    Makes the image rectangular. For a image that is wider than it is high, the hight will not change, and the width will be cropped to match the height. The cropping is centered.

    GetBitmap
    This simply returns the Bitmap object that is contained in the WsImage.Image object. Do not dispose this object, just forget it when you’re done with it.

    GetProportions
    Returns a Size object that describes the proportions of the image. For example, an image sized 1000×1000 pixel will return a size object with the value 1×1, an image sized 17×11 pixels will return a size object with the value 17×11, an image sized 800×600 pixels will return a size object with the value 4×3 and so on.

    GetSize
    Returns the size of the image.

    GetThumbnail
    Returns a thumbnail as a .NET Bitmap. Currently, there is no overload for actually requesting the size of the thumbnail, it simply gives you a 100 pixels wide version of image. If the image is less than 100 pixels wide, black border is added – zooming will not occur. Dispose the returned Bitmap when you are finished with it.

    Yes, you can download the compiled class here, but if you’re not deadly interested in it, you could wait until it has a few more features in it. Like I said, I started today. If you do use it, remember to credit me in the about box.

  • Beer after work

    I wonder why I don’t do this more often. A beer after work gives you a chanse to test ideas and talk through more or less successful strategies. I love it.

  • Swedish creationist to the parlament

    Sorry for doing this in Swedish, but basically I’m just whineing about the Christian Democratic Party in Sweden, who wants to send a creationist to the EU parlament.

    Ella Bohlin – En svensk kreationist i Europaparlamentet

  • Filename is the sorce in the jukebox

    There is one oddity in the WinAmpJukebox that I am planning on leaving in. That is the code for determining the artist name and the song name. For this, I do not use the meta data in the MP3/WMA-file, I use the filename, consequently. I use a program called Mp3tag to manage my songs, and I am actually quite indulgent on managing the meta data, but very picky on managing the file name. So this oddity works for me, wild protests might make reconsider.

    I use CDEx to copy my CD:s to to the hard drive, and it lets me specify how I want the file to be named. I prefer this setup: %1\%2\%7. %1 – %4

    Meaning: A folder with the name of the artist (as registered in CDDB), a subfolder with the name of the album, and the song is named after the tracknumber, the artist name and the song name. For example:

    ..\My Music\MP3\Queen\A Night at the Opera\01. Queen – Death on two legs.wma

    This is how it is I currently extract the information from the full path to display it in the jukebox:

    1. Remove the file ending.
    2. Remove any starting number. I use a Regex to detect these two variants:

    “07-In the Neighborhood”
    “07. In the Neighborhood”

    3. If the filename contains a minus separated by two spaces, assume that the artist name and the song name is found, otherwise I assume that the containing folder has the same name as the performing artist.

    This rimes quite well with what you would expect from a jukebox. A disk with a bunch of artist directories, with a few songs in each of them, or possible some genre directories at the root level. But again, protests might make me change this, but for now, I like it a lot.

  • Two clips: Yor and Onion fire cause

    In this clip, The Onion sets thing straight on who started a devastating fire. And in this clip from The Spoony Experement, we get a nice review of Yor – The Hunter From The Future. Enjoy! (I did.)

  • Market it as more primitive than it really is?

    The Sweex digital photo frame MM008 v2 is a great little product, but one thing puzzles me. All the specifications and documentations that I have found on it, states that the display is 480×234 pixels. Anyone who has viewed a 480×234 picture can see that this is not the case. It took me a while to count the pixels on the display, but now I am under the impression that it actually has 480×270 pixels. That is 17.280 pixels more! Why would you ever want your potential customer to think that the product has less capacity than it actually has? And don’t get me started on the time I spent on counting pixels by producing strange pictures in different sizes with special patterns to detect if and how the photo frame interpolated the picture. Phew.

  • The one and only jukebox

    I am very exited about my new jukebox. For perfect playback, it is implemented as an addon to WinAmp. WinAmp is free, and I can take care about the playback later (if ever). It is intended for use on parties, and it prevents that one person picks all the music.

    Of all players that I could have chosen for making an addon to, why WinAmp? Because of the output plugin called SqrSoft Advanced Crossfading! A superb and very intelligent crossfader! If you haven’t got it, get it!

    So, why crossfading?

    If you allow a blank space between songs, people that attends to the party will do one (or both) of the following:

    • Fiddle with the stereo.
    • Go home.

    Crossfading prevents this. Check out for the download, it will be posted soon.

  • Leonard Cohen

    I samband med att Leonard Cohen släppt en ny liveskiva med tillhörande dvd har jag bestämt mig för att lyssna in mig lite på honom. En kollega ser till att jag får låna.

    Företaget har ny hemsida ute! Jag hoppas inte reklambyråns folk blir irriterade på att vi gick igenom hur den renderades, utan plikttroget åtgärdar så att det blir bra. Jag tycker vi har lyft oss, och den nya logotypen håller på att sjunka in. Den syns bättre på håll, och den är lite futuristisk.

  • Shadowing

    One feature that I use every day, really every day, in Visual Basic is shadowing. Like the keyword “new” in C#, it is used to override a method that is not overridable, but unlike the new keyword, shadowing replaces all overloads of a function in the base class. This is so very usefull. Imagine that you are designing a custom dialog, and you want certain arguments to be passed to the ShowDialog function. Create e shadow of  it, and code that calls ShowDialog must pass the arguments you have specified in the shadow. It could look like this:

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

    This is the one thing that I really miss in C#.

  • PhotoName improvements, May 2009

    Added: A checkbox is displayed that allows you to only load images that haven’t been renamed yet. This saves loading time for the application. PhotoName doesn’t really know what images that has been renamed, it uses a simple RegEx to determine the format of the filename, and if it doesn’t match, the image is loaded.

    The same RegEx is used to determine if the image should be default checked for renaming or not.

    If you have a previous version of PhotoName installed, it must be uninstalled first.

    Download PhotoName here.

  • The differences, part 2

    Visual Basic 9 and C# 3.5 has much in common, and I suspect that they will differ more in the future. I have pointed out some current differences, like completion lists, object initializers, deep XML support and declarative events.

    A few more VB-specific features:

    Properties with parameters is an odd feature. By creating an object with parameterized properties you can give the impression that the object has different object with indexers as members. Properties with parameters can not be accessed from C#. A property with two parameters can look like this:

    Public Property MyProperty(ByVal X As Integer, ByVal Y As Integer) As String
        Get
        End Get
        Set(ByVal value As String)
        End Set
    End Property

    The My namespace in Visual Basic is an extensible namespace with hierarchical arranged functions. It is loaded with function to manage sound, file transfers and other handy things, and you can extend it by simply creating hidden modules under the My namespace.

    Optional parameters in functions is a feature that has been around in Visual Basic for a long while, that will be available in C# version 4. This shows how to only pass the sixth parameter to a function:

    DoSome(, , , , , 55)

    Aditionally, you can clarify by naming the argument. This example also calls the sixth parameter (called B in this example):

    DoSome(B := 55)

    Named arguments will also be available in C# 4, with slightly different syntax (loose the colon).