Today, I’m pleased to announce that a new version of YouTube8, my first Windows 8 application, is available on the Windows Store.

This version is a major update that include a lot of new features and improvements:

  1. No more limitation on video playback: all videos can be played within the application
  2. Full Screen support
  3. PlayTo feature
  4. Multi-resolution (when they are more than 1 resolution available)
  5. Search improvements
  6. And more !

 

Feel free to try it and to share what you think about it ! http://bit.ly/MezRoj

 

Happy testing!

On my spare time, I’ve started a few weeks ago to work on a small Windows 8 application that allow users to look for YouTube videos and play them directly in the application.

I’m proud to announce that the application is now live on the Microsoft Store and any Windows 8 Release Preview users can download it and play with it !

For now, there are some issues with some videos that cannot be played directly in the app but I’ll try to improve this part (and add more features) in the next version !

Here are some screenshots:

Capture d’écran 1

Capture d’écran 2

Capture d’écran 3

Capture d’écran 4

I hope you’ll enjoy it !

Given a particular MailItem, the method below will help you to get the SMTP address of the person who send the email. The code is simple but take care of the fact that, in case of an Exchange user, we cant to get the SMTP address (and not the X.500 address):

public static string GetSenderEmailAddress(Outlook.MailItem mailItem)

{

    var propSMTP = “http://schemas.microsoft.com/mapi/proptag/0x39FE001F”;

    string emailAddress = string.Empty;

 

    if (mailItem.Sender.AddressEntryUserType == OlAddressEntryUserType.olExchangeUserAddressEntry)

    {

        var exchangeUser = mailItem.Sender.GetExchangeUser();

        if (exchangeUser != null)

        {

            emailAddress = exchangeUser.PrimarySmtpAddress;

 

            exchangeUser.ReleaseComObject();

        }

    }

    else

    {

        emailAddress = (string)mailItem.Sender.PropertyAccessor.GetProperty(propSMTP);

    }

 

    return emailAddress;

}

The method use the following extension method to release the COM object:

public static void ReleaseComObject(this object obj)

{

    if (obj != null && Marshal.IsComObject(obj))

        Marshal.ReleaseComObject(obj);

}

Note that the code can be easily modified to be used with the email’s recipients or, in fact, with any AddressEntry object !

Please, note that the code use the PropertyAccessor method so it’ll work only for Outlook version > 2007.

 

Happy coding!

[Windows 8] How to create an awaitable component ?

June 7th, 2012 | Posted by Tom in .NET | Windows 8 | WinJS | WinRT - (2 Comments) | Read: 4,529

C# 5, with it’s async/await pattern, is extremelly useful for asynchronous development. In Windows 8, the good point is that all the APIs which take more than 50ms must be run asynchronously !

But how do you create your own WinRT component ? This might be simple but there are some tricky points that I wanted to highlight in this blog post.

We know that each WinRT components need to be a sealed class so let’s take a look at the following code:

public sealed class Reader

{

    public async static Task<IEnumerable<string>> GetItemsAsync()

