Fully native C++ WinRT application example
1 // 2 // Fully native C++ WinRT application example 3 // Programmed by fincs 4 // 5 6 #include <windows.h> 7 #include <roapi.h> 8 #include <wchar.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <wrl.h> 13 14 #include <Windows.UI.Xaml.h> 15 #include <Windows.UI.Xaml.Markup.h> 16 #include <Windows.ApplicationModel.Activation.h> 17 18 using namespace Microsoft::WRL; 19 using namespace Microsoft::WRL::Wrappers; 20 using namespace Windows::Foundation; 21 using namespace ABI::Windows::UI::Xaml; 22 using namespace ABI::Windows::UI::Xaml::Markup; 23 using namespace ABI::Windows::ApplicationModel::Activation; 24 25 //--------------------------------------------------------------------------- 26 // Error handling 27 //--------------------------------------------------------------------------- 28 29 // Even though this is officially unsupported and the corresponding declaration in 30 // the header files is left out for WinRT apps, it is actually possible to use these 31 // "forbidden" functions via manually including the declaration like as follows: 32 extern "C" int WINAPI MessageBoxW(HWND parent, LPCWSTR aText, LPCWSTR aTitle, int opt); 33 34 // Error checking helper 35 void CheckHRESULT(HRESULT hr, LPCWSTR message) 36 { 37 if (FAILED(hr)) 38 { 39 WCHAR aBuf[1024]; 40 swprintf_s(aBuf, L"Error 0x%08X during: %s", hr, message); 41 MessageBoxW(NULL, aBuf, L"BareMetalMetroApp", MB_ICONERROR); 42 exit(1); 43 } 44 } 45 46 //--------------------------------------------------------------------------- 47 // Application class 48 //--------------------------------------------------------------------------- 49 50 class MyApp: public RuntimeClass<IApplicationOverrides> 51 { 52 InspectableClass(L"BareMetalMetroApp.MyApp", BaseTrust); 53 54 protected: 55 ComPtr<IApplicationOverrides> pBaseImpl; 56 57 public: 58 void SetBase(IApplicationOverrides* _pBaseImpl) 59 { 60 pBaseImpl = _pBaseImpl; 61 } 62 63 STDMETHOD(OnActivated)(IActivatedEventArgs* args) { return pBaseImpl->OnActivated(args); } 64 STDMETHOD(OnLaunched)(ILaunchActivatedEventArgs* args); 65 STDMETHOD(OnFileActivated)(IFileActivatedEventArgs* args) { return pBaseImpl->OnFileActivated(args); } 66 STDMETHOD(OnSearchActivated)(ISearchActivatedEventArgs* args) { return pBaseImpl->OnSearchActivated(args); } 67 STDMETHOD(OnShareTargetActivated)(IShareTargetActivatedEventArgs* args) { return pBaseImpl->OnShareTargetActivated(args); } 68 STDMETHOD(OnFileOpenPickerActivated)(IFileOpenPickerActivatedEventArgs* args) { return pBaseImpl->OnFileOpenPickerActivated(args); } 69 STDMETHOD(OnFileSavePickerActivated)(IFileSavePickerActivatedEventArgs* args) { return pBaseImpl->OnFileSavePickerActivated(args); } 70 STDMETHOD(OnCachedFileUpdaterActivated)(ICachedFileUpdaterActivatedEventArgs* args) { return pBaseImpl->OnCachedFileUpdaterActivated(args); } 71 }; 72 73 //--------------------------------------------------------------------------- 74 // OnLaunched event 75 //--------------------------------------------------------------------------- 76 77 #define MARKUP_TO_LOAD \ 78 L"<Grid xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">" \ 79 L" <TextBlock Text=\"Hello, fully native world!\" VerticalAlignment=\"Center\" HorizontalAlignment=\"Center\" FontSize=\"48\" />" \ 80 L"</Grid>" 81 82 // TODO: find out how to listen to events coming from e.g. buttons 83 // L" <Button Content=\"Click me\" VerticalAlignment=\"Center\" HorizontalAlignment=\"Center\" />" 84 85 /* 86 // This is what this function looks like under C++/CX: 87 88 void MyApp::OnLaunched(ILaunchActivatedEventArgs^ args) 89 { 90 Window::Current->Content = XamlReader::Load(MARKUP_TO_LOAD); 91 } 92 */ 93 94 STDMETHODIMP MyApp::OnLaunched(ILaunchActivatedEventArgs* args) 95 { 96 // Prepare HSTRING versions of class names 97 HStringReference WindowClsName(RuntimeClass_Windows_UI_Xaml_Window); 98 HStringReference XamlReaderClsName(RuntimeClass_Windows_UI_Xaml_Markup_XamlReader); 99 HStringReference MarkupData(MARKUP_TO_LOAD); 100 101 // pCurWin = Window::Current 102 ComPtr<IWindow> pCurWin; 103 { 104 ComPtr<IWindowStatics> pWinStatics; 105 CheckHRESULT(GetActivationFactory(WindowClsName.Get(), &pWinStatics), L"IWinStatics"); 106 CheckHRESULT(pWinStatics->get_Current(&pCurWin), L"get_Current"); 107 } 108 109 ComPtr<IUIElement> pContent; 110 { 111 ComPtr<IXamlReaderStatics> pXamlReaderStatics; 112 ComPtr<IInspectable> pObj; 113 114 // pContent = XamlReader::Load(MarkupData) 115 CheckHRESULT(GetActivationFactory(XamlReaderClsName.Get(), &pXamlReaderStatics), L"IXamlReaderStatics"); 116 CheckHRESULT(pXamlReaderStatics->Load(MarkupData.Get(), &pObj), L"Markup loading failure"); 117 CheckHRESULT(pObj.As(&pContent), L"IUIElement"); 118 } 119 120 // pCurWin->Content = pContent 121 pCurWin->put_Content(pContent.Get()); 122 pCurWin->Activate(); 123 124 return S_OK; 125 } 126 127 //--------------------------------------------------------------------------- 128 // Application initialization function 129 //--------------------------------------------------------------------------- 130 131 /* 132 // This is what this function looks like under C++/CX: 133 134 static void InitApplication(IApplicationInitializationCallbackParams^ args) 135 { 136 auto app = ref new MyApp(); 137 } 138 */ 139 140 static STDMETHODIMP InitApplication(IApplicationInitializationCallbackParams* args) 141 { 142 // Prepare HSTRING versions of class names 143 HStringReference ApplicationClsName(RuntimeClass_Windows_UI_Xaml_Application); 144 145 ComPtr<IApplicationFactory> pAppFactory; 146 CheckHRESULT(GetActivationFactory(ApplicationClsName.Get(), &pAppFactory), L"IApplicationFactory"); 147 148 ComPtr<MyApp> pMyApp = Make<MyApp>(); 149 ComPtr<IApplication> pApp; 150 { 151 // This is done like this because pInner is set to a reference to the same object as the 152 // return value (albeit with a different VTable (offset)), and the Microsoft guys *FORGOT* 153 // to AddRef(). Therefore we need to throw out the pInner pointer. 154 IInspectable* pInner; 155 CheckHRESULT(pAppFactory->CreateInstance(pMyApp.Get(), &pInner, &pApp), L"CreateInstance"); 156 } 157 158 // Set the inherited Application object 159 ComPtr<IApplicationOverrides> pBaseImpl; 160 CheckHRESULT(pApp.As(&pBaseImpl), L"IApplicationOverrides"); 161 pMyApp->SetBase(pBaseImpl.Get()); 162 163 return S_OK; 164 } 165 166 //--------------------------------------------------------------------------- 167 // Application entrypoint 168 //--------------------------------------------------------------------------- 169 170 /* 171 // This is what this function looks like under C++/CX: 172 173 int main() 174 { 175 Application::Start(ref new ApplicationInitializationCallback(InitApplication)); 176 return 0; 177 } 178 */ 179 180 int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) 181 { 182 // Initialize WinRT 183 RoInitializeWrapper init(RO_INIT_MULTITHREADED); 184 CheckHRESULT(init, L"RoInitialize"); 185 186 ComPtr<IApplicationStatics> pAppStatics; 187 HStringReference ApplicationClsName(RuntimeClass_Windows_UI_Xaml_Application); 188 CheckHRESULT(GetActivationFactory(ApplicationClsName.Get(), &pAppStatics), L"IApplicationStatics"); 189 190 // Application::Start(AppMain) 191 ComPtr<IApplicationInitializationCallback> pCallback = Callback<IApplicationInitializationCallback>(InitApplication); 192 pAppStatics->Start(pCallback.Get()); 193 194 return 0; 195 }