Kevin Marshall's Epic Work Blog for Awesome People

@ksmarshall - i <3 software
in

August 2009 - Posts

Chromeless WPF Windows with Aero Blur

Recently Pete Blois from the Expression team posted about using a pixel shader to create a 9 grid in Silverlight. I thought it would be cool to apply the same concept to WPF so you could create chromeless windows in WPF with any type of boarder effect done in an image rather than bitmap effects. Also I wanted to add the glass aero blur to a window. Usually every example uses the same same DwmExtendFrameIntoClientArea but there are few other methods you can pinvoke like DwmEnableBlurBehindWindow. Since that method requires a pointer and you can only get one to the window in WPF I had to use CreateEllipticRgn to draw the blur behind the window. I used the size of the border around my content and it’s corner radius as the inputs and the handle to that drawing as the input for DwmEnableBlurBehindWindow .  The 9grid is used to apply a drop shadow around the window.

Here is how it looks. It subtle, but you can see the drop shadow created by the 9 grid around the window.

image

The performance is good considering the gratuitous blue effect although it’s probably not recommended for most applications. Here is the sample code if you’d like you’d like to look at it or you want the WPF version of Pete’s SL Nine Grid.

Demo source files

(Note: this really isn’t a compete example, it was just a prototype. Obviously you’d need to wire up minimize, close etc. Also there may some other side effects since I haven’t used this in an app yet and there is a slight ghosting when you resize quickly that i need to fix.)

Location Aware Silverlight 3 Applications

Adding location awareness makes every application better. Like adding chili to any food item makes it awesomer. Google has a nice AJAX API for finding your current location (for details see http://code.google.com/apis/ajax/documentation/)

To see an example of getting the location here: http://employees.claritycon.com/kmarshall/blog/files/slgeocode/ 

Since it’s based of your IP address it doesn’t always work well depending on your ISP or if you are VPN’d into another network.  Also SL3 out of browser apps have no DOM to access so you can’t run JS code. In that case I have a separate function to ping http://api.hostip.info/get_html.php?position=true The Google results seem a bit better so the application checks if it’s OOB . If it isn’t then it uses the Google APIs and if it is OOB or the Google API call returns no result then it tries hostip.info.  In Silverlight you can easily interop with javascript through the html bridge.

As for the code, in the page that hosts your application add:

<script src="http://www.google.com/jsapi?key=YOUR_API_KEY" 
type="text/javascript"></script>
<script type="text/javascript">
    //<![CDATA[
    google.load("maps", "2");
    function GetCurrentLocation() {
        if (google.loader.ClientLocation) {
            return google.loader.ClientLocation;
        }
    }
    //]]>
</script>

 

In Silverlight you can invoke that function:

public Location GetCurrentLocationFromJS()
{
    //dom is available so call the google location api in js
    ScriptObject scriptObject = HtmlPage.Window.Invoke("GetCurrentLocation") as ScriptObject;
    if (scriptObject != null)
        return scriptObject.ConvertTo<Location>();
    else
        return null;
}

The convertTo method will de-serialize the javascript object if there is a class with a matching definition. Otherwise you could create JSON in the host page and pass that back.

public class Location
{
    public string latitude { get; set; }
    public string longitude { get; set; }
    public Address address { get; set; }
    public class Address
    {
        public string city { get; set; }
        public string country { get; set; }
        public string country_code { get; set; }
        public string region { get; set; }
    }
}

The code to get the location from the hostip.info is just a normal webclient request.  In the demo application, it also uses the Yahoo geocoding service so you can enter a location or place name like “Golden Gate Park” and it will calculate the distance. I tried using Yahoo Placemaker, but that does not allow cross domain calls. Although someone messaged me on Twitter that you can use Placemaker via YQL which does allow cross domain calls. This code was part a experiment to see if we could geotag tweets/bios in a SL twitter client and filter on results relevant to your current location. Even though twitter is going to add location info to the API, I still think it’s potentially interesting to  infer locations through Placemaker e.g Someone sends a message “Going to Union Square” and you can get the coordinate of Union Square and others filtering on 10 miles of San Francisco will see the message".

Demo source files