Keep track of all the latest news and events on developer tools and technologies you care about
by David Britch
I recently joined a project developing a Windows 8 Metro application using C++. It had been a while since I’d written any C++ and I subsequently discovered that C++ has changed. A lot.
WinRT is the framework and library for building Metro applications. It can be used from C++, as well as JavaScript and .NET languages. It’s built on COM, and while working with COM has traditionally been difficult, WinRT has made the process very straight forward.
Developing a Windows 8 Metro application using C++ gives you the advantages of programming in both C++11 and C++/CX. C++11, formerly known as C++0x, is the name of the most recent iteration of the C++ programming language. It includes additions to the core language and also extends the C++ standard library. C++/CX (Component Extensions) is a set of extensions that makes it easy to consume WinRT functionality. It looks like C++/CLI but its native code, being COM under the covers rather than .NET. In addition, C++/CX hides all the COM, making programming WinRT straight forward.
The power of WinRT and the ease of use of C++ can be demonstrated through a sample application that enumerates the Windows 8 pictures library, and displays thumbnails for each picture. The file system and image files are an important part of this sample application, and traditionally one of the most common sources of performance issues. Accessing media files can be expensive, because it takes memory and CPU cycles to decode and display the images. WinRT provides functionality to efficiently access the file system and display the thumbnails.
The user interface for a Windows 8 Metro application developed using C++/CX can be written in XAML, providing all the usual features of XAML such as data binding, eventing, templating, styling etc. The XAML for the sample application is shown below.
<Page>
<Page.Resources>
...
<local:ThumbnailConverter x:Key="thumbnailConverter" />
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
<GridView x:Name="PhotosGrid" CanReorderItems="True" CanDragItems="True">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate>
<Border Background="#FF939598">
<Image Height="130" Width="190" Stretch="UniformToFill"
Source="{Binding Path=Thumbnail,
Converter={StaticResource thumbnailConverter}}" />
</Border>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
</Page>
Photos are displayed in a GridView, with a WrapGrid being used position photo thumbnails sequentially from left to right, top to bottom. Photo thumbnails are displayed in an Image control which binds to the Thumbnail property of the collection it displays. A converter is defined as a page-level resource, which is then used to convert the thumbnails into a format that the Image control can display.
When you want to access large collections of files, they should be accessed through the Windows::Storage::BulkAccess APIs. These APIs combined multiple file operations into a single operation, making it faster to access multiple files and file properties. These APIs can dramatically improve the performance of applications that display a collection of items from the file system, such as a collection of images.
The MainPage.cpp file is partially shown below. It imports the Windows::Storage, Windows::Storage::Search, Windows::Storage::BulkAccess, and Windows::Storage::FileProperties namespaces. The MainPage.h file, which defines the member variables and functions used in the sample application, is not shown.
void MainPage::OnNavigatedTo(NavigationEventArgs^ e)
{
auto fileTypeFilter = ref new Vector<Platform::String^>();
fileTypeFilter->Append(".jpg");
fileTypeFilter->Append(".png");
auto library = KnownFolders::PicturesLibrary;
auto queryOptions = ref new QueryOptions(CommonFileQuery::OrderByDate,
fileTypeFilter);
queryOptions->FolderDepth = FolderDepth::Deep;
queryOptions->IndexerOption = IndexerOption::UseIndexerWhenAvailable;
auto fileQuery = library->CreateFileQueryWithOptions(queryOptions);
auto fif = ref new FileInformationFactory(fileQuery,
ThumbnailMode::PicturesView, 190, ThumbnailOptions::UseCurrentScale, false);
auto dataSource = fif->GetVirtualizedFilesVector();
PhotosGrid->ItemsSource = dataSource;
}
C++/CX supports reference counted objects through the ref new keywords. When an object created by using ref new goes out of scope, the memory used by the object is reclaimed automatically.
The QueryOptions class specifies the parameters of the search query for enumerating the contents of the pictures library. A deep enumeration of the folder contents is specified, so that Windows traverses through subfolders to discover JPGs and PNGs, and then present the results in a single list that combines all the discovered images. When enumerating the folders, the indexer will be used if it’s available, otherwise the file system will be accessed directly.
An instance of the FileInformationFactory class is then created, which is used by the sample application to load information about files from the results of the query. After loading that information, the sample application can then access that information quickly using synchronous operations. A number of parameters are passed into the FileInformationFactory constructor to specify in what format the data should be returned. The GetVirtualizedFilesVector function is then called on the instance of the FileInformationFactory object, returning a virtualized vector of FileInformation objects that are suited for binding to a GridView. Finally, the ItemsSource property of the GridView is set to the virtualized vector returned by the call to GetVirtualizedFilesVector.
One of the properties of the FileInformation objects is the Thumbnail property that the Image control in the XAML binds to. However, Image control cannot bind to this property without converting the data first. This is because the Thumbnail property is of type StorageItemThumbnail, and must be converted to a BitmapImage to be displayed by the Image control. The code below shows how this conversion is performed by the ThumbnailConverter class.
public ref class ThumbnailConverter sealed :
public Windows::UI::Xaml::Data::IValueConverter
public:
virtual Platform::Object^ Convert(Platform::Object^ value,
Windows::UI::Xaml::Interop::TypeName targetType,
Platform::Object^ parameter,
Platform::String^ culture)
if (value != nullptr)
Windows::Storage::Streams::IRandomAccessStream^ thumbnailStream =
(Windows::Storage::Streams::IRandomAccessStream^) value;
Windows::UI::Xaml::Media::Imaging::BitmapImage^ bmp = ref new
Windows::UI::Xaml::Media::Imaging::BitmapImage();
bmp->SetSource(thumbnailStream);
return bmp;
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
virtual Platform::Object^ ConvertBack(Platform::Object^ value,
throw ref new Platform::NotImplementedException();
};
Summary
This article has demonstrated how to build a simple WinRT application, written in C++/CX, which enumerates the Windows 8 pictures library, and displays thumbnails for each picture. WinRT provides functionality to efficiently access the file system and display the thumbnails.
C++ is the language for power and performance, and the combination of C++11 and C++/CX makes C++/CX read a lot like C#, while giving you the benefits of native code. Memory leaks can be avoided by using reference counted objects, and the ability to develop the UI using XAML enables the designer-developer workflow present in the .NET world.
http://www.cm-group.co.uk/ David Britch is Senior Technologist at Content Master. David has a PhD in computation, specialising in image and signal processing. He has experience of designing and developing a wide range of application types including corporate systems, commercial products, and mobile solutions.
Great Article David, Reading this makes the world of C++ (something that is very alien to me) seem far more approachable.