Monthly Archives: November 2015

Using a timer to update the UI Thread

In trying to write a Windows 10 Desktop application that refreshes an image on the screen within a timer; I had the following code:

                _timer = new Timer((data) =>
                {
                    if (_imgIdx > Images.Count)
                        _imgIdx = 0;
                    AnimatedImage = Images.ElementAt(_imgIdx);
                    _imgIdx++;
                }, null, 0, 300);

However, when I run this, I get an exception:

The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))

My assumption was that the update was occurring on a different thread from the UI (a valid assumption I believe); so I, initially tried to call:

var dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;

However, this gave me a null exception.

DispatcherTimer

The answer is the DispatcherTimer class. Here’s how it’s used:

                _dispatcherTimer = new DispatcherTimer();
                _dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 500);
                _dispatcherTimer.Tick += Dt_Tick;
                _dispatcherTimer.Start();

Dt_Tick can now update the UI thread.


        private void Dt_Tick(object sender, object e)
        {

From the naming convention, you might infer that _dispatcherTimer is a class level variable; that’s because it is. The reason is that you can stop the timer elsewhere in the code:

                _dispatcherTimer.Stop();

Load and Display a list of Images in Windows 10

The following is a quick tutorial on how to load a series of images from the machine and display them on screen. This is something that I’m working on for my next Store Application.

The XAML

Let’s start with the screen layout – the GridView control makes this quite an easy task in Windows 10:

            <GridView ItemsSource="{Binding Images}">
                <GridView.ItemTemplate>
                    <DataTemplate>
                        <Image Source="{Binding}" Stretch="Uniform" 
                               Width="100" Height="100"/>
                    </DataTemplate>
                </GridView.ItemTemplate>
            </GridView>

Binding

In this case, I have bound the view to a ViewModel; the relevant part of which looks like this:


        private ObservableCollection<BitmapImage> _images;
        public ObservableCollection<BitmapImage> Images
        {
            get
            {
                if (_images == null)
                {
                    _images = new ObservableCollection<BitmapImage>();
                }
                return _images;
            }
            set
            {
                _images = value;
                NotifyPropertyChanged();
            }
        }

Basically, just an observable collection of BitmapImage.

Load the Image

Here’s where we populate the list:


        private async void Load()
        {
            FileOpenPicker openPicker = new FileOpenPicker();
            openPicker.ViewMode = PickerViewMode.Thumbnail;
            openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
            openPicker.FileTypeFilter.Add(".jpg");
            openPicker.FileTypeFilter.Add(".jpeg");
            openPicker.FileTypeFilter.Add(".png");
            openPicker.FileTypeFilter.Add(".gif");

            StorageFile file = await openPicker.PickSingleFileAsync();
            if (file != null)
            {
                var fileStream = await file.OpenAsync(FileAccessMode.Read);

                BitmapImage bi = new BitmapImage();

                bi.SetSource(fileStream);
                Images.Add(bi);

            }            
        }

Conclusion

I spent a short period of time wondering what had happened to the UniformGrid for Windows 10, but as you can see, the GridView just makes this job much easier.

OCR in Windows 10

Believe it or not, Windows 10 comes with OCR capabilities out of the box. It’s actually very easy to use as well; admittedly, it’s not the most sensitive in the world – but it does basically work. Here’s how you would scan in a bitmap image and recognise characters:

        public async string RecogniseOCR()
        {                        
            var ocrEngine = Windows.Media.Ocr.OcrEngine.TryCreateFromLanguage(new Windows.Globalization.Language("en"));
            
            var file = await Package.Current.InstalledLocation.GetFileAsync(@"Assets\test.bmp");            
            using (var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
            {
                // Create image decoder.
                var decoder = await BitmapDecoder.CreateAsync(stream);

                // Load bitmap.
                var bitmap = await decoder.GetSoftwareBitmapAsync();

                // Extract text from image.
                OcrResult result = await ocrEngine.RecognizeAsync(bitmap);

                // Return recognized text.
                return result.Text;
            }
        }

I scanned this image:

OCRScan

And it found this:

OCRScan2

Like I said – not the most sensitive recognition in the world, but still, it’s there in Windows 10! What’s remarkable is that I only found it by accident – another example of Microsoft marketing missing a huge opportunity.

Targeting Windows 10 Desktop Device Family

Having upgraded to Windows 10 recently, I came across an idea for a new app. Part of what this app is supposed to do it allow scanning of an image. Whilst I found a number of helpful articles of the code to scan an image, they seemed to make an assumption that the reader knew how to target the Desktop Device Family.

Reference the Extension for Desktop Applications

Windows 10 has a number of specific extensions for specific targeted devices. The first step is to reference in the correct one:

Extensions

Change the target in you Package.appxmanifest file

If you have a look in the UI menu for this, you won’t find any way to change the targeted device family (at least I didn’t). So, you need to change the XML:

  <Dependencies>
<!--    <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
--> 
	  <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0"/>
  </Dependencies>