Tag Archives: WinRT

WRL component with support for Event handlers

The WRL sample is updated to support event handling on a WinRT component.

It requires a special delegate type in the IDL file.

// Library1.IDL
import "inspectable.idl";
import "Windows.Foundation.idl";

#define COMPONENT_VERSION 1.0

namespace Library1
{
    interface ILogger;
    runtimeclass Logger;

    [uuid(1FCD374B-2C3C-49E3-93A7-6FB801080D45), version(COMPONENT_VERSION)]
    delegate HRESULT LoggerEventHandler([in] HSTRING e);

    [uuid(3EC4B4D6-14A6-4D0D-BB96-31DA25224A15), version(COMPONENT_VERSION)]
    interface ILogger : IInspectable
    {
        HRESULT LogInfo([in] HSTRING value);
        [eventadd] HRESULT LoggerChanged([in] LoggerEventHandler* handler, [out][retval] EventRegistrationToken* token);
        [eventremove] HRESULT LoggerChanged([in] EventRegistrationToken token);
    }

    [version(COMPONENT_VERSION), activatable(COMPONENT_VERSION)]
    runtimeclass Logger
    {
        [default] interface ILogger;
    }
}

Sample updated : http://code.msdn.microsoft.com/windowsapps/Windows-Runtime-Component-4dc6fa20

Advertisements

New article about WinRT/C++/WRL in French magazine Programmez n°174

The issue number 174 of Programmez magazine, available on May 1, will contain my technical article about WinRT, C++ and WRL.

New WRL containers updated !

Based on my first sample review (see previous post), I have updated my C++/WRL sample that implements Vector<T>, Map<K, V>, UnorderedMap<K, V>.

This file is the C++/WRL portage of the collection.h file that was designed for C++/CX.

Sample Link: http://code.msdn.microsoft.com/windowsapps/Windows-Runtime-Component-9b6c6989

WRL Sample reviewed done

My C++/WRL sample available in Dev Center – Windows Store Apps has been reviewed by the creator of WRL himself, Sridhar Madhugiri.

Because this sample source code will be the support for an upcoming technical article published in Dr Dobb’s magazine Digital Issue, I have asked the Microsoft Visual C++ Lead to give me some advices.

I had a strange bug in some circumstances. So he proposed directly to Sridhar to give me some help !

My problem was about handling HSTRING new Windows data type. It has to be wrapped with a String helper class.

The same issue occurred with interface pointers that need to be wrapped with the ComPtr<T> class.

Sample Link: http://code.msdn.microsoft.com/windowsapps/Windows-Runtime-Component-4dc6fa20

New WRL container like Vector, Map support for Standard ISO C++

I have made a portage of collection.h available for C++/CX for handling collections like Vector<T>, Map<K, V>.

This header can be only used for C++/CX so… if you want to rely on standard ISO C++, you can download my header called NewCollection.h.

It’s available on Dev Center – Windows Store Apps : http://code.msdn.microsoft.com/windowsapps/Windows-Runtime-Component-9b6c6989

The WRL project template to download

Just update your Visual Studio to download the WRL Project template here. It allows to target WinRT component.

Be careful, you have to update your project with Linker -> Windows Metadata -> Generate Windows Metadata to TRUE.

This project template allows to build WinRT components using the real C++. Not the C++/CX compiler extensions.

Building WinRT or COM Components with C++ and WRL

When you want to make Windows 8.x applications using C++, there are few possibilities:

  • using C++/CX which are C++ compiler extensions
  • using WRL in standard C++ project

C++/CX is a complete change for writting C++ classes. The pointer and references symbols have changed. You have to pass only Windows Runtime types in your methods. Objects need to be constructed using ref new instead of new. Example:

// h file
namespace WindowsRuntimeComponent1
{
public ref class Logger sealed
{
public:
Logger();

public:
void LogInfo(String^ message);
};
}

// cpp file
using namespace WindowsRuntimeComponent1;

Logger::Logger()
{
}

void Logger::LogInfo(String^ message)
{
std::wstring str = message->Data();
String^ str2 = ref new String();
str2 = L"hello String^";
}

C++/CX is easy but your code is completely stucked with thoses ugly C++/CX extensions. There is another way to make WinRT components. This is the Microsoft way of doing things. It is called WRL, Windows Runtime Library. It is like ATL, the new ATL. Here is an example of a WinRT component using WRL:

// idl file
import "inspectable.idl";
import "Windows.Foundation.idl";

#define COMPONENT_VERSION 1.0

namespace Library1
{
interface ILogger;
runtimeclass Logger;

[uuid(3EC4B4D6-14A6-4D0D-BB96-31DA25224A15), version(COMPONENT_VERSION), exclusiveto(Logger)]
interface ILogger : IInspectable
{
HRESULT LogInfo([in] HSTRING value);
HRESULT GetInt32([out] int * pValue);
}

[version(COMPONENT_VERSION), activatable(COMPONENT_VERSION)]
runtimeclass Logger
{
[default] interface ILogger;
}
}

// h file
namespace ABI
{
namespace Library1
{
class Logger : public RuntimeClass<ILogger>
{
InspectableClass(L"Library1.Logger", BaseTrust)

public:
Logger();

public:
STDMETHOD(LogInfo)(HSTRING value);
STDMETHOD(GetInt32)(int * pValue);
};

ActivatableClass(Logger);
}
}

// cpp file
namespace ABI
{
namespace Library1
{
Logger::Logger()
{
}

STDMETHODIMP Logger::LogInfo(HSTRING value)
{
HString str;
str.Set(value);
std::wstring ws = str.GetRawBuffer(nullptr);
return S_OK;
}

STDMETHODIMP Logger::GetInt32(int * pValue)
{
*pValue = 10;
return S_OK;
}
}
}

With this kind of code, you stay with the real C++ and you use the built-in Windows type.
For string handling, there is a new handle or pointer called HSTRING and the WRL class that handles it is HString.

With WRL you can also create standard COM components. You just have to change the header or your classes to use a different RuntimeClass template and adjust your IDL file to use COM built-in types:

// idl file
import "oaidl.idl";
import "ocidl.idl";

#define COMPONENT_VERSION 1.0

[uuid(3AAF07AA-A699-4E7C-8F01-BFF237D22B1B), version(COMPONENT_VERSION)]
interface ILogger : IUnknown
{
HRESULT LogInfo([in] BSTR bstrMessage);
}

[uuid(F15D3912-E8B8-40C8-8CF3-354F0B8B93CC), version(COMPONENT_VERSION)]
library WRLCOMLibrary1
{
[uuid(75DB8F5A-F13F-4E16-A487-9CD26A874654), version(COMPONENT_VERSION)]
coclass Logger
{
[default] interface ILogger;
}
}

// h file
class Logger : public RuntimeClass<RuntimeClassFlags<ClassicCom>, ILogger>
{
public:
Logger();

public:
STDMETHOD(LogInfo)(BSTR bstrMessage);
};

CoCreatableClass(Logger);

This kind of construction works if you build a standard Win32 dll and add runtimeobject.lib to your linker input.