I got the following C++/CX code that works as intended but would like to convert it to C++/WinRT code:
namespace My.Custom.Stuff
{
[Windows::Foundation::Metadata::WebHostHidden]
public ref class BaseClass : public Windows::UI::Xaml::Controls::SwapChainPanel
{
public:
BaseClass();
void PublicMethod();
protected:
static ::DirectX::XMFLOAT3 ProtectedMethod();
};
}
namespace My.Custom.Stuff
{
[Windows::Foundation::Metadata::WebHostHidden]
public ref class SubClass sealed : public BaseClass
{
public:
SubClass();
void UseProtectedMethod()
{
::DirectX::XMFLOAT3 value = ProtectedMethod()
// ...
}
};
}
However, the problem that I encounter is as follows: BaseClass
contains a protected method that returns a type that cannot be mapped to a corresponding Windows Runtime type. In C++/CX this is not a problem because ProtectedMethod
is not mapped at all. If I use my Windows Runtime component ProtectedMethod
is simply not exposed which is what I want.
However, that method should be a member of BaseClass
because multiple other classes like SubClass
use the method when implementing their public methods. I have come up with the following C++/WinRT MIDL code:
namespace My.Custom.Stuff
{
unsealed runtimeclass BaseClass : Windows.UI.Xaml.Controls.SwapChainPanel
{
BaseClass();
void PublicMethod();
// This does not work
protected DirectX.XMFLOAT3 RgbFromBrush(IInspectable brush);
}
}
import "BaseClass.idl";
namespace My.Custom.Stuff
{
runtimeclass SubClass : BaseClass
{
SubClass();
void UseProtectedMethod();
}
}
The problem is that if I define ProtectedMethod
that way it won't work because ::DirectX::XMFLOAT3
is no Windows Runtime type. If I use any other return type that protected method gets mapped. However, it should not be visible when using that Windows Runtime component and of course I should not have to change its return type.
How can I achieve what I do with C++/CX using C++/WinRT?
Edit
Compiling the MIDL code results in something like this:
#include "BaseClass.g.h"
namespace winrt::My::Custom::Stuff::implementation
{
struct BaseClass : BaseClassT<BaseClass>
{
BaseClass() = default;
// ...
};
}
namespace winrt::My::Custom::Stuff::factory_implementation
{
struct BaseClass : BaseClassT<BaseClass, implementation::BaseClass>
{
};
}
I thought it might be possible to simply add the protected method as follows:
namespace winrt::My::Custom::Stuff::implementation
{
struct BaseClass : BaseClassT<BaseClass>
{
BaseClass() = default;
protected:
static ::DirectX::XMFLOAT3 ProtectedMethod();
};
}
However, attempting to use ProtectedMethod
in SubClass
results in the following error:
error C2039: 'ProtectedMethod': is not a member of 'winrt::My::Custom::Stuff::BaseClass'
Here's how I'm using it:
#include "SubClass.g.h"
namespace winrt::My::Custom::Stuff::implementation
{
struct SubClass : SubClassT<SubClass>
{
SubClass() = default;
void UseProtectedMethod()
{
::DirectX::XMFLOAT3 value = ProtectedMethod();
}
};
}
namespace winrt::My::Custom::Stuff::factory_implementation
{
struct SubClass : SubClassT<SubClass, implementation::SubClass>
{
};
}
When converting from C++/CX to C++/WinRT, only public methods should go into your IDL file, as those are the only methods comprising the WinRT API surface.
Methods that are private/protected/internal are not part of the WinRT API surface, and so they should not go into the IDL.
The usage code you posted shouldn't compile, because your C++ definition of
implementation::SubClass
is missing a template parameter. Since the IDL/WinRT definition hasSubClass
deriving fromBaseClass
, you need to supplyBaseClass
's implementation type toSubClassT
, and if you examine the contents of the cppwinrt-generated "SubClass.h", you'll see this happening. Once you declare your implementation ofSubClass
correctly, you will have access to the protected methods onBaseClass
.I just tried this out successfully, and it looks like this:
BaseClass.idl
BaseClass.h
SubClass.idl
SubClass.h