    {

        var feedsTitle = new List<string>();

        var client = new SyndicationClient();

        var feeds = await client.RetrieveFeedAsync(new Uri(“http://channel9.msdn.com/coding4fun/articles/RSS”));

        foreach (var item in feeds.Items)

        {

            feedsTitle.Add(item.Title.Text);

        }

        return feedsTitle.AsEnumerable();

    }

}

Even if this code seems correct, it’ll fail to compile due to the following error (click on image to enlarge):

image

The problem here is that each type exposed via your component need to be projected using WinRT. And the compiler is not able to project the Task type.

So we need to create a wrapper that will return (and take in parameters) only types that can be projected. And, for asynchronous operations, the dedicated type is IAsyncOperation<T>, which can be obtained, from a Task object, using the AsAsyncOperation extension’s method:

public sealed class Reader

{

    public static IAsyncOperation<IEnumerable<string>> GetItemsAsync()

    {

        return InternalGetItemsAsync().AsAsyncOperation();

    }

    internal async static Task<IEnumerable<string>> InternalGetItemsAsync()

    {

        var feedsTitle = new List<string>();

        var client = new SyndicationClient();

        var feeds = await client.RetrieveFeedAsync(new Uri(“http://channel9.msdn.com/coding4fun/articles/RSS”));

        foreach (var item in feeds.Items)

        {

            feedsTitle.Add(item.Title.Text);

        }

        return feedsTitle.AsEnumerable();

    }

}

(Note that the method “InternalGetItemsAsync” is set to “internal” to not be exposed).

Now, if you compile, no errors are produced. Plus, the compiler generate a code that can be called asynchronously:

public class Test

{

    public async void GetItemsAsync()

    {

        var items = await Reader.GetItemsAsync();

    }

}

(Here is the C# version, using the async/await keywords)

WinRTLib.Reader.getItemsAsync().then(function (feedsTitle) {

    var feeds = feedsTitle;

});

(Here is the WinJS version, using the Promise)

As you can see, this is pretty simple but extremely useful as soon as you are aware of this little trick: “A WinRT component can only exposed WinRT types so they could be projected !”

 

More info: http://msdn.microsoft.com/en-us/library/windows/apps/br230301(v=vs.110).aspx

 

Happy coding!

 

[Windows 8] How to load a file marked as Content ?

May 21st, 2012 | Posted by Tom in .NET | Windows 8 | WinJS | WinRT - (0 Comments) | Read: 2,712

Most of the sample/blog posts that you can found on Internet show you how to load a file that is contained in local storage. But what do you need to do if you want to access a file that is marked as “Content” in Visual Studio ?

The trick is to access to the files/folder are installed with your application. And to do this, you need to use Windows.ApplicationModel.Package.Current.InstalledLocation:

var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(@”Assets\Test\Test.txt”);

Note the syntax used to access the file (no need to use ms-appx or something else).

Pretty simple isn’t it ? :)

Be careful: I’ve found a bug in the way Windows 8 handle file path with “\” and “@” characters. Indeed, “@” is usually used to escape the “\” character thus, the previous syntax works fine. But don’t try to duplicate “\” character when using “@” or you’ll get an exception. So the following code will not work:

var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(@”Assets\\Test\\Test.txt”);

 

I hope this bug will be fix in the Release Preview !

 

Happy coding!

[Windows 8] How to read the content of a ZIP file ?

May 18th, 2012 | Posted by Tom in .NET | Article | Windows 8 | WinJS | WinRT - (1 Comments) | Read: 3,211

Here is a simple code sample that show you how you can read the content of a ZIP file:

var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;

var file = await localFolder.GetFileAsync(“Test.zip”);

var randomStream = await file.OpenReadAsync();

 

using (Stream stream = randomStream.AsStreamForRead())

{

    var zipArchive = new System.IO.Compression.ZipArchive(stream);

 

    // Entries contains all the files in the ZIP

    foreach (var entry in zipArchive.Entries)

    {

        using (var entryStream = entry.Open())

        {

            //

            // Read string file content

            //

            //using (var streamReader = new StreamReader(entryStream))

            //{

            //    var result = await streamReader.ReadToEndAsync();

            //}

 

            //

            // Read string file content (using WinRT APIs)

            //

            using (var inputStream = entryStream.AsInputStream())

            {

                 using (DataReader reader = new DataReader(inputStream))

                 {

                     var fileSize = await reader.LoadAsync((uint)entryStream.Length);

                     var stringContent = reader.ReadString(fileSize);

 

                     // You can also use the other methods available on DataReader to load an IBuffer, Byte Array, etc.

                 }

            }

        }

    }

}

 

Have fun and happy coding!

[Windows 8] How to get a search suggestions list ?

May 15th, 2012 | Posted by Tom in .NET | Article | Windows 8 | WinJS - (0 Comments) | Read: 1,878

In my Windows 8 application, I’m using the Search contract to allow users to perform searches on the backend web site. But I also wanted to propose some suggestions to the users.

Unfortunately, the APIs exposed by the backend does not offer a way to get some suggestions so I needed to find a way. I started to look on Internet using my favorite search engine and tought: “Hey, I’m trying to implement a feature that is already present in most of the current search engines !”

Screenshot

After some researches, I was unable to find how to get the results proposed by Google (mostly due to the new HTTPS protocol used since few months).

But I wanted to use this feature so I decided to check on YouTube to see if I could get the search suggestions:

Screenshot (2)

Taking a look at under the cover, I discover that, in fact, this suggestions list is just populated after a call to a service:

image

The results of this call is a JSON string containing the suggestions sent by YouTube/Google, according to the query string (“q=YYY”) sent by the user:

image

So, to use the feature, you can just create a simple helper function (results are voluntary restricted to 5 to be used in Windows 8 suggestions list):

function getSuggestions(word) { return new WinJS.Promise(function (complete, error, progress) { var suggestUrl = "http://client1.google.com/complete/search?client=youtube-psuggest&ds=yt&json=t&q=" + word + "&key=" + developerKey; WinJS.xhr({ url: suggestUrl }).then(function (args) { var suggestions = JSON.parse(args.responseText); var results = []; if (suggestions && suggestions.length >= 2) { for (var i = 0; i < 5; i++) { results.push(suggestions[1][i]); } } complete(results); }); }); }

Then, just call your function when user start to enter some text in the Search box:

appModel.Search.SearchPane.getForCurrentView().onsuggestionsrequested = function (eventObject) { var queryText = eventObject.queryText; var suggestions = eventObject.request.searchSuggestionCollection; var deferral = eventObject.request.getDeferral(); // Call services to get search suggestions and add them to the search pane GetSuggestions(queryText).then(function (suggestResults) { suggestResults.forEach(function (item) { if (item) { suggestions.appendQuerySuggestion(item); } }); deferral.complete(); }); };

Even if the results are “limited” to the one proposed by YouTube, the implementation is pretty simple but very useful (at least in my case !)

Screenshot (4)

 

Happy (Windows 8) coding!

In one of his blog post (here or here, for the French version), the Windows 8 Development Master David Catuhe explained how to generate and to rescale a new picture for a tile (secondary or not).

This is very useful if you’re not able to modify the service delivering the images to rescale them automatically. Its technique need you to use an Image HTML element and, unfortunately, you’re not allowed to use graphical components in a Windows 8 background task.

So here is the version I propose, which is quite different. First, I use a Promise when David’s version use an callback parameter. Then, I don’t use an Image element but I take advantage of the BitmapTransform class to perform a transformation (scale, rotation, etc.) on the image, accessed using the BitmapDecoder:

function rescaleImage2(src, destinationWidth, destinationHeight, localfilename) {

    return new WinJS.Promise(function (complete, error, progress) {

        var Imaging = Windows.Graphics.Imaging;

 

        WinJS.xhr({ url: src, responseType: “blob” }).then(function (request) {

            var imageStream = request.response;

 

            var fileName = new Date().getTime() + “_” + parseUri(src).file

 

            Windows.Storage.ApplicationData.current.localFolder.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.replaceExisting).then(function (rootFile) {

                rootFile.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {

                    Windows.Storage.Streams.RandomAccessStream.copyAsync(imageStream.msDetachStream(), stream).then(function () {

                        stream.flushAsync().then(function () {

                            stream.close();

                                     Windows.Storage.ApplicationData.current.localFolder.getFileAsync(fileName).then(function(file){

                            file.openReadAsync().then(function (stream) {

                                Imaging.BitmapDecoder.createAsync(stream).then(function (bd) {

                                    var transform = new Windows.Graphics.Imaging.BitmapTransform();

                                    transform.scaledHeight = destinationHeight;

                                    transform.scaledWidth = destinationWidth;

 

                                    bd.getPixelDataAsync(Imaging.BitmapPixelFormat.rgba8, Imaging.BitmapAlphaMode.straight, transform, Imaging.ExifOrientationMode.respectExifOrientation, Imaging.ColorManagementMode.doNotColorManage).then(function (pdp) {

                                        var pixelData = pdp.detachPixelData();

                                       Windows.Storage.ApplicationData.current.localFolder.createFileAsync(localfilename, Windows.Storage.CreationCollisionOption.replaceExisting).then(function (file) {

           file.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream){

                                                                 Imaging.BitmapEncoder.createAsync(Imaging.BitmapEncoder.pngEncoderId, stream).then(function (encoder) {

               encoder.setPixelData(Imaging.BitmapPixelFormat.rgba8, Imaging.BitmapAlphaMode.straight, destinationWidth, destinationHeight, 96, 96, pixelData);

 

               encoder.flushAsync().then(function () {

                   stream.flushAsync().then(function () {

                       stream.close();

                       rootFile.deleteAsync().done(function () {

                           if (complete)

                               complete(“ms-appdata:///local/” + localfilename.replace(“\\”, “/”));

                                                            });

                                                        });

                                                    });

                                                });

                                             });

                                         });

                                      });

                                  });

                              });

                          });

                      });

                  });

              });

          });

      });

    });

}

The code is also available, in a more readable format, here (thanks http://codepaste.net !)

As always, feel free to use it, comment, it, etc.

 

Happy coding!

[Windows 8] Some helpers to use in your developments

May 4th, 2012 | Posted by Tom in .NET | HTML5 | Windows 8 | WinJS - (1 Comments) | Read: 2,440

Some people ask me if there are some helpers available to perform various tasks such manipulating settings, local storage, etc.

There are no built-in helpers but for the current Windows 8 application I’m working, I’ve developed some of them and I wanted to share them with the community (note that this helpers are available in Javascript but it should not be hard to translate them in C#):

ResourcesHelper:

(function () {

    “use strict”;

 

    var appView = Windows.UI.ViewManagement.ApplicationView;

    var displayProps = Windows.Graphics.Display.DisplayProperties;

    var nav = WinJS.Navigation;

    var ui = WinJS.UI;

    var utils = WinJS.Utilities;

 

    WinJS.Namespace.define(“ResourcesHelper”, {

        ResourcesManager: WinJS.Class.define(

        // Define the constructor function for the ResourcesManager.

            function (resourceFile) {

                this.resourceLoader = null;

 

                if (resourceFile) {

                    this.resourceLoader = new Windows.ApplicationModel.Resources.ResourceLoader(resourceFile);

                }

                else {

                    this.resourceLoader = new Windows.ApplicationModel.Resources.ResourceLoader();

                }

            }, {

                // Instance methods

                ResourceLoader: {

                    get: function () { return this.resourceLoader; }

                },

 

                GetString: function (key) {

                    return this.ResourceLoader.getString(key);

                }

            }, {

                // Static methods               

            }

        )

    });

})();

 

SettingsHelper:

(function () {

    “use strict”;

 

    var applicationData = Windows.Storage.ApplicationData.current;

 

    function hasSetting(key) {

        return new WinJS.Promise(function (complete, error, progress) {

            var result = applicationData.roamingSettings.values.hasKey(key);

 

            complete(result);

        });

    }

 

    function getSetting(key) {

        return new WinJS.Promise(function (complete, error, progress) {

            hasSetting(key).then(function (found) {

                if (found) {

                    var result = applicationData.roamingSettings.values[key];

 

                    complete(result);

                }

                else {

                    complete(false);

                }

            });

        });

    }

 

    function addSetting(key, value) {

        return new WinJS.Promise(function (complete, error, progress) {

            var result = applicationData.roamingSettings.values.insert(key, value);

 

            complete(result);

        });

    }

 

    function removeSetting(key) {

        return new WinJS.Promise(function (complete, error, progress) {

            applicationData.roamingSettings.values.remove(key);

 

            complete();

        });

    }

 

    function updateSetting(key, value) {

        return new WinJS.Promise(function (complete, error, progress) {

            hasSetting(key).then(function (result) {

                if (result) {

                    removeSetting(key).then(function () {

                        addSetting(key, value).then(function (addResult) {

                            complete(addResult);

                        });

                    });

                }

                else {

                    addSetting(key, value).then(function (result) {

                        complete(result);

                    });

                }

            });

        });

    }

 

    function clearSettings() {

        return new WinJS.Promise(function (complete, error, progress) {

            applicationData.roamingSettings.values.clear();

 

            complete();

        });

    }

 

    WinJS.Namespace.define(“SettingsHelper”, {

        HasSetting: hasSetting,

        GetSetting: getSetting,

        AddSetting: addSetting,

        RemoveSetting: removeSetting,

        UpdateSetting: updateSetting,

        ClearSettings: clearSettings

    });

})();

 

StorageHelper:

(function () {

    “use strict”;

 

    var applicationData = Windows.Storage.ApplicationData.current;

    var localFolder = applicationData.localFolder;

 

    function hasSavedContent(file) {

        return new WinJS.Promise(function (complete, error, progress) {

            localFolder.getFileAsync(file).then(function (file) {

                complete(true);

            }, function () {

                complete(false);

            });

        });

    }

 

    function saveToCache(file, content) {

        return new WinJS.Promise(function (complete, error, progress) {

            localFolder.createFileAsync(file, Windows.Storage.CreationCollisionOption.replaceExisting)

                .then(function (file) {

                    file.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {

                        var writer = new Windows.Storage.Streams.DataWriter(stream.getOutputStreamAt(0));

                        writer.writeString(content);

                        writer.storeAsync().then(function () {

                            writer.flushAsync().then(function () {

                                complete();

                            });

                        });

                    });

                });

        });

    }

 

    function getFromCache(file) {

        return new WinJS.Promise(function (complete, error, progress) {

            hasSavedContent().then(function (exists) {

                if (exists) {

                    localFolder.getFileAsync(file).then(function (file) {

                        file.openReadAsync().then(function (stream) {

                            var reader = new Windows.Storage.Streams.DataReader(stream.getInputStreamAt(0));

                            reader.loadAsync(stream.size).then(function (fileLength) {

                                var jsonContentAsString = reader.readString(fileLength);

 

                                complete(jsonContentAsString);

                            });

                        });

                    });

                }

                else {

                    complete();

                }

            });

        });

    }

 

    function deleteCache(file) {

        return new WinJS.Promise(function (complete, error, progress) {

            hasSavedContent().then(function (exists) {

                if (exists) {

                    localFolder.getFileAsync(file).then(function (file) {

                        if (file) {

                            file.deleteAsync().then(function () {

                                complete();

                            });

                        }

                        else {

                            complete();

                        }

                    })

                }

                else {

                    complete();

                }

            });

        });

    }

 

    WinJS.Namespace.define(“StorageHelper”, {

        HasSavedContent: hasSavedContent,

        SaveToCache: saveToCache,

        GetFromCache: getFromCache,

        DeleteCache: deleteCache

    });

})();

 

TilesHelper:

(function () {

    “use strict”;

 

    function updateMainTile() {

        return new WinJS.Promise(function (complete, error, progress) {

            complete();

        });

    }

 

    function addSecondTile(tileId, name, image) {

        return new WinJS.Promise(function (complete, error, progress) {

            var tile = new Windows.UI.StartScreen.SecondaryTile(tileId);

            tile.shortName = name;

            tile.displayName = name;

            tile.arguments = tileId;

            tile.tileOptions = Windows.UI.StartScreen.TileOptions.showNameOnWideLogo;

 

            //var uri = parseUri(image);

            //var imageLocalUri = tileId + “_” + uri.file;

 

            var imageLocalUri = tileId + “.jpg”;

 

            rescaleImage2(image, 150, 150, imageLocalUri.replace(“.jpg”, “_uri.jpg”), false).then(function (uriLogo) {

                rescaleImage2(image, 310, 150, imageLocalUri.replace(“.jpg”, “_wide.jpg”), false).then(function (wideLogo) {

                    tile.logo = new Windows.Foundation.Uri(uriLogo);

                    tile.wideLogo = new Windows.Foundation.Uri(wideLogo);

 

                    tile.requestCreateAsync().then(function (isPinned) {

                        if (isPinned) {

                            _updateSecondaryTile(tileId, name, uriLogo, wideLogo);

                        }

 

                        complete(isPinned);

                    });

                });

            });

        });

    }

 

    function updateSecondaryTile(tileId, name, image) {

        return new WinJS.Promise(function (complete, error, progress) {

            isPinned(tileId).then(function (isPinned) {

                if (isPinned) {

                    var tileToUpdate = new Windows.UI.StartScreen.SecondaryTile(tileId);

                    tileToUpdate.shortName = name;

                    tileToUpdate.displayName = name;

                    tileToUpdate.arguments = tileId;

                    tileToUpdate.tileOptions = Windows.UI.StartScreen.TileOptions.showNameOnWideLogo;

 

                    //var uri = parseUri(image);

                    //var imageLocalUri = tileId + “_” + uri.file;

 

                    var imageLocalUri = tileId + “.jpg”;

 

                    rescaleImage2(image, 150, 150, imageLocalUri.replace(“.jpg”, “_uri.jpg”), false).then(function (uriLogo) {

                        rescaleImage2(image, 310, 150, imageLocalUri.replace(“.jpg”, “_wide.jpg”), false).then(function (wideLogo) {

                            tileToUpdate.logo = new Windows.Foundation.Uri(uriLogo);

                            tileToUpdate.wideLogo = new Windows.Foundation.Uri(wideLogo);

 

                            _updateSecondaryTile(tileId, name, uriLogo, wideLogo);

 

                            complete();

                        });

                    });

                }

                else {

                    complete();

                }

            });

        });

    }

 

    function _updateSecondaryTile(tileId, name, uriLogo, wideLogo) {

        // Square tile

        var tileXml = Windows.UI.Notifications.TileUpdateManager.getTemplateContent(Windows.UI.Notifications.TileTemplateType.tileSquarePeekImageAndText04);

        var imageXml = tileXml.getElementsByTagName(“image”);

        imageXml.item(0).attributes.getNamedItem(“src”).innerText = uriLogo;

 

        var textXml = tileXml.getElementsByTagName(“text”);

        textXml.item(0).innerText = name;

 

        // Wide tile

        var wideTileXml = Windows.UI.Notifications.TileUpdateManager.getTemplateContent(Windows.UI.Notifications.TileTemplateType.tileWidePeekImage03);

        imageXml = wideTileXml.getElementsByTagName(“image”);

        imageXml.item(0).attributes.getNamedItem(“src”).innerText = wideLogo;

 

        textXml = wideTileXml.getElementsByTagName(“text”);

        textXml.item(0).innerText = name;

 

        // Merge both xml to get one tile

        var mergedNode = tileXml.importNode(wideTileXml.getElementsByTagName(“binding”).item(0), true);

        tileXml.getElementsByTagName(“visual”).item(0).appendChild(mergedNode);

 

        var notificationUpdater = Windows.UI.Notifications.TileUpdateManager.createTileUpdaterForSecondaryTile(tileId);

        notificationUpdater.clear();

        notificationUpdater.enableNotificationQueue(true);

 

        var tileNotification = Windows.UI.Notifications.TileNotification(tileXml);

        tileNotification.tag = tileId;

 

        notificationUpdater.update(tileNotification);

    }

 

    function removeSecondTile(tileId) {

        return new WinJS.Promise(function (complete, error, progress) {

            isPinned(tileId).then(function (isPinned) {

                if (isPinned) {

                    var tileToDelete = new Windows.UI.StartScreen.SecondaryTile(tileId);

                    tileToDelete.requestDeleteAsync().then(function (isUnPinned) {

                        complete(isUnPinned);

                    });

                }

                else {

                    complete();

                }

            });

        });

    }

 

    function isPinned(tileId) {

        return new WinJS.Promise(function (complete, error, progress) {

            var isPinned = Windows.UI.StartScreen.SecondaryTile.exists(tileId);

 

            complete(isPinned);

        });

    }

 

    function rescaleImage2(src, destinationWidth, destinationHeight, localfilename) {

        return new WinJS.Promise(function (complete, error, progress) {

            var Imaging = Windows.Graphics.Imaging;

 

            WinJS.xhr({ url: src, responseType: “blob” }).then(function (request) {

                var imageStream = request.response;

 

                var fileName = new Date().getTime() + “_” + parseUri(src).file

 

                Windows.Storage.ApplicationData.current.localFolder.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.replaceExisting).then(function (rootFile) {

                         rootFile.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {

                             Windows.Storage.Streams.RandomAccessStream.copyAsync(imageStream.msDetachStream(), stream).then(function () {

                                 stream.flushAsync().then(function () {

                                     stream.close();

                                     Windows.Storage.ApplicationData.current.localFolder.getFileAsync(fileName).then(function(file){

                                         file.openReadAsync().then(function (stream) {

                                             Imaging.BitmapDecoder.createAsync(stream).then(function (bd) {

                                                 var transform = new Windows.Graphics.Imaging.BitmapTransform();

                                                 transform.scaledHeight = destinationHeight;

                                                 transform.scaledWidth = destinationWidth;

 

                                                 bd.getPixelDataAsync(Imaging.BitmapPixelFormat.rgba8, Imaging.BitmapAlphaMode.straight, transform, Imaging.ExifOrientationMode.respectExifOrientation, Imaging.ColorManagementMode.doNotColorManage).then(function (pdp) {

                                                     var pixelData = pdp.detachPixelData();

 

                                                     Windows.Storage.ApplicationData.current.localFolder.createFileAsync(localfilename,

                                                         Windows.Storage.CreationCollisionOption.replaceExisting).then(function (file) {

                                                             file.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {

                                                                 Imaging.BitmapEncoder.createAsync(Imaging.BitmapEncoder.pngEncoderId, stream).then(function (encoder) {

                                                                     encoder.setPixelData(Imaging.BitmapPixelFormat.rgba8, Imaging.BitmapAlphaMode.straight, destinationWidth, destinationHeight, 96, 96, pixelData);

 

                                                                     encoder.flushAsync().then(function () {

                                                                         stream.flushAsync().then(function () {

                                                                             stream.close();

 

                                                                             rootFile.deleteAsync().done(function () {

                                                                                 if (complete)

                                                                                     complete(“ms-appdata:///local/” + localfilename.replace(“\\”, “/”));

                                                                             });

                                                                         });

                                                                     });

                                                                 });

                                                             });

                                                         });

                                                 });

                                             });

                                         });

                                     });

                                 });

                             });

                         });

                     });

            });

        });

    }

 

    // parseUri 1.2.2

    // (c) Steven Levithan <stevenlevithan.com>

    // MIT License

    function parseUri (str) {

        var    o   = parseUri.options,

        m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str),

        uri = {},

        i   = 14;

 

        while (i–) uri[o.key[i]] = m[i] || “”;

 

        uri[o.q.name] = {};

        uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {

            if ($1) uri[o.q.name][$1] = $2;

        });

 

        return uri;

    }

