Images and Scaling with Windows Runtime #WinRT #WPDev #Windev

With the advent of Windows Phone 8.1, developers have the option of using WinRT native XAML stack as opposed to the Silverlight XAML the only option with early Windows Phone iterations.

One of the differences between WinRT XAML and Silverlight XAML is scaling and like with fonts, & images, scaling can have a significant effect on the look and feel of an app.

The default behavior with Windows Phone 8 was the inherent Silverlight behavior of scaling the image to fit. This meant that unless a high-resolution image was used, the image would end up looking blurred. Windows Runtime takes a different approach.

Windows 8x supports multitudes of screen sizes, resolutions and DPI. Windows Phone now supports 4 resolutions. The way Windows Runtime deals with this is by allowing developer to specify multiple images to match certain scale factors.

Windows Store Apps Windows Phone Store Apps
1.0 (100% no scaling) 1.0 (100% no scaling)
1.4 (140% scaling) 1.4 (140% scaling)
1.8 (180% scaling) 2.4 (240% scaling)

The runtime would determine the scaling factor to use depending upon the screen size, resolution, DPI and the form factor of device in question. The developer is required to supply images for scaling 1; the other scale factors are optional. If they are supplied, they will be used if necessary.

There are two ways of supplying images to support multi-scaling support.

  • Specify image scale within the file name e.g. Image.scale-100.png or Image.scale-140.png
  • Create direct for each image scale and place images inside without specifying scaling like in 1. E.g. scale-100/Image.png or scale-140/Image.png

The attached project includes examples of both ways.

To use this and enable auto-scaling support, you specify the image as specified below

<Image Source="Assets/Iris.png" />
<Image Source="Assets/Iris2.png" />

Occasionally it is necessary to set the images from code. In those instances, one should query the windows runtime to determine the current scaling factor and return appropriate image resource.

var uri = new System.Uri("ms-appx:///Assets/Iris.png");
var file = await StorageFile.GetFileFromApplicationUriAsync(uri);

This will correctly detect the scaling factor and get appropriate file.

Alternatively, for Windows 8x, we can use DisplayProperties.ResolutionScale to determine current scaling and for Windows Phone, we can use DisplayInformation.RawPixelsPerViewPixel.

Uri uri = null;
#if WINDOWS_PHONE_APP
    var rawpixelperview = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel; 

    var Width = Convert.ToInt32(Window.Current.Bounds.Width * rawpixelperview); 
    var Height = Convert.ToInt32(Window.Current.Bounds.Height * rawpixelperview); 

    if(Width == 480 && Height == 800)
    {
        uri2 = new System.Uri("ms-appx:///Assets/scale-100/Iris2.png");
    }
    else if((Width == 720 && Height == 1280 ) || (Width == 768 && Height == 1280))
    {
        uri2 = new System.Uri("ms-appx:///Assets/scale-140/Iris2.png");
    }
    else
    {
        uri2 = new System.Uri("ms-appx:///Assets/scale-240/Iris2.png");
    }
#else
    switch (DisplayProperties.ResolutionScale)
    {
        case ResolutionScale.Scale100Percent:
            uri2 = new System.Uri("ms-appx:///Assets/scale-100/Iris2.png");
            break;

        case ResolutionScale.Scale140Percent:
            uri2 = new System.Uri("ms-appx:///Assets/scale-140/Iris2.png");
            break;

        case ResolutionScale.Scale180Percent:
            uri2 = new System.Uri("ms-appx:///Assets/scale-180/Iris2.png");
            break;
    }
#endif

var file = await StorageFile.GetFileFromApplicationUriAsync(uri);

It worth noting that images set in xaml and those done codebehind behave differently at least as far as size on screen is concerned. The only way to achieve correct size as visible in xaml is to set size to that of scale 1.0 image.

Supporting Accessibility

Windows Store apps support high contrast mode. The two available options are

  • Black background and white foreground
  • White background and black foreground.

To additionally support these two accessible image formats, you need to provide scale factor 1 images named / placed appropriately. I have excluded the high contrast images from sample as windows phone was using that by default.

Assets/Iris.scale-100_contrast-black.png

Assets/Iris.scale-100_contrast-white.png

or

Assets/scale-100_contrast-black/Iris2.png

