The app object and DirectX (Windows Runtime apps using DirectX with C++)
[ This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation ]
Windows Store apps with DirectX (mostly games) don't use many of the new Windows UI user interface elements and objects. Rather, because they run at a lower level in the Windows Runtime stack, they must interoperate with the user interface framework in a more fundamental way: by accessing and interoperating with the app object directly. Learn when and how this interoperation occurs, and how you, as a DirectX developer, can effectively use this model in the development of your Windows Store apps.
The important core user interface namespaces
First, let's note the Windows Runtime namespaces that you must include (with using) in your Windows Store apps. We get into the details in a bit.
- Windows.ApplicationModel.Core
- Windows.ApplicationModel.Activation
- Windows.UI.Core
- Windows.System
- Windows.Foundation
Note If you are not developing a Windows Store app using DirectX with C++, use the user interface components provided in the JavaScript- or XAML-specific libraries and namespaces instead of the types provided in these namespaces.
The Windows Runtime app object
In your Windows Store app, you want to get a window and a view provider from which you can get a view and to which you can connect your swap chain (your display buffers). You can also hook this view into the window-specific events for your running app. To get the parent window for the app object, defined by the CoreWindow type, create a type that implements IFrameworkViewSource, as we did in the previous code snippet.
Here's the basic set of steps to get a window using the core user interface framework:
Create a type that implements IFrameworkView. This is your view.
In this type, define:
- An Initialize method that takes an instance of CoreApplicationView as a parameter. You can get an instance of this type by calling CoreApplication.CreateNewView. The app object calls it when the app is launched.
- A SetWindow method that takes an instance of CoreWindow as a parameter. You can get an instance of this type by accessing the CoreWindow property on your new CoreApplicationView instance.
- A Load method that takes a string for an entry point as the sole parameter. The app object provides the entry point string when you call this method. This is where you set up resources. You create your device resources here. The app object calls it when the app is launched.
- A Run method that activates the CoreWindow object and starts the window event dispatcher. The app object calls it when the app's process starts.
- An Uninitialize method that cleans up the resources set up in the call to Load. The app object calls this method when the app is closed.
Create a type that implements IFrameworkViewSource. This is your view provider.
In this type, define:
- A method named CreateView that returns an instance of your IFrameworkView implementation, as created in step 1.
Pass an instance of the view provider to CoreApplication.Run from main.
With those basics in mind, let's look at more options you have to extend this approach.
Core user interface types
Here are other core user interface types in the Windows Runtime that you might find helpful:
- Windows.ApplicationModel.Core.CoreApplicationView
- Windows.UI.Core.CoreWindow
- Windows.UI.Core.CoreDispatcher
You can use these types to access your app's view, specifically, the bits that draw the contents of the app's parent window, and handle the events fired for that window. The app window's process is an application single-threaded apartment (ASTA) that is isolated and that handles all callbacks.
Your app's view is generated by the view provider for your app window, and in most cases will be implemented by a specific framework package or the system itself, so you don't need to implement it yourself. For DirectX, you need to implement a thin view provider, as discussed previously. There is a specific 1-to-1 relationship between the following components and behaviors:
- An app's view, which is represented by the CoreApplicationView type, and which defines the method(s) for updating the window.
- An ASTA, the attribution of which defines the threading behavior of the app. You cannot create instances of COM STA-attributed types on an ASTA.
- A view provider, which your app obtains from the system or which you implement.
- A parent window, which is represented by the CoreWindow type.
- Sourcing for all activation events. Both views and windows have separate activation events.
In summary, the app object provides a view provider factory. It creates a view provider and instantiates a parent window for the app. The view provider defines the app's view for the parent window of the app. Now, let's discuss the specifics of the view and the parent window.
CoreApplicationView behaviors and properties
CoreApplicationView represents the current app view. The app singleton creates the app view during initialization, but the view remains dormant until it is activated. You can get the CoreWindow that displays the view by accessing the CoreApplicationView.CoreWindow property on it, and you can handle activation and deactivation events for the view by registering delegates with the CoreApplicationView.Activated event.
CoreWindow behaviors and properties
The parent window, which is a CoreWindow instance, is created and passed to the view provider when the app object initializes. If the app has a window to display, it displays it; otherwise, it simply initializes the view.
CoreWindow provides a number of events specific to input and basic window behaviors. You can handle these events by registering your own delegates with them.
You can also obtain the window event dispatcher for the window by accessing the CoreWindow.Dispatcher property, which provides an instance of CoreDispatcher.
CoreDispatcher behaviors and properties
You can determine the threading behavior of event dispatching for a window with the CoreDispatcher type. On this type, there's one particularly important method: the CoreDispatcher.ProcessEvents method, which starts window event processing. Calling this method with the wrong option for your app can lead to all sorts of unexpected event processing behaviors.
CoreProcessEventsOption option | Description |
---|---|
CoreProcessEventsOption.ProcessOneAndAllPending | Dispatch all currently available events in the queue. If no events are pending, wait for the next new event. |
CoreProcessEventsOption.ProcessOneIfPresent | Dispatch one event if it is pending in the queue. If no events are pending, don't wait for a new event to be raised but instead return immediately. |
CoreProcessEventsOption.ProcessUntilQuit | Wait for new events and dispatch all available events. Continue this behavior until the window is closed or the application calls the Close method on the CoreWindow instance. |
CoreProcessEventsOption.ProcessAllIfPresent | Dispatch all currently available events in the queue. If no events are pending, return immediately. |
Windows Store apps using DirectX should use the CoreProcessEventsOption.ProcessAllIfPresent option to prevent blocking behaviors that might interrupt graphics updates.