1 / 44

Tips for building a Windows Store app using XAML and C++: The Hilo project

Tips for building a Windows Store app using XAML and C++: The Hilo project. Scott Densmore – Development Lead 3-001. Agenda. Hilo C++ Background Tips for building C++ Windows Store apps. The Hilo Project.

yosefu
Télécharger la présentation

Tips for building a Windows Store app using XAML and C++: The Hilo project

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Tips for building a Windows Store app using XAML and C++: The Hilo project Scott Densmore – Development Lead 3-001

  2. Agenda • Hilo C++ Background • Tips for building C++ Windows Store apps

  3. The Hilo Project • End-to-end photo sample that provides guidance to C++ developers on how to use modern C++, asynchronous programming, XAML, and the Windows Runtime to build a world-ready app for the global market.

  4. C++ and XAML Architecture

  5. Demo • Walkthrough

  6. 1. Use smart pointers, stack semantics and RAII pattern • // old way • void func() { • widget* p = new widget(); • p->draw(); • delete p; • }

  7. Smart Pointers • void func() { • auto p = make_shared<widget>(); // no leak, and exception safe • p->draw(); • } • // no delete required, out-of-scope triggers smart pointer destructor

  8. Stack semantics and the RAII pattern • void f() { • unique_ptr<widget> p( new widget(…) ); • my_classx( new widget() ); … • } • // automatic destruction and deallocation for both widget objects • // automatic exception safety

  9. 2. Use public ref classes only for interop • public ref class Photo sealed : public IResizable, public IPhoto, public Windows::UI::Xaml::Data::INotifyPropertyChanged • { • internal: • Photo(Windows::Storage::BulkAccess::FileInformation^ file, IPhotoGroup^ photoGroup, std::shared_ptr<ExceptionPolicy> exceptionPolicy); • public: • virtual ~Photo(); • virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged; • ... • internal: • concurrency::task<void> QueryPhotoImageAsync(); • ... • private: • Windows::Storage::BulkAccess::FileInformation^ m_fileInfo; • ... • };

  10. Async

  11. 3. Don't create circular references between ref classes and lambda expressions. • … • { • auto wr = Platform::WeakReference(this); • function<void()> callback = [wr] { • auto vm = wr.Resolve<HubPhotoGroup>(); • if (nullptr != vm) • { • vm->OnDataChanged(); • } • }; • m_repository->AddObserver(callback, PageType::Hub); • }

  12. 4. Use explicit capture for lambda expressions • intmain() • { • using namespace std; • inti = 3; • int j = 5; • ... // more variables • // bad – specifies that the body of the lambda expression accesses all captured variables by reference unless you explicitly specify otherwise • function<int(void)> f = [&] { return i + j; }; • // bad – that the body of the lambda expression accesses all captured variables by value • function<int (void)> f = [=] { return i + j; }; • // The following lambda expression captures i by value and j by reference. • function<int (void)> f = [i, &j] { return i + j; }; • }

  13. 5. Use task cancellation consistently. • void CartoonizeImageViewModel::CartoonizeImage(Object^ parameter) { • m_cts = cancellation_token_source(); • auto token = m_cts.get_token(); • m_initializationTask = m_initializationTask.then([this, token]() -> task<void> • { • if (m_useHardwareAcceleration){ • return CartoonizeImageAmpAsync(token); • } • ... • } • void CartoonizeImageViewModel::CancelCartoonize(Object^ parameter) • { • m_cts.cancel(); • ViewModelBase::GoBack(); • }

  14. 6. Be aware of context rules for continuations of tasks • task<void> ImageViewModel::QueryPhotosAsync() { • assert(IsMainThread()); • ... • auto t = m_repository->GetPhotosForDateRangeQueryAsync(m_query); • return t.then([this](IVectorView<IPhoto^>^ photos) { • assert(IsBackgroundThread()); • auto temp = ref new Vector<IPhoto^>(); • ... • }, task_continuation_context::use_arbitrary()).then([this](Vector<IPhoto^>^ temp) { • assert(IsMainThread()); • auto size = temp->Size; • ... • }).then([this](task<void> priorTask) { • assert(IsMainThread()); • try { • priorTask.get(); • ... • });

  15. Pages and Navigation

  16. 7. Use the LayoutAwarePage class to provide navigation, state management, and view management • Navigation support • virtual void GoHome(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); • virtual void GoBack(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); • virtual void GoForward(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); • Visual state switching • void StartLayoutUpdates(Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); • void StopLayoutUpdates(Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); • Process lifetime management • virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override; • virtual void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override; • virtual void LoadState(Platform::Object^ navigationParameter, • Windows::Foundation::Collections::IMap<Platform::String^, Platform::Object^>^ pageState); • virtual void SaveState(Windows::Foundation::Collections::IMap<Platform::String^, • Platform::Object^>^ pageState);

  17. Navigating with XAML • <local:HiloPage … /> • <Button x:Name="FilmStripBackButton" AutomationProperties.AutomationId="FilmStripBackButton" Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" Margin="26,53,36,36" Style="{StaticResourceBackButtonStyle}“VerticalAlignment="Top"/>

  18. Navigating with Code • void RotateImageViewModel::Initialize(String^ photoPath) { assert(IsMainThread()); m_photo= nullptr; m_photoPath= photoPath; GetImagePhotoAsync().then([this](IPhoto^ photo) { assert(IsMainThread()); // Return to the hub page if the photo is no longer present if (photo == nullptr) { GoHome(); } }); • }

  19. 8. Support visual state for landscape, portrait, fill, and snap • <VisualStateManager.VisualStateGroups> • <VisualStateGroup x:Name="ApplicationViewStates"> • <VisualState x:Name="FullScreenLandscape"/> • <VisualState x:Name="Filled"/> • <VisualState x:Name="FullScreenPortrait"> • <Storyboard> ... </Storyboard> • </VisualState> • <VisualState x:Name="Snapped"> • <Storyboard> ... </Storyboard> • </VisualState> • </VisualStateGroup> • </VisualStateManager.VisualStateGroups>

  20. 9. Use asynchronous programming techniques to keep the UI responsive. • task<void> ImageViewModel::QueryPhotosAsync() { • assert(IsMainThread()); • ... • auto t = m_repository->GetPhotosForDateRangeQueryAsync(m_query); • return t.then([this](IVectorView<IPhoto^>^ photos) { • assert(IsBackgroundThread()); • auto temp = ref new Vector<IPhoto^>(); • ... • }, task_continuation_context::use_arbitrary()).then([this](Vector<IPhoto^>^ temp) { • assert(IsMainThread()); • auto size = temp->Size; • ... • }).then([this](task<void> priorTask) { • assert(IsMainThread()); • try { • priorTask.get(); • ... • });

  21. MVVM

  22. 10. Use BindableBase class to provide support for MVVM • public ref class BindableBase : Windows::UI::Xaml::DependencyObject, • Windows::UI::Xaml::Data::INotifyPropertyChanged, • Windows::UI::Xaml::Data::ICustomPropertyProvider • { • public: • virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged; • ... • protected: • virtual void OnPropertyChanged(Platform::String^ propertyName); • ... • }

  23. 11. Use MVVM to build an interop layer between XAML and your models

  24. World Ready

  25. 12. Separate resources for each locale

  26. 13. Use the Calendar class to support world calendars • Calendar^ CalendarExtensions::GetCalendar() { • return ref new Calendar(); • } • intCalendarExtensions::GetNumberOfMonthsInYear(DateTimeyearDate) • { • auto cal = GetCalendar(); • cal->SetDateTime(yearDate); • return cal->NumberOfMonthsInThisYear; • }

  27. Suspend, Resume, and Terminate

  28. 14. Save application data when the app is being suspended.

  29. 15. When the app resumes after termination, use the saved app data to restore the app state.

  30. 16. Release exclusive resources when the app is being suspended.

  31. Touch Language

  32. 17. Ensure your controls for tap and hold appears above the touch point • void Hilo::ImageView::OnImagePointerPressed(Object^ sender, PointerRoutedEventArgs^ e) • { • m_pointerPressed = true; • PointerPoint^ point = e->GetCurrentPoint(PhotoGrid); • m_pointer = point->Position; • if (point->Properties->IsLeftButtonPressed) • { • ImageViewFileInformationPopup->HorizontalOffset = point->Position.X - 200; • ImageViewFileInformationPopup->VerticalOffset = point->Position.Y - 200; • ImageViewFileInformationPopup->IsOpen = true; • } • }

  33. 18. Use the standard touch gestures and controls that Windows 8 provides.

  34. Tiles

  35. 19. Use Windows Runtime to create image thumbnail for tiles • auto createThumbnail = create_task(sourceFile->GetThumbnailAsync(ThumbnailMode::PicturesView, ThumbnailSize)); • return createThumbnail.then([](StorageItemThumbnail^ thumbnail) { • IRandomAccessStream^ imageFileStream = static_cast<IRandomAccessStream^>(thumbnail); • return BitmapDecoder::CreateAsync(imageFileStream); • }).then([decoder](BitmapDecoder^ createdDecoder) { • (*decoder) = createdDecoder; • return createdDecoder->GetPixelDataAsync(BitmapPixelFormat::Rgba8, ...); • }).then([pixelProvider, resizedImageStream](PixelDataProvider^ provider) { • (*pixelProvider) = provider; • return BitmapEncoder::CreateAsync(BitmapEncoder::JpegEncoderId, resizedImageStream); • }).then([pixelProvider, decoder](BitmapEncoder^ createdEncoder) { • createdEncoder->SetPixelData(BitmapPixelFormat::Rgba8, ...); • return createdEncoder->FlushAsync(); • }).then([resizedImageStream] { • resizedImageStream->Seek(0); • return resizedImageStream; • });

  36. File System

  37. 20. Ensure queries prefetchproperties to improve performance • auto queryOptions = ref new QueryOptions(CommonFileQuery::OrderByDate, fileTypeFilter); • queryOptions->IndexerOption = IndexerOption::UseIndexerWhenAvailable; • queryOptions->SetPropertyPrefetch(PropertyPrefetchOptions::ImageProperties, dateTakenProperties); • queryOptions->Language = CalendarExtensions::ResolvedLanguage(); • auto fileQuery = folderQuery->CreateFileQueryWithOptions(queryOptions);

  38. Performance

  39. 21. Keep the launch times of your app fast • ... • m_tileUpdateScheduler= std::make_shared<TileUpdateScheduler>(); • m_tileUpdateScheduler->ScheduleUpdateAsync(m_repository, m_exceptionPolicy); • ...

  40. Bonus: Read the Guide

  41. Related Sessions • 11/2/2012 12:45- B33 McKinley- The Future of C++

  42. Links & thank you • Code  http://aka.ms/Hilocpp-code • Documentation  http://aka.ms/hilocpp-doc • Codeplex  http://hilo.codeplex.com • Thank you

More Related