Skip to content

Instantly share code, notes, and snippets.

@fincs
Created May 19, 2012 22:37
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save fincs/2732608 to your computer and use it in GitHub Desktop.
Save fincs/2732608 to your computer and use it in GitHub Desktop.
Fully native C++ WinRT (Metro-style) app
//
// Fully native C++ WinRT application example
// Programmed by fincs
//
#include <windows.h>
#include <roapi.h>
#include <wchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wrl.h>
#include <Windows.UI.Xaml.h>
#include <Windows.UI.Xaml.Markup.h>
#include <Windows.ApplicationModel.Activation.h>
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace Windows::Foundation;
using namespace ABI::Windows::UI::Xaml;
using namespace ABI::Windows::UI::Xaml::Markup;
using namespace ABI::Windows::ApplicationModel::Activation;
//---------------------------------------------------------------------------
// Error handling
//---------------------------------------------------------------------------
// Even though this is officially unsupported and the corresponding declaration in
// the header files is left out for WinRT apps, it is actually possible to use these
// "forbidden" functions via manually including the declaration like as follows:
extern "C" int WINAPI MessageBoxW(HWND parent, LPCWSTR aText, LPCWSTR aTitle, int opt);
// Error checking helper
void CheckHRESULT(HRESULT hr, LPCWSTR message)
{
if (FAILED(hr))
{
WCHAR aBuf[1024];
swprintf_s(aBuf, L"Error 0x%08X during: %s", hr, message);
MessageBoxW(NULL, aBuf, L"BareMetalMetroApp", MB_ICONERROR);
exit(1);
}
}
//---------------------------------------------------------------------------
// Application class
//---------------------------------------------------------------------------
class MyApp: public RuntimeClass<IApplicationOverrides>
{
InspectableClass(L"BareMetalMetroApp.MyApp", BaseTrust);
protected:
ComPtr<IApplicationOverrides> pBaseImpl;
public:
void SetBase(IApplicationOverrides* _pBaseImpl)
{
pBaseImpl = _pBaseImpl;
}
STDMETHOD(OnActivated)(IActivatedEventArgs* args) { return pBaseImpl->OnActivated(args); }
STDMETHOD(OnLaunched)(ILaunchActivatedEventArgs* args);
STDMETHOD(OnFileActivated)(IFileActivatedEventArgs* args) { return pBaseImpl->OnFileActivated(args); }
STDMETHOD(OnSearchActivated)(ISearchActivatedEventArgs* args) { return pBaseImpl->OnSearchActivated(args); }
STDMETHOD(OnShareTargetActivated)(IShareTargetActivatedEventArgs* args) { return pBaseImpl->OnShareTargetActivated(args); }
STDMETHOD(OnFileOpenPickerActivated)(IFileOpenPickerActivatedEventArgs* args) { return pBaseImpl->OnFileOpenPickerActivated(args); }
STDMETHOD(OnFileSavePickerActivated)(IFileSavePickerActivatedEventArgs* args) { return pBaseImpl->OnFileSavePickerActivated(args); }
STDMETHOD(OnCachedFileUpdaterActivated)(ICachedFileUpdaterActivatedEventArgs* args) { return pBaseImpl->OnCachedFileUpdaterActivated(args); }
};
//---------------------------------------------------------------------------
// OnLaunched event
//---------------------------------------------------------------------------
#define MARKUP_TO_LOAD \
L"<Grid xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">" \
L" <TextBlock Text=\"Hello, fully native world!\" VerticalAlignment=\"Center\" HorizontalAlignment=\"Center\" FontSize=\"48\" />" \
L"</Grid>"
// TODO: find out how to listen to events coming from e.g. buttons
// L" <Button Content=\"Click me\" VerticalAlignment=\"Center\" HorizontalAlignment=\"Center\" />"
/*
// This is what this function looks like under C++/CX:
void MyApp::OnLaunched(ILaunchActivatedEventArgs^ args)
{
Window::Current->Content = XamlReader::Load(MARKUP_TO_LOAD);
}
*/
STDMETHODIMP MyApp::OnLaunched(ILaunchActivatedEventArgs* args)
{
// Prepare HSTRING versions of class names
HStringReference WindowClsName(RuntimeClass_Windows_UI_Xaml_Window);
HStringReference XamlReaderClsName(RuntimeClass_Windows_UI_Xaml_Markup_XamlReader);
HStringReference MarkupData(MARKUP_TO_LOAD);
// pCurWin = Window::Current
ComPtr<IWindow> pCurWin;
{
ComPtr<IWindowStatics> pWinStatics;
CheckHRESULT(GetActivationFactory(WindowClsName.Get(), &pWinStatics), L"IWinStatics");
CheckHRESULT(pWinStatics->get_Current(&pCurWin), L"get_Current");
}
ComPtr<IUIElement> pContent;
{
ComPtr<IXamlReaderStatics> pXamlReaderStatics;
ComPtr<IInspectable> pObj;
// pContent = XamlReader::Load(MarkupData)
CheckHRESULT(GetActivationFactory(XamlReaderClsName.Get(), &pXamlReaderStatics), L"IXamlReaderStatics");
CheckHRESULT(pXamlReaderStatics->Load(MarkupData.Get(), &pObj), L"Markup loading failure");
CheckHRESULT(pObj.As(&pContent), L"IUIElement");
}
// pCurWin->Content = pContent
pCurWin->put_Content(pContent.Get());
pCurWin->Activate();
return S_OK;
}
//---------------------------------------------------------------------------
// Application initialization function
//---------------------------------------------------------------------------
/*
// This is what this function looks like under C++/CX:
static void InitApplication(IApplicationInitializationCallbackParams^ args)
{
auto app = ref new MyApp();
}
*/
static STDMETHODIMP InitApplication(IApplicationInitializationCallbackParams* args)
{
// Prepare HSTRING versions of class names
HStringReference ApplicationClsName(RuntimeClass_Windows_UI_Xaml_Application);
ComPtr<IApplicationFactory> pAppFactory;
CheckHRESULT(GetActivationFactory(ApplicationClsName.Get(), &pAppFactory), L"IApplicationFactory");
ComPtr<MyApp> pMyApp = Make<MyApp>();
ComPtr<IApplication> pApp;
{
// This is done like this because pInner is set to a reference to the same object as the
// return value (albeit with a different VTable (offset)), and the Microsoft guys *FORGOT*
// to AddRef(). Therefore we need to throw out the pInner pointer.
IInspectable* pInner;
CheckHRESULT(pAppFactory->CreateInstance(pMyApp.Get(), &pInner, &pApp), L"CreateInstance");
}
// Set the inherited Application object
ComPtr<IApplicationOverrides> pBaseImpl;
CheckHRESULT(pApp.As(&pBaseImpl), L"IApplicationOverrides");
pMyApp->SetBase(pBaseImpl.Get());
return S_OK;
}
//---------------------------------------------------------------------------
// Application entrypoint
//---------------------------------------------------------------------------
/*
// This is what this function looks like under C++/CX:
int main()
{
Application::Start(ref new ApplicationInitializationCallback(InitApplication));
return 0;
}
*/
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
// Initialize WinRT
RoInitializeWrapper init(RO_INIT_MULTITHREADED);
CheckHRESULT(init, L"RoInitialize");
ComPtr<IApplicationStatics> pAppStatics;
HStringReference ApplicationClsName(RuntimeClass_Windows_UI_Xaml_Application);
CheckHRESULT(GetActivationFactory(ApplicationClsName.Get(), &pAppStatics), L"IApplicationStatics");
// Application::Start(AppMain)
ComPtr<IApplicationInitializationCallback> pCallback = Callback<IApplicationInitializationCallback>(InitApplication);
pAppStatics->Start(pCallback.Get());
return 0;
}
@adrushya
Copy link

