Presentation: “Introduction to Writing Metro Style Apps in Native C++”

advertisement
Introduction to Writing Metro
Style Apps in Native C++
Marc Grégoire
Software Architect
[email protected]
http://www.nuonsoft.com/
http://www.nuonsoft.com/blog/
May 8th 2012
Agenda






Windows 8 Platform
Windows Runtime (WinRT)
C++ Extensions (C++/CX)
Asynchronous programming model
Libraries (WinRT   STL)
XAML
Windows 8 Platform
Model
Controller
View
Metro style Apps
XAML
XAML
C
C++
Desktop Apps
HTML / CSS
C#
VB
JavaScript
(Chakra)
JavaScript
C
C++
C#
VB
Internet
Explorer
Win32
.NET
/ SL
HTML
Core
System Services
WinRT APIs
Communication
& Data
Graphics & Media
Devices & Printing
Application Model
Windows Core OS Services
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++ Extensions (C++/CX)
Key Bindings
Feature
Summary
1. Data Types
ref class
Reference type
value class
Value type
interface class
Interface
property
Property with get/set
event
“Delegate property” with add/remove/raise
delegate
Type-safe function pointer
generic
Type-safe generics
ref new
Reference-counted allocation
2. Allocation
3. Pointer & Reference ^
%
Strong pointer (“hat” or “handle”)
Strong reference
C++ Extensions (C++/CX)
C/C++
External Surface
for native
callers/callees
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();
p2->Name = "John";
p = p2;
}
p = nullptr;
//
//
//
//
//
ref
ref
ref
ref
ref
count
count
count
count
count
=
=
=
=
=
1
1
2
1
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) Usage:
Person^ p = ref new Person("John");
Example:
p->Greet(ref new Person("Jim"));
public ref class Person
{
public:
Person(String^ name, String^ email);
void Greet(Person^ other);
Public/protected methods  only
WinRT parameters
internal:
~Person();
void SetPassword(const std::wstring& passwd);
};
Private/internal methods
 any C++ types as
parameters
WinRT Interface

Defining

public interface class IShape
{
void Draw();
};

ref class Rectangle : ISelectableShape
{
public:
virtual void Draw();
virtual void Select();
};
Inheriting
public interface
class ISelectableShape : IShape
{
void Select();
};
Implementing

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 own
exceptions from Exception
HRESULT
Exception
E_OUTOFMEMORY
OutOfMemoryException
E_INVALIDARG
InvalidArgumentException
E_NOINTERFACE
InvalidCastException
E_POINTER
NullReferenceException
E_NOTIMPL
NotImplementedException
E_ACCESSDENIED
AccessDeniedException
E_FAIL
FailureException
E_BOUNDS
OutOfBoundsException
E_CHANGED_STATE
ChangedStateException
REGDB_E_CLASSNOTREG
ClassNotRegisteredException
E_DISCONNECTED
DisconnectedException
E_ABORT
OperationCanceledException
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
Async with PPL Tasks




Windows 8 Metro only allows asynchronous operations for
anything that can take longer than a couple milliseconds.
For example: there are no synchronous file operations possible
in Metro.
Advantage: keeps UI fast and fluid
Disadvantage: programming can be more complex, but new
PPL tasks support helps alot here.
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. */
}
);
Libraries (WinRT   STL)
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);
XAML
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
Demo C++ and XAML
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.
Download
Related flashcards

Theory of computation

16 cards

ARM architecture

23 cards

X86 architecture

22 cards

MSN

28 cards

Web development

38 cards

Create Flashcards