Assets/scale-100_contrast-white/Iris2.png

Downloadable sample code can be downloaded here

Advertisement

How to renew your Windows Store subscription using MSDN code

If you have an msdn account, you get codes for registering on both Windows Phone and Windows Store. These allow you to submit apps and generate revenue (potentially) for free since you are already playing for MSDN.

Last year while waiting for my app to be approved by App Excellence Lab, this feature was announced and having gone through 3 different AEL sessions, I found it easy to register account using MSDN provided code 🙂

Its almost a year since that day, I haven’t managed to generate enough revenue to pay for it but I am fortunate enough to have MSDN account and have a code at hand.

The notification email advises heading to https://commerce.microsoft.com and renewing there – alternatively you do nothing and they charge your card.

Visiting the above site, I only saw renewal options paying by card / Direct Debit or paypal.. no option to use MSDN code. I kept looking around and here’s how you do it. Copy code to clipboard and navigate to http://dev.windows.com/

Account

From dashboard, click Subscription and then click Renew button. You will get this page

code

Paste your MSDN supplied 7 character code and hit update total. After a few checks the total should be displayed as 0.00. Click Next and follow through.

Note: If your card has expired or is invalid, you will get Invalid session message and it will prompt you to start again. Click Signin and enter new card details (it needs a valid card even though you are paying 0.00) and complete the process.

Done.. you will get a confirmation email when you have completed the process. Lets hope this year brings more financial rewards to Win8dev

Geolocator and MovementThreshold #wpdev #win8dev

Last few months, I have had too much on my plate. Been doing lot to Windows 8 and Phone development. Surprisingly Microsoft UK is keeping tabs on phone developers who aren’t adapting to #WP8 and seemingly, I was invited to a dev event targeting the likes of me 😛

Sure I am going and in anticipation of the event, I decided to port Cineworld app to WP8. Its been a challenging task. Reworking a few bits of LongListSelector, Visual Studio / Blend disliking all the xaml and of course a button style causing xaml exception. If that wasn’t enough:

Having used Geolocator in Windows 8 app, I decided to use the same for WP8 as its usually a lot faster than GeoCoordinateWatcher. I moved the code to be more like Win8 and noticed that the location detection was flaky at best. Now I did the stupid thing and like in WP7 version, I decided to set both DesiredAccuracy to High and MovementThreshold to 0 thinking absolutely nothing.

Of course that didn’t help it, it made matters worse, instead of flaky behaviour, it decided to call it quits.

var pos = await locator.GetGeopositionAsync(TimeSpan.FromMinutes(5), TimeSpan.FromSeconds(2));

instead of timing out, it started to hang. In desperation, I started looking at other events exposed by this class and tried hooking into StatusChanged event. Now things were bad, I noticed that it was getting operation aborted exception and decided that something was seriously wrong and that I should take a nap instead 🙂

Of course the problem was still there when I woke up the next day 😛 its only later that I decided to search on Geolocation and operation aborted and realised that I wasn’t the only one and it was all my fault – causality of me setting the MovementThreshold to 0. I set it to 10 instead and bingo.. it all works.

While I didn’t find it, I hope this post helps people like an earlier post helped me.

Consume Callisto’s SettingsFlyout for #Win8Dev

With Windows 8, all Metro-style apps are supposed to publish a few things under Settings Charm. These include
1) About info
2) Privacy Policy (if you use data connection this is a must)
3) User configurable options
4) Help etc

This can be easily done using Tim Heuer’s Callisto lib for Windows 8. It ships with a handy control called SettingsFlyout. Let’s get started. I tend to register info into SettingsCharm at the start of the app and leave it at that. Lets open MainPage.xaml.cs and add to the constructor

public MainPage()
{
    // constructor
    this.InitializeComponent();

    SettingsPane.GetForCurrentView().CommandsRequested += MainPage_CommandsRequested;
}

private void MainPage_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
{
    SettingsCommand command = new SettingsCommand("GameRules", "Rules", (x) =>
    {
        SettingsFlyout settings = new SettingsFlyout();
        settings.Content = new GameRules();
        settings.HeaderBrush = new SolidColorBrush(Color.FromArgb(255, 0, 77, 96));
        settings.Background = new SolidColorBrush(Colors.White);
        settings.HeaderText = "Rules";
        settings.IsOpen = true;
    });

    args.Request.ApplicationCommands.Add(command);

    // and so on.. add the other commands you need to show
}

