340 likes | 528 Views
Introduction to Writing Metro Style Apps in Native C ++. Marc Grégoire Software Architect marc.gregoire@nuonsoft.com http://www.nuonsoft.com / http://www.nuonsoft.com/blog /. Agenda. Windows 8 Platform Windows Runtime ( WinRT ) C++ Extensions (C++/CX) Asynchronous programming model
E N D
Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com http://www.nuonsoft.com/ http://www.nuonsoft.com/blog/
Agenda • Windows 8 Platform • Windows Runtime (WinRT) • C++ Extensions (C++/CX) • Asynchronous programming model • Libraries (WinRT STL) • XAML
Windows 8 Platform Metro style Apps Desktop Apps HTML JavaScript HTML / CSS XAML XAML View JavaScript (Chakra) C C++ C C++ C# VB Model Controller C C++ C# VB WinRT APIs Devices & Printing Communication & Data Graphics & Media System Services .NET / SL Internet Explorer Win32 Application Model Windows Core OS Services Core
Windows 8 Platform – Where can C++ be used? • Metro Hybrid Apps • HTML5 + Javascript front-end • C++ components • Metro XAML Apps • UI using XAML • C++ code behind • Metro high performance 2D/3D Apps • C++ with DirectX rendering
Windows Runtime • Set of language extensions and libraries to allow direct consumption and authoring of WinRT types • Strongly-typed system for Windows Runtime • Automatically reference counted • Exception-based • Deep integration with STL • Well defined binary contract across module boundaries, ABI-safe
C++ Extensions (C++/CX) C/C++ External Surface for native callers/callees WinRT External Surface for WinRT callers/callees Module Internals written in C++
Automatic Lifetime Management • Handle (^ / Hat) is smart pointer to WinRT objects • Reference counted • Allocated with ref new • Example: Person^ p; { Person^ p2 = ref new Person(); // ref count = 1 p2->Name = "John"; // ref count = 1 p = p2; // ref count = 2 } // ref count = 1 p = nullptr; // ref count = 0 ~Person()
Automatic Lifetime Management • On the stack, or as a member of another WinRT type • Example: { Person p; p.Name= "John"; /* ... */ } // ~Person()
WinRT Class • Use ref class to define new WinRT classes (ABI-safe cross-language classes) • Example: public ref class Person { public: Person(String^ name, String^ email); void Greet(Person^ other); internal: ~Person(); void SetPassword(conststd::wstring& passwd); }; Usage: Person^ p = ref new Person("John"); p->Greet(ref new Person("Jim")); Public/protected methods only WinRT parameters Private/internal methods any C++ types as parameters
WinRT Interface • Defining public interface class IShape { void Draw(); }; • Inheriting public interface class ISelectableShape : IShape { void Select(); }; • Implementing ref class Rectangle : ISelectableShape { public: virtual void Draw(); virtual void Select(); }; • Using IShape^ shape = ref new Rectangle(); shape->Draw();
WinRT Property • Defining • Trivial properties (with private backing store) public: property String^ Name; • User defined properties public: property Person^ Sibling { Person^ get() { InitSiblings(); return _sibling; } void set(Person^ value) { _sibling = value; NotifySibling(); } } private: Person^ _sibling; • Using Person^ p = ref new Person("John"); p->Sibling = ref new Person(p->Name);
WinRT Delegate • Declaring public delegate void PropertyChanged(String^ propName, String^ propValue); • Instantiating • From lambda: auto p = ref new PropertyChanged( [](String^ pn, String^ pv) { cout << pn << " = " << pv; }); • From free-function auto p = ref new PropertyChanged(UIPropertyChanged); • From class-member auto p = ref new PropertyChanged(this, MainPage::OnPropertyChanged); • Invoking p("Visible", "f");
WinRT Event • Defining • Trivial event (with private backing store) public: event PropertyChanged^ OnPropertyChanged; • User defined properties public: event PropertyChanged^ OnNetworkChanged { EventRegistrationToken add(PropertyChanged^); void remove(EventRegistrationToken t); void raise(String^, String^); } • Using • Subscribing person->OnPropertyChanged += propertyChangedDelegate; auto token = person->OnPropertyChanged::add(propertyChangedDelegate); • Unsubscribing person->OnPropertyChanged -= token; person->OnPropertyChanged::remove(token);
WinRT Exceptions • Under the covers, WinRT uses COM, thus HRESULTs • WinRT wraps HRESULTs into exceptions • Throwing exceptions throw ref new InvalidArgumentException(); throw ref new COMException(E_*); • Catching exceptions try { … } catch (OutOfMemoryException^ ex) { … } • Access HRESULT value via ex->HResult
WinRT Exceptions • Only a fixed set of exceptions available • Catch all WinRT exceptions: catch (Platform::Exception^) { } • You cannot derive your ownexceptions from Exception
WinRT Generics • Defining generic<typename T, typename U> public interface class IPair { property T First; property U Second; }; • Implementing ref class PairStringUri: IPair<String^, Uri^> { public: property String^ First; property Uri^ Second; }; • Using IPair<String^, Uri^>^ uri= ref new PairStringUri(); auto first = uri->First; // String^ auto second = uri->Second; // Uri^
WinRT .winmd Metadata Files • .winmd files • Contain the metadata representation of WinRT types • To consume a winmd file: • Right click on project in Solution Explorer > References > Add New Reference… Or • #using <Company.Component.winmd> • Make sure the winmd and implementation dll is packaged together with your application • To produce a .winmd file: • Start from the “C++ WinRT Component Dll” template • Define public types (ref classes, interfaces, delegates, etc.)
WinRT Partial Runtime Classes • Partial class definition partial ref class MainPage: UserControl, IComponentConnector { public: void InitializeComponent(); void Connect() { btn1->Click += ref new EventHandler(this, &MainPage::Button_Click); } }; • Class definition ref class MainPage { public: MainPage() { InitializeComponent(); } void Button_Click(Object^ sender, RoutedEventArgs^ e); };
Async with PPL Tasks • Windows 8 Metro onlyallowsasynchronous operations foranythingthatcan take longerthan a couplemilliseconds. • For example: there are no synchronous file operations possible in Metro. • Advantage: keeps UI fastandfluid • Disadvantage: programmingcanbe more complex, but new PPL tasks support helpsalothere.
Async with PPL Tasks • Example: create a file in the standard “Pictures” folder, without PPL Tasks: StorageFolder^ folder = KnownFolders::PicturesLibrary; auto createStorageFileOp= folder->CreateFileAsync("myfile.txt"); createStorageFileOp->Completed = ref new AsyncOperationCompletedHandler<StorageFile^>( [](IAsyncOperation<StorageFile^>^ asyncOp, AsyncStatus status) { StorageFile^ storageFile = asyncOp->GetResults(); /* Do something with the file. */ } );
Async with PPL Tasks • with PPL Tasks: StorageFolder^ folder = KnownFolders::PicturesLibrary; create_task(folder->CreateFileAsync("myfile.txt")).then( [](StorageFile^ storageFile) { /* Do something with the file. */ } );
Vector and ObservableVector • Instantiating using namespace Platform::Collections; Vector<String^>^ items = ref new Vector<String^>(); • Adding elements items->Append("Hello"); • Returning a read-only view of the vector IVectorView<String^>^ view = items->GetView(); • Getting notification for changes items->VectorChanged += ref new VectorChangedEventHandler<String^> (this, &MyClass::VectorChanged);
Map and ObservableMap • Defining using namespace Platform::Collections; auto favorites = ref new Map<String^, Uri^>(); • Adding elements favorites->Insert("MSDN", ref new Uri("http://msdn.com")); • Checking and removing elements if (favorites->HasKey("MSDN")) favorites->Remove("MSDN");
Integration with STL Algorithms • WinRT String has Begin()/End() member methods. • For WinRT collections, collection.h defines begin() and end() functions. • Example: IVector<int>^ v = GetItems(); int sum = 0; std::for_each(begin(v), end(v), [&sum](int element) { sum += element; });
Integration with STL Containers • Conversion is possible between STL containers and WinRT containers • String^ std::wstring (via wchar_t*) • Vector std::vector std::vector<int> v; v.push_back(10); auto items = ref new Vector<int>(v); • Vector std::vector Vector<int>^ items = ...; std::vector<int> v = to_vector(items);
Windows 8 Platform – Where can C++ be used? • Metro Hybrid Apps • HTML5 + Javascript front-end • C++ components • Metro XAML Apps • UI using XAML • C++ code behind • Metro high performance 2D/3D Apps • C++ with DirectX rendering
Resources • “Using Windows Runtime With C++” – Herb Sutter • http://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-532T • “Building Windows Metro style apps in C++/XAML” – Vikas Bhatia, Joanna Mason • http://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-479T
Questions ? I would like to thank Herb Sutter from Microsoft for his permission to base this presentation on one that he wrote for Build 2011.