    parseUri.options = {

        strictMode: false,

        key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],

        q:   {

            name:   “queryKey”,

            parser: /(?:^|&)([^&=]*)=?([^&]*)/g

        },

        parser: {

            strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,

            loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/

        }

    };

 

    WinJS.Namespace.define(“TilesManager”, {

        UpdateMainTile: updateMainTile,

        AddSecondTile: addSecondTile,

        UpdateSecondaryTile: updateSecondaryTile,

        RemoveSecondTile: removeSecondTile,

        IsPinned: isPinned,

        RescaleImage: rescaleImage2

    });

})();

(this last one is probably the one you’ll want to modify a bit, depending to the kind of tile you’ll want to use in your application)

Be aware that there might be some bugs or issues with the code so feel free to let me a comment if you have a fix !

 

Happing coding!

[Windows 8] How to print a document ?

April 16th, 2012 | Posted by Tom in .NET | Article | Windows 8 - (1 Comments) | Read: 2,223

Here is a simple code sample that can help you if you plan to add the Print feature in your application.

First, you need to setup your application and specify preview pages, options, etc.:

var pd = new PrintDocument();

pd.Paginate += (sender, args) =>

{

    // Set the number of pages to preview

    pd.SetPreviewPageCount(1, PreviewPageCountType.Final);

};

pd.AddPages += (sender, args) =>

{

    // Add a page/document to the print list

    pd.AddPage(this);

    pd.AddPagesComplete();

};

pd.GetPreviewPage += (sender, args) =>

{

    // Indicate the page number to display in the preview window

    pd.SetPreviewPage(args.PageNumber, this);

};

 

var printManager = PrintManager.GetForCurrentView();

printManager.PrintTaskRequested += (sender, args) =>

{

    // Create a print task and set its options

    var printTask = args.Request.CreatePrintTask(“My First WinRT Impression”, requestedArgs => requestedArgs.SetSource(pd.DocumentSource));

    printTask.Options.Orientation = PrintOrientation.Landscape;

};

Finally, you need to display the Print Page to the user:

private async void PrintButtonClick(object sender, RoutedEventArgs e)

{

    // Display the print ui

    await PrintManager.ShowPrintUIAsync();

}

And that’s all!

For your information, if you saved the document as a XPS file, this one is saved in “Documents” library !

 

Happy WinRT coding!