now when you app runs, you can see it in settings charm as shown

if you click the appropriate link (e.g. rules which we added), we will see

now I prefer to also show appbar icon and possible a keyboard shortcut. If we have already set both in place, lets see how we can show Rules directly from appbar, you just call ShowHelp

private void ShowHelp()
{
    SettingsFlyout settings = new SettingsFlyout();
    settings.Content = new GameRules();
    settings.HeaderBrush = new SolidColorBrush(Color.FromArgb(255, 0, 77, 96));
    settings.Background = new SolidColorBrush(Colors.White);
    settings.HeaderText = "Rules";
    settings.IsOpen = true;
}

and this is what it does.

App Excellence Lab Q & A #WinRT #Win8Dev

I have spent some time porting libs and code to get Wordastic working on Windows 8. Having missed App Excellence lab due to date confusion, I had to reschedule it and did a remote App Excellence Lab session. Here are the things I found out.

Iris Classon has also blogged her experience and is a worthy read

What does App Excellence Lab do ?
App Excellence Lab sessions are carried out by Microsoft Netherlands. The idea is to ensure that pre-release apps are worthy of being on pre-release marketplace. If the app passes all the requirements, the developer is given a token that allows access to Marketplace store.

I already have a token, why isn’t my app available ?
Having a token and passing requirements is not a guarantee of app publication. Apps are further filtered out to ensure those that stand out and provide an example to other app devs.

I encountered issues with my AEL, do I need to schedule another one ?
That depends upon the extent of changes / failures. I had a few changes to deal with and I was told that I need to email my sponsor and send them the correct package. This will then be tested against the points noted in the AEL and there is no need for Second AEL session.

Unique app naming
Each app in marketplace needs to have unique name. I have a game called wordastic on Windows Phone but I can’t have that in Windows 8 as someone published an app with same name.
I could abuse the system by say calling it “Play wordastic” or anything as long as it is unique by itself.
Access to store gives you ability to reserve a name and you have 1 year to publish app with that name.

Styles
Try to not use Title style else where – consume the other styles available for controls and try not to use fixed widths etc as the app needs to support multiple resolutions without looking crap

Do I need an app bar ?
No app bars are not mandatory and if you provide buttons for users within the app, ensure that user doesn’t have to move their hand a great distance. At the bottom of screen like app bar isn’t the best unless you have a very good reason. Keep it closer to where user already is. If its a game, keep them closer to game components.

Gridview items
Ensure that you don’t use / fix rows and columns for Gridview. This allows the items to be wrapped / rearranged when app is used at higher resolution or the orientation is changed

About Page and Privacy Policy
If you app access data connection, you need to ensure that you have an about page and a privacy policy. Use settings charm and make it available. This is mandatory.

Read content files #Metro apps #Wind8Dev #WinRT

I have started working on @Wordastic for #Windows8. Windows 8 is a weird beast.. you code in C# but you don’t code for CLR you code for #WinRT.

WinRT or the Windows Run Time as the name suggests is a OS layer that exposes functionality to all languages C / C++/ .NET and JS. This means that things change in many ways. For starters all methods are async. You need to use await to implicitly add callbacks etc. no need for Thread.Sleep etc.

Lets say that in our project we have “Content” directory that contains “MyTest1.txt” file which is included as Content. How do we read it.. well here it is

string myFile = Path.Combine(Package.Current.InstalledLocation.Path, "Content/MyTest1.txt");

StorageFolder myFolder = await StorageFolder.GetFolderFromPathAsync(Path.GetDirectoryName(myFile));
                
using (Stream s = await myFolder.OpenStreamForReadAsync(Path.GetFileName(myFile)))
{
    using (StreamReader sr = new StreamReader(s))
    {
        // do whateve you want
    }
}

Package.Current.InstalledLocation gives you the path to the app installations. then you navigate forward to the content path and you open the stream. At each step you use await to cause execution to return at desired point to continue execution e.g. after getting access to storage folder or opening the file for reading.

That’s it for today. more later.