如何用C++/WinRT+WinUI3编程设置Path几何图形?代码报错求助
C++/WinRT + WinUI3 路径标记语法转换问题
我有几十年MFC开发经验,正在学习C++/WinRT和WinUI 3,目前正在将Petzold《Programming Windows》第6版中的C#代码转换为C++/WinRT,处理第2章的PathMarkupSyntaxCode示例。尝试实现后程序报错,希望排查问题。
参考的C#代码
public MainPage() { this.InitializeComponent(); Path path = new Path { Stroke = new SolidColorBrush(Colors.Red), StrokeThickness = 12, StrokeLineJoin = PenLineJoin.Round, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, Data = PathMarkupToGeometry( "M 0 0 L 0 100 M 0 50 L 50 50 M 50 0 L 50 100 " + "M 125 0 C 60 -10, 60 60, 125 50, 60 40, 60 110, 125 100 " + "M 150 0 L 150 100, 200 100 " + "M 225 0 L 225 100, 275 100 " + "M 300 50 A 25 50 0 1 0 300 49.9") }; (this.Content as Grid).Children.Add(path); } Geometry PathMarkupToGeometry(string pathMarkup) { string xaml = "<Path " + "xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>" + "<Path.Data>" + pathMarkup + "</Path.Data></Path>"; Path path = XamlReader.Load(xaml) as Path; // Detach the PathGeometry from the Path Geometry geometry = path.Data; path.Data = null; return geometry; }
我编写的C++/WinRT代码(报错版本)
MainWindow::MainWindow() { InitializeComponent(); std::string str; str = "M 0 0 L 0 100 M 0 50 L 50 50 M 50 0 L 50 100 "; str += "M 125 0 C 60 -10, 60 60, 125 50, 60 40, 60 110, 125 100 "; str += "M 150 0 L 150 100, 200 100 "; str += "M 225 0 L 225 100, 275 100 "; str += "M 300 50 A 25 50 0 1 0 300 49.9"; Path path; path.Stroke(SolidColorBrush(Colors::Red())); path.StrokeThickness(12); path.StrokeLineJoin(PenLineJoin::Round); path.HorizontalAlignment(HorizontalAlignment::Center); path.VerticalAlignment(VerticalAlignment::Center); path.Data(PathMarkupToGeometry(str)); Grid().Children().Append(path); } Geometry MainWindow::PathMarkupToGeometry(const std::string& pathMarkup) { std::string xaml = "<Path "; xaml += "xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>"; xaml += "<Path.Data>"; xaml += pathMarkup; xaml += "</Path.Data></Path>"; hstring str = winrt::to_hstring(xaml); auto tmpl = XamlReader::Load(str); Path path(tmpl.try_as<Path>()); Geometry geometry = path.Data(); return geometry; }
错误情况
设置path.Data时,程序在Microsoft.UI.Xaml.h的OnLaunched函数的produce()结构体中抛出错误,原因是参数'args'为0。目标是在主窗口显示由路径标记组成的HELLO图形。
问题排查与修正
1. 错误:添加Path到临时Grid实例
原代码中Grid().Children().Append(path)创建了一个全新的临时Grid对象,并未关联到窗口的实际Content容器,导致Path无法被渲染到界面。修正为获取窗口的Content并转换为Grid:
if (auto grid = Content().try_as<Grid>()) { grid.Children().Append(path); }
2. 错误:字符串编码与XAML格式问题
使用std::string转hstring可能存在编码偏差,直接改用winrt::hstring构造路径标记与XAML字符串,避免转换错误;同时XAML字符串中直接使用<和>而非转义字符(C++宽字符串无需HTML转义)。
3. 错误:Geometry所有权未解除
原C#代码中通过path.Data = null解除Geometry与原Path的关联,C++/WinRT中需要执行相同操作,否则返回的Geometry仍被原Path持有,导致新Path无法正确获取所有权:
Geometry geometry = path.Data(); path.Data(nullptr); // 解除关联 return geometry;
4. 补充:添加空指针检查
在将XamlReader加载的对象转换为Path时,添加空指针检查,避免后续操作访问无效对象。
修正后的完整代码
MainWindow构造函数
MainWindow::MainWindow() { InitializeComponent(); winrt::hstring pathMarkup = L"M 0 0 L 0 100 M 0 50 L 50 50 M 50 0 L 50 100 " L"M 125 0 C 60 -10, 60 60, 125 50, 60 40, 60 110, 125 100 " L"M 150 0 L 150 100, 200 100 " L"M 225 0 L 225 100, 275 100 " L"M 300 50 A 25 50 0 1 0 300 49.9"; Path path; path.Stroke(SolidColorBrush(Colors::Red())); path.StrokeThickness(12); path.StrokeLineJoin(PenLineJoin::Round); path.HorizontalAlignment(HorizontalAlignment::Center); path.VerticalAlignment(VerticalAlignment::Center); path.Data(PathMarkupToGeometry(pathMarkup)); // 获取窗口的Content Grid并添加Path if (auto grid = Content().try_as<Grid>()) { grid.Children().Append(path); } }
PathMarkupToGeometry函数
Geometry MainWindow::PathMarkupToGeometry(const winrt::hstring& pathMarkup) { winrt::hstring xaml = L"<Path " L"xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>" L"<Path.Data>" + pathMarkup + L"</Path.Data></Path>"; auto xamlObj = XamlReader::Load(xaml); Path path = xamlObj.try_as<Path>(); if (!path) { throw winrt::hresult_error(E_INVALIDARG, L"Failed to load Path from XAML"); } Geometry geometry = path.Data(); path.Data(nullptr); // 解除Geometry与原Path的关联 return geometry; }
内容的提问来源于stack exchange,提问作者dr_eck
相关产品推荐
相关产品推荐