Hi Fincs,

One has to add one more method
STDMETHOD(OnWindowCreated)(IWindowCreatedEventArgs* args) { return pBaseImpl->OnWindowCreated(args);}
so that one can create an instance of this class MyApp.
Also the MessageBox thingy does not compile.
Even after removing all the compile time error I could not get this to work. It simply crashes.
Any ideas what might be going wrong.
Thanks,
--=> Adru.

@fincs
Copy link
Author

fincs commented Oct 15, 2012

  1. This code was written in the days of Windows 8 CP, so the interface may have changed.
  2. You need to link to user32.lib.

@tomun
Copy link

tomun commented Oct 19, 2012

I was able to get this code to compile and run in Windows 8 RTM by adding the following to MyApp:
STDMETHOD(OnWindowCreated)(IWindowCreatedEventArgs* args) { return S_OK; }

if I attempted to add
STDMETHOD(OnWindowCreated)(IWindowCreatedEventArgs* args) { return pBaseImpl->OnWindowCreated(args);}
as adrushya suggested above, then at runtime the app would crash due to a stack overflow. pBaseImpl is the same as 'this' at runtime. Perhaps your comment in InitApplication about the VTable is no longer applicable to Win8 RTM?

Thanks for this enlightening sample!
Tom

@FreeVili
Copy link

FreeVili commented Mar 3, 2013

Hi
I'm new under the metro. I had try your source. It compiled and ran simple, but didn't do anything (I mean nothing show up). Did I do something wrong?
FreeVili

@wpbest
Copy link

wpbest commented Mar 23, 2015

Sorry but this is not a complete Windows store Application. Thanks anyway.

@2bitsin
Copy link

2bitsin commented Mar 9, 2016

This crashes on startup :/
windows\dxaml\xcp\dxaml\lib\frameworkapplication_partial.cpp(143)\Windows.UI.Xaml.dll!00007FFF204C5EA0: (caller: 00007FF7D8D3D169) FailFast(1) tid(3694) 8000FFFF Catastrophic failure

@teodorbaciu
Copy link

To run the application, you need an application package manifest. The XAML UI APIs require an application to have a package identity. For more information see Creating a minimal UWP app using the WRL and Run, debug, and test an MSIX package. Another option would be to create a Win32 app and use XAML islands (this option requires an application manifest): Host a standard UWP control in a C++ Win32 app

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment