In testing some of Kenny Kerr's sample code for C++/Winrt I find the following demonstration of a canvas drawing operation:
CanvasTextFormat format;
format.HorizontalAlignment(CanvasHorizontalAlignment::Center);
format.VerticalAlignment(CanvasVerticalAlignment::Center);
format.FontSize(72.0f);
format.FontFamily(L"Segoe UI Semibold");
control.Draw([=](CanvasControl const& sender, CanvasDrawEventArgs const& args)
{
float2 size = sender.Size();
float2 center{ size.x / 2.0f, size.y / 2.0f };
Rect bounds{ 0.0f, 0.0f, size.x, size.y };
CanvasDrawingSession session = args.DrawingSession();
session.FillEllipse(center, center.x - 50.0f, center.y - 50.0f, Colors::DarkSlateGray());
session.DrawText(L"Win2D with\nC++/WinRT!", bounds, Colors::Orange(), format);
});
The Draw operation works great in my project except for the text drawing - that line will not build as written. VS says argument 2 can't be converted from Rect to float:
C2664 'void winrt::impl::consume_Microsoft_Graphics_Canvas_ICanvasDrawingSession<winrt::Microsoft::Graphics::Canvas::ICanvasDrawingSession>::DrawText(const winrt::param::hstring &,float,float,float,float,const winrt::Windows::UI::Color &,const winrt::Microsoft::Graphics::Canvas::Text::CanvasTextFormat &) const': cannot convert argument 2 from 'winrt::Windows::Foundation::Rect' to 'float'
it seems to want to interpret this call as the version that takes four float arguments, and does so even if I type the second argument. Yet one of the DrawText methods in winrt clearly says that argument 2 can be a rect. And that is the only variant that also uses Color and Format arguments:
template void consume_Microsoft_Graphics_Canvas_ICanvasDrawingSession::DrawText(param::hstring const& text, Windows::Foundation::Rect const& rectangle, Windows::UI::Color const& color, Microsoft::Graphics::Canvas::Text::CanvasTextFormat const& format) const { check_hresult(WINRT_SHIM(Microsoft::Graphics::Canvas::ICanvasDrawingSession)->DrawTextAtRectWithColorAndFormat(get_abi(text), get_abi(rectangle), get_abi(color), get_abi(format))); }
Seems to me that VS is not telling me what is wrong with my implementation - maybe there is something else wrong rather than argument 2 not being a float? I've attempted to duplicate closely the sample's use of DrawText.
[Update] Curiouser and curiouser: suddenly VS is returning link errors for the text format too - Previously it had no trouble with that, but only with the call to DrawText. Maybe this is a hint. I tried just changing the color of the ellipse; the text format wouldn't link; changed the ellipse color back to the way it was before and it still won't build, though I didn't touch the format declaration at all. Here is the link error:
Error LNK2019 unresolved external symbol "public: void __thiscall winrt::impl::consume_Microsoft_Graphics_Canvas_Text_ICanvasTextFormat<struct winrt::Microsoft::Graphics::Canvas::Text::ICanvasTextFormat>::FontFamily(struct winrt::param::hstring const &)const " (?FontFamily@?$consume_Microsoft_Graphics_Canvas_Text_ICanvasTextFormat@UICanvasTextFormat@Text@Canvas@Graphics@Microsoft@winrt@@@impl@winrt@@QBEXABUhstring@param@3@@Z) referenced in function "public: void __thiscall <lambda_05084435c3f7f2f96a04d3453f0476aa>::operator()(struct winrt::Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &,struct winrt::Microsoft::Graphics::Canvas::UI::Xaml::CanvasDrawEventArgs const &)const " (??R<lambda_05084435c3f7f2f96a04d3453f0476aa>@@QBEXABUCanvasControl@Xaml@UI@Canvas@Graphics@Microsoft@winrt@@ABUCanvasDrawEventArgs@234567@@Z)
So, now it will build and run if I comment out the declaration for text format. Previously it ran fine with that present - just couldn't link the DrawText call.
I'm not 100% on understanding why this fix works, but it does work: I took the declaration of the text format object out of the lambda, to start with. And I noticed that at some point during editing, the name winrt::Microsoft::Graphics::Canvas::Text::CanvasTextFormat had gotten changed to winrt::Microsoft::Graphics::Canvas::Text::ICanvasTextFormat, which clearly is wrong (Does anyone have a link to an explanation of the meaning of the "I" in such keywords?). At any rate the declaration produces no struct if "I" is there, so that was simply an error on my part. Yet it failed before, too, before I accidentally put in the "I." So perhaps the critical fix was taking the declaration outside the lambda body. I now pass the DrawingSession to a draw method and - VS now understands the arguments for DrawText, and it draws the text very nicely. More lessons learned. Thanks to IInspectable (there's the "I" again) for looking at this.