Created
May 19, 2012 22:37
-
-
Save fincs/2732608 to your computer and use it in GitHub Desktop.
Fully native C++ WinRT (Metro-style) app
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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; | |
} |
Sorry but this is not a complete Windows store Application. Thanks anyway.
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
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
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