Phillip Trelford's Array

POKE 36879,255

Silverlight 5 Native Windows P/Invoke

Silverlight 5 brings native window and P/Invoke support for Silverlight desktop apps (elevated trust out-of-browser applications). The Silverlight Window class contains a subset of the properties and methods provided by in the equivalent WPF Window class. That subset of functionality may be enough for many users, and anything else can be implemented with a sprinkling of P/Invoke. Remember that .Net is mostly managed spackle over the Win32 API. With Silverlight 5 you can create your own managed spackle using P/Invoke.

Setting a Silverlight window’s transparency

WPF provides an AllowsTransparency property that you can set. Win32 provides a SetLayeredWindowAttributes function you can call:

public static void SetTransparency(IntPtr hwnd, byte alpha)
{
  // Note: the window must be in the hidden state for this to take effect
  SetWindowLong(hwnd, GWL_EXSTYLE, (int)(WS_EX_LAYERED + WS_EX_TRANSPARENT));
  SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA);
}

The SetLayeredAttributes function works on Layered Windows, so first we must set the window’s style to WS_EX_LAYERED using the Win32 SetWindowLong function.

[DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowLong(IntPtr hwnd, int nIndex);

[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

Finally before we call our SetTransparency function we need to find the window’s handle:

public static IntPtr FindHwnd(Window window)
{
    var oldTitle = window.Title;
    var id = oldTitle + "(" + Guid.NewGuid().ToString() + ")";
    window.Title = id;
    var hwnd = FindWindowByCaption(IntPtr.Zero, id);
    window.Title = oldTitle;
    return hwnd;
}

The trick here is to temporarily give the window a unique title (using a GUID) and then find the window via it’s caption (title) using the Win32 FindWindow function.

[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpCaption);

Note: you can not click on the new transparent window which limits its usefulness to specific operations, for example a drag and drop cue window.

Removing a Silverlight window from the task bar

WPF provides a ShowInTaskBar property for this. Win32 provides an Extended Window Style WS_EX_NOACTIVATE which does the same:

public static void RemoveFromTaskBar(IntPtr hwnd)
{
    // Note: the window must be hidden for this to take effect
    SetWindowLong(hwnd, GWL_EXSTYLE, (int)WS_EX_NOACTIVATE);
}

Note: the window must have been shown then hidden before the method can work.

window.Show();
window.Hide();
Hwnd.RemoveFromTaskBar(hwnd);

Detecting when a windows is Activated/Deactivated

WPF provides Activated and Deactivated events. Win32 provides a WM_ACTIVATE message that you can listen in to:

[AllowReversePInvokeCalls]
private IntPtr WindowHook(int code, IntPtr wParam, IntPtr lParam)
{
    if (code == HC_ACTION)
    {
        var messageInfo = new CWPSTRUCT();
        Marshal.PtrToStructure(lParam, messageInfo);

        if (messageInfo.message == WM_ACTIVATE)
        {
            var hwnd = messageInfo.lparam;
            if ((int)messageInfo.wparam == WA_INACTIVE)
            {
                var e = WindowActivated;
                if (e != null)
                    e(this, new WindowActivatedEventArgs(hwnd));
            }
            else
            {
                var e = WindowDeactivated;
                if (e != null)
                    e(this, new WindowDeactivatedEventArgs(hwnd));
            }
        }

    }
    return CallNextHookEx(_hHook, code, wParam, lParam);
}

The method above is a hook for windows events. It triggers an event when a message signals that a window has become active or inactive. Calling SetWindowsHookEx starts it:

SetWindowsHookEx(WH_CALLWNDPROC, _callback, IntPtr.Zero, GetCurrentThreadId());

Summary

With a sprinkling of Managed spackle we’ve been able to extend the Silverlight 5 multi window feature. Silverlight 5’s P/Invoke feature provides a lot of customization potential.

The source code to this post is available on BitBucket:

Pacman Tiles

Back in January I built a sample Pacman maze script in F# to use at a Pacman Kata evening with the F#unctional Londoners group. Coincidentally there’s another Coding Kata this Thursday 26th July at Skills Matter. Anyway a couple of weeks ago I started playing with the sample again on the train to and from work, filling in some of the gameplay.

You can play the latest version with your cursor keys and 9 lives below:

(Right click to install game to desktop)

 
Windows 8

As the sample runs in Silverlight I thought I’d also try it out on it’s cousin WinRT. WinRT lets you build Metro apps on Windows 8. The transition code wise has been pretty straight forward and I now have a tile for the game appearing on my Windows 8 start page:

One click: From Metro tile to video game

 

WinRT is yet another XAML based framework, and is very similar to Silverlight and WPF. One of the few differences I have encountered has been the namespaces the classes are in. For example in Silverlight the Canvas class is in the System.Windows.Controls namespace and in WinRT it is in Windows.UI.Xaml.Controls namespace. It is possible to target both WinRT and Silverlight from the same source code using conditional directives:

#if NETFX_CORE
using Windows.UI.Xaml.Controls;
#else
using System.Windows.Controls;
#endif

 

Multi-targeting

Multi-targeting Silverlight and WinRT is the route I decided to go down which allowed me to develop the game on my laptop running Windows 7 with Visual Studio 2010. Then I periodically tested it out on a desktop box running the Windows 8 Preview Release using Visual Studio 2012. Visual Studio 2012 does run on Windows 7, however WinRT does not.

The WinRT version of the app is implemented in F# and C#. The game part is written in F# as a portable library and the plumbing in C#. There’s a great walkthrough on Creating a Portable F# Library over on MSDN which describes this direction in some detail.

Code Fragment

When the ghosts are eaten they need to return to the enclosure. I used a flood fill algorithm to mark the shortest route from anywhere in the maze back to the enclosure. The flood fill is started inside the enclosure, the fill number is incremented with each iteration of the fill, so that the shortest route is to follow the lowest number adjacent to the ghost’s current square:

module Algorithm =
    let flood canFill fill (x,y) =
        let rec f n = function
            | [] -> ()
            | ps ->
                let ps = ps |> List.filter canFill
                ps |> List.iter (fill n)
                ps |> List.collect (fun (x,y) -> 
                    [(x-1,y);(x+1,y);(x,y-1);(x,y+1)]
                )
                |> f (n+1)
        f 0 [(x,y)]
 
Full Source

The full source code to the game is publicly available on BitBucket:

A single file playable script version is also available on F# Snippets:

PacMan Kata

F#unctional LondonersThe F#unctional Londoners Meetup Group will be starting 2012 with a code Kata on Thursday January 26th at 6:30pm at Skills Matter.

 
Kata

The term Kata comes from martial arts. A code Kata is a short programming exercise for practicing an aspect of software development.

C64_explodingfistBack in November in the Programming with the Stars session at the Progressive F# Tutorials our celebrities Mark Needham and Mark Seemann took on the Tennis Kata, first in C# and then F#.

As the two Mark’s talked through their solutions a number of people worked on their own versions, 2 of which you can see on the F# Snippets site:


PacMan
Scanning over the Kata catalogue for ideas the PacMan Kata bit me immediately.

    Pacman finds himself in a grid filled with monsters. Will he be able to eat all the dots on the board before the monsters eat him?

    maze

    To get things started I’ve built up a maze and some graphics. You can see an example over on F# Snippets that runs in the browser on http://tryfsharp.org which uses Silverlight: PacMan Maze

    I’ve also created a repository on BitBucket with sample projects for Visual Studio 2010 targeting WPF, Silverlight and HTML/JavaScript.

    The Javascript version uses the Pit compiler, you can see it running here. (Keys Q/A/Z/X *only in IE)

     


    Look forward to seeing you at the event.