Search code examples
c++windowswindows-phone-8.1windowactivation

Minimal app for Windows Phone 8.1 (no XAML) : differences with desktop app


I'm beginning the development of Windows Runtime applications in C++. I'm experienced on Win32/C++ development but this is a new world for me.

The following is a minimal, no-XAML app I've typed, collecting information from various sources (MSDN, DirectXTutorial.com, etc).

My question is: In Windows desktop, works well by displaying a blank window and receiving the PointerPressed Event. But in Windows Phone I only reach the app start logo and nothing happens.

What is the difference between two platforms for this minimal app? Do I require to create some DirectX or drawing surface in the case of the Windows Phone 8.1 platform?

I'm using WIndows 10 host plus Visual Studio 2015. Thanks.

#include "pch.h"

using namespace Windows::ApplicationModel;
using namespace Windows::ApplicationModel::Core;
using namespace Windows::ApplicationModel::Activation;
using namespace Windows::UI::Core;
using namespace Windows::Foundation;
using namespace Platform;

ref class dxAppView sealed : IFrameworkView
{
    bool _bActive;

public:
    virtual void Initialize(CoreApplicationView ^applicationView)
    {
        applicationView->Activated += ref new TypedEventHandler<CoreApplicationView ^, IActivatedEventArgs ^>(this, &dxAppView::OnActivated);
        CoreApplication::Suspending += ref new EventHandler<SuspendingEventArgs^>(this, &dxAppView::OnSuspending);
        CoreApplication::Resuming += ref new EventHandler<Object ^>(this, &dxAppView::OnResuming);

        _bActive = true;
    }

    virtual void SetWindow(CoreWindow ^window)
    {       
        window->PointerPressed += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &dxAppView::OnPointerPressed);
        window->Closed += ref new Windows::Foundation::TypedEventHandler<Windows::UI::Core::CoreWindow ^, Windows::UI::Core::CoreWindowEventArgs ^>(this, &dxAppView::OnClosed);
    }

    virtual void Load(String ^entryPoint) {}
    virtual void Run() 
    {
        CoreWindow^ wnd = CoreWindow::GetForCurrentThread();

        while (_bActive)
        {
            wnd->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
        }

    }

    virtual void Uninitialize() {}

    void OnActivated(CoreApplicationView ^sender, IActivatedEventArgs ^args)
    {
        CoreWindow^ wnd = CoreWindow::GetForCurrentThread();
        wnd->Activate();
    }

    void OnPointerPressed(CoreWindow ^sender, PointerEventArgs^  args)
    {
        Windows::UI::Popups::MessageDialog dlg(L"Hi From Windows Runtime app.");
        dlg.ShowAsync();
    }

    void OnSuspending(Platform::Object ^sender, Windows::ApplicationModel::SuspendingEventArgs ^args){}

    void OnResuming(Platform::Object ^sender, Platform::Object ^args){}

    void OnClosed(Windows::UI::Core::CoreWindow ^sender, Windows::UI::Core::CoreWindowEventArgs ^args)
    {
        _bActive = false;
    }
};

ref class dxAppFrameworkViewSource sealed : IFrameworkViewSource
{
public:
    virtual IFrameworkView^ CreateView()
    {
        return ref new dxAppView;
    }
};


[MTAThread]
int main(Array<String^>^ args)
{
    CoreApplication::Run(ref new dxAppFrameworkViewSource());
    return 0;
};

Solution

  • I've found it, seems that you can't do anything in Phone 8.1 without a DX swap chain active. So, the minimal no-XAML application involves the following additional code:

    Create a Direct3D Device

    (Variables prefixed with underscore are class members)

    ComPtr<ID3D11DeviceContext> pDevCtx;
    ComPtr<ID3D11Device>        pDev;
    ComPtr<IDXGISwapChain>      pSwapChain;
    
    D3D_FEATURE_LEVEL fLevel;
    
    HRESULT hr = D3D11CreateDevice(
            nullptr,
            D3D_DRIVER_TYPE_HARDWARE,
            nullptr,
            0,
            nullptr,
            0,
            D3D11_SDK_VERSION,
            &pDev,
            &fLevel,
            &pDevCtx);
    

    Create a swap chain

    pDevCtx.As(&_pDevCtx);
    pDev.As(&_pDevice);
    
    ComPtr<IDXGIDevice1> pDXGIDev;
    pDev.As(&pDXGIDev);
    
    ComPtr<IDXGIAdapter> pDXGIAdapter;
    pDXGIDev->GetAdapter(&pDXGIAdapter);
    
    ComPtr<IDXGIFactory2> pDXGIFactory;
    pDXGIAdapter->GetParent(__uuidof(IDXGIFactory2), &pDXGIFactory);
    
    DXGI_SWAP_CHAIN_DESC1 swChDesc = { 0 };
    swChDesc.BufferCount = 2;
    swChDesc.SampleDesc.Count = 1;
    swChDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    swChDesc.SampleDesc.Quality = 0;
    swChDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swChDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
    
    CoreWindow^ wnd  = CoreWindow::GetForCurrentThread();
    
    pDXGIFactory->CreateSwapChainForCoreWindow(
        _pDevice.Get(),
        (IUnknown*) wnd,
        &swChDesc,
        nullptr,
        _pSwapChain.GetAddressOf());
    

    Present (flip your buffers)

    while (_bActive)
    {
      wnd->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
      Render();
    }
    

    where Render() can be something like:

    _pSwapChain->Present(1, NULL);