WPF中调用UWP API

news2024/12/23 1:34:11

最近在github上看到一个音乐播放器项目,dopamine(项目地址:GitHub - digimezzo/dopamine-windows: Audio player which tries to make organizing and listening to music as simple and pretty as possible.)

在编译时,提示有一个库找不到

找了好一会,才发现这是调用了UWP的库。

在最初Windows 8 出来时,这一套新的运行时叫Windows RT,后面到Windows 10时,改成了UWP。

因为我也没做过UWP方面的开发,大概了解了一下。里面提供了一些新的API,UI上面也更加炫丽。

所以这里做个总结,如何在WPF中调用UWP的库,以后有需要的时候可以用得到。

===========================================================================

调用UWP API

这里我们以调用一个提供对当前地理位置的访问权限的类为例

Windows.Devices.Geolocation.Geolocator

.Net Framework版本

调用方法比较简单,跟引用其它库一样,直接引用UWP的库即可

1、先引用 Windows.winmd(位置:C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.22000.0),后面的版本号以机器上安装的版本为准 。

我也是第一次知道还能引用winmd这种格式

2、引用 System.Runtime.WindowsRuntime.dll(位置:C:\Windows\Microsoft.NET\Framework64\v4.0.30319)

官方博客上说的是C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\System.Runtime.WindowsRuntime.dll这个路径,但我电脑上没有这个文件,所以就到Windows目录下去找了。

.Net Core版本

针对.NET6 及以上版本,直接修改项目工程文件,将目标框架修改为带Windows版本号的即可。

  • net6.0-windows10.0.17763.0:Windows 10 版本 1809。
  • net6.0-windows10.0.18362.0:Windows 10 版本 1903。
  • net6.0-windows10.0.19041.0:Windows 10 版本 2004。
  • net6.0-windows10.0.22000.0:Windows 11。

不知道当前系统什么版本,运行输入winver查看

我电脑的系统版本是Windows 1903,所以修改如下:

针对.NET 6以下版本,安装Microsoft.Windows.SDK.Contracts  Nuget包。(这里我没测试过)

  • 10.0.19041.xxxx:Windows 10 版本 2004
  • 10.0.18362.xxxx: Windows 10 版本 1903
  • 10.0.17763.xxxx: Windows 10 版本 1809
  • 10.0.17134.xxxx: Windows 10 版本 1803

测试

新建一个WPF工程,创建如下测试代码:

xaml

1   <Grid>
2         <Button Content="调用UWP api获取当前地理位置" HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click"/>
3   </Grid>

xaml.cs

1  private async void Button_Click(object sender, RoutedEventArgs e)
2         {
3             var locator = new Windows.Devices.Geolocation.Geolocator();
4             var location = await locator.GetGeopositionAsync();
5             var position = location.Coordinate.Point.Position;
6             var latlong = string.Format("lat:{0}, long:{1}", position.Latitude, position.Longitude);
7             var result = MessageBox.Show(latlong);
8         }

开启电脑上的定位开关,运行结果如下:

注意:

有两个主要的 WinRT API 集在桌面应用中不受支持或具有限制:

  • 需要程序包标识符的 API(请参阅需要程序包标识符的功能)。 此类 API 仅在使用 MSIX 打包的桌面应用中受支持。(应用商店相关)
  • 依赖于用户界面 (UI) 功能的 API,这些功能仅在通用 Windows 平台 (UWP) 应用中可用。

基于代码生成 MSIX 程序包可以参考以下链接:基于代码生成 MSIX 程序包概述 - MSIX | Microsoft Learn。这里不做详细介绍了,感兴趣的可以自行了解。

无法在WPF使用UWP跟界面相关的API,解决方案如下:

如何在WPF中使用UWP的控件?

这里主要是借助CommunityToolkit.Wpf.UI.XamlHost包里的WindowsXamlHost控件实现。

以前在WPF中使用Winform控件时,使用了一个叫做WindowsFormHost的控件,原理是创建一个单独的窗口句柄,然后在上面进行绘制。

目测WindowsXamlHost应该也是类似的原理,具体也没有深入了解过。

WindowsXamlHost支持

  • Windows SDK 或 WinUI 库提供UWP 控件

  • 自定义 UWP 控件

使用代码创建及显示UWP控件

1、导入Nuget包,Microsoft.Toolkit.UI.XamlHost

2、引用 Windows.winmd

注意:

截止本文发布,

针对.NET Core版本,Microsoft.ToolKit.UI.XamlHost仅支持.NET 5以下版本。以后应该会支持到.NET 5及以后版本

https://learn.microsoft.com/en-us/answers/questions/1010047/does-net6-0-support-xaml-island

针对.Net FrameWork版本,需要添加app.manifest文件,否则运行时会报错。

添加app.manifest文件的方法是启用ClickOnce安全设置,然后再取消即可。

在MainWindow.cs中添加代码如下:

 1 public partial class MainWindow : Window
 2     {
 3         public MainWindow()
 4         {
 5             InitializeComponent();
 6             CreateUWPControlsFirst();
 7         }
 8 
 9         private void CreateUWPControlsFirst()
10         {
11             //初始化UWP容器环境
12             Windows.UI.Xaml.Hosting.WindowsXamlManager.InitializeForCurrentThread();
13 
14             //创建一个UWP按钮
15             Windows.UI.Xaml.Controls.Button myButton = new Windows.UI.Xaml.Controls.Button();
16             myButton.Name = "btn_Message";
17             myButton.Width = 188;
18             myButton.Height = 48;
19             myButton.TabIndex = 0;
20             myButton.Content = "弹出UWP消息框";
21             myButton.Click += MessageButton_Click;
22             Microsoft.Toolkit.Wpf.UI.XamlHost.WindowsXamlHost myHostControl = new Microsoft.Toolkit.Wpf.UI.XamlHost.WindowsXamlHost();
23             myHostControl.Name = "myWindowsXamlHostControl";
24             myHostControl.Child = myButton;
25             myHostControl.HorizontalAlignment = HorizontalAlignment.Center;
26             myHostControl.VerticalAlignment = VerticalAlignment.Center;
27             this.grid.Children.Add(myHostControl);
28         }
29 
30         private async void MessageButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
31         {
32             var messageDialog = new MessageDialog("这是一个示例的消息框");
33             messageDialog.Commands.Add(new UICommand(
34                 "确定",
35                 new UICommandInvokedHandler(this.Confirm)));
36             messageDialog.Commands.Add(new UICommand(
37                 "取消",
38                 new UICommandInvokedHandler(this.Cancel)));
39             messageDialog.DefaultCommandIndex = 0;
40             messageDialog.CancelCommandIndex = 1;
41             await messageDialog.ShowAsync();
42         }
43 
44         private void Confirm(IUICommand command)
45         {
46             
47         }
48 
49         private void Cancel(IUICommand command)
50         {
51 
52         }
53     }

运行效果:

在XAML中直接创建UWP控件

添加命名空间前缀:

1 xmlns:xamlhost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"

使用InitialTypeName属性设置初始控件类型

1 InitialTypeName="Windows.UI.Xaml.Controls.CalendarView"

添加当容器里控件渲染后事件处理程序

1 ChildChanged="MyCalendar_ChildChanged"

完整代码如下:

MainWindow.xaml

 1 <Window x:Class="HostUWPControl.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:HostUWPControl"
 7         xmlns:xamlhost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"
 8         mc:Ignorable="d"
 9         Title="MainWindow" Height="450" Width="800">
10     <Grid Name="grid">
11         <xamlhost:WindowsXamlHost x:Name="myCalendar" InitialTypeName="Windows.UI.Xaml.Controls.CalendarView"
12           Margin="10,10,10,10" Width="600" Height="300" ChildChanged="MyCalendar_ChildChanged" />
13     </Grid>
14 </Window>

MainWindow.xaml.cs

 1    private void MyCalendar_ChildChanged(object sender, EventArgs e)
 2         {
 3             WindowsXamlHost windowsXamlHost = (WindowsXamlHost)sender;
 4             var calendarView =(Windows.UI.Xaml.Controls.CalendarView)windowsXamlHost.Child;
 5             if (calendarView != null)
 6             {
 7                 calendarView.SelectedDatesChanged += (obj, args) =>
 8                 {
 9                     if (args.AddedDates.Count > 0)
10                     {
11                         MessageBox.Show("当前选择的日期是: " + args.AddedDates[0].DateTime.ToString());
12                     }
13                 };
14             }
15         }

 运行效果:

目前已经有部分UWP控件支持直接在XAML中添加,需要对项目进行一定的配置,这里就不做介绍了,上面两种方式在日常开发中应该够用了。后面有时间再更新如何直接在XAML中添加UWP控件。

示例代码 

参考文档:

Call Windows Runtime APIs in desktop apps

Call Windows Runtime APIs in desktop apps - Windows apps | Microsoft Learn

Calling Windows 10 APIs From a Desktop Application

Calling Windows 10 APIs From a Desktop Application - Windows Developer Blog

Windows Runtime APIs not supported in desktop apps

桌面应用中不支持的 Windows 运行时 API - Windows apps | Microsoft Learn

Building an MSIX package from your code

基于代码生成 MSIX 程序包概述 - MSIX | Microsoft Learn

Use XAML Islands to host a UWP XAML control

Use XAML Islands to host a UWP XAML control in a C# WPF app - Windows apps | Microsoft Learn

https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/xaml-islands#host-controls

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1970461.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

免费泛域名证书申请(永久免费,不限申请次数)

免费泛域名证书&#xff08;也称为通配符SSL证书&#xff09;的申请过程通常涉及以下几个步骤。以下是一个详细的指南&#xff0c;帮助您了解如何申请免费泛域名证书&#xff1a; 一、选择合适的证书提供商 目前&#xff0c;市场上提供免费泛域名证书的服务商主要有Lets Encr…

从零开始学习网络安全渗透测试之基础入门篇——(六)网络抓包全局协议封包监听网卡模式科来wiresharkPC应用

网络抓包技术是一种用于捕获和分析网络数据包的技术手段。它能够帮助我们深入了解网络中的数据传输情况&#xff0c;对于网络故障排查、性能优化、安全监测等方面都具有重要意义。 网络抓包的工作原理通常是通过将网络接口设置为混杂模式&#xff0c;使其能够接收流经该接口的…

openEuler使用mariadb

1.安装mariadb 两者互为依赖 解决&#xff1a; 2.开机自启 3.进入数据库 数据库默认没有密码&#xff0c;直接回车进入 4.安全初始化 5.修改密码 远程用户无法登录 6.创建远程登录用户 7.创建数据库 8.赋予远程用户bbs数据库的操作权限 查看用户权限 9.使用普通账号&…

[Docker][Docker NetWork][下]详细讲解

目录 1.网络管理命令1.docker network creatre2.docker network inspect3.docker network connect4.docker network disconnect5.docker network prune6.docker network rm7.docker network ls 2.docker bridge 详解0.基本概念1.默认 bridge2.自定义 bridge3.DNS解析4.端口暴露…

45 标准库 collections 中与字典有关的类

Python 标准库中提供了很多扩展功能&#xff0c;大幅度提高了开发效率。主要介绍 collections 中 OrderedDict 类、defaultdict 类和 Counter类。 1 OrderedDict 类 Python 内置字典 dict 是无序的&#xff0c;如果需要一个可以记住元素插入顺序的字典&#xff0c;则可以使用…

大厂的风控引擎架构设计

1 架构师能力思维模型 全局思维抽象思维 2 新需求的思考路径 需求是否合理&#xff0c;是否能解决问题&#xff1f; 能划分多少个子系统&#xff1f; 每个子系统能划分多少个模块&#xff1f;这个系统需要可靠性吗&#xff0c;需要扩展能力吗&#xff1f;成本需要控制吗&a…

路径规划——广度优先搜索与深度优先搜索

路径规划——广度优先搜索与深度优先搜索 https://www.hello-algo.com/chapter_graph/graph_traversal/ 1.广度优先搜索 Breath-First-Search 在图论中也称为广度优先遍历&#xff0c;类似于树的层序遍历。 算法原理 从起始节点出发&#xff0c;首先访问它的邻近节点&…

openEuler中安装数据库

目录 一.安装数据库 二.出现报错解决方法 1.根据报错查看冲突软件包 2.忽略软件依赖性解决 3.再次查看是否删掉冲突软件 三.再次执行安装数据库命令 四.启动数据库可直接输入mysql进入数据库&#xff0c;此时不安全 五.安全初始化 1.是否有root密码&#xff0c;没有直…

从表型感知到全链路贯通:数字孪生与LLM重塑设施农业新范式

当前,设施农业正处于从传统模式向现代智慧农业加速跃迁的关键时期。数字孪生和大语言模型引领的技术变革浪潮为催生设施农业的创新发展模式提供了新的可能。二者携手打造的全场景数字化运营新范式,必将重塑农业生产的业态和价值链。农业科技工作者应顺应时代发展潮流,将数字孪生…

iOS-Swift 数据库 WCDB 二次封装使用/自定义字段映射类型

WCDB官方使用文档 WCDB简介 WCDB 是一个易用、高效、完整的移动数据库框架&#xff0c;它基于 SQLite 和 SQLCipher 开发&#xff0c;在微信中应用广泛&#xff0c;且支持在 C、Java、Kotlin、Swift、Objc 五种语言环境中使用。 整体架构&#xff1a; 对于WCDB详细的介绍和…

Tomcat安装教程

Tomcat官方网站&#xff1a;http://tomcat.apache.org/ 1.找到左边一栏有个Download&#xff0c;点击Tomcat 10 注意&#xff1a;Tomcat也是要下载JDK环境的&#xff0c;这里我使用Tomcat 10&#xff0c;JDK环境要大于等于11版本&#xff0c;具体可看下图&#xff1a; 2.下拉找…

更小、更安全、更透明:Google发布的Gemma推动负责任AI的进步

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Python习题 101:输入年月打印日历

使用了 Python 的内置库 calendar&#xff0c;它提供提供与日历有关功能&#xff0c;可以帮助我们做时间日期相关的计算&#xff0c;省去复杂的判断&#xff0c;比较实用。

cv2读取中文路径图像名称

1.cv2.imdecode 是 OpenCV 库中的一个函数&#xff0c;用于从内存中的数据解码图像。这通常用于从文件、网络传输或数据库中读取图像数据而不必直接从磁盘读取。此函数特别适用于处理字节数组形式的图像数据。 img cv2.imdecode(buf, flagsNone) 参数说明&#xff1a; buf&am…

解锁PDF编辑新境界:2024年大家都在用的4款工具

PDF这个文件格式大家应该都不陌生吧。他以不易窜改和可以保持版式一直的优势成为我们日常传输文件的首选格式。随着使用使用率的增加&#xff0c;一些PDF表格如果能直接修改内容就能有效的提升工作效率。这就需要借助一些PDF编辑工具来实现啦。 1.福昕PDF编辑器 直达链接&am…

游戏(河南萌新2024)

1.超时的写法&#xff08;没有用堆优化&#xff09; #include <bits/stdc.h>using namespace std; typedef long long ll; typedef double db; typedef long double ldb; typedef pair<int, int> pii; typedef pair<ll, ll> PII; #define pb emplace_back /…

vulnhub靶场serial-php渗透(蜥蜴细!)

目录 一、信息收集 1.探测主机存活&#xff08;目标主机IP地址&#xff09; 2.访问web服务 3.后台目录和端口扫描 4.解析bak.zip源码 二、漏洞利用 1.构造payload 2.通过bp的repeater模块 3.get shell 4.获取反弹shell 三、提升权限 1. 查看系统版本&#xff0c;内核…

ctfshow 大赛原题 web697--web700

web697 先扫一下&#xff0c;其实也可以不用扫 因为什么也扫不出来 这里看到有一个参数 尝试一下数组 随便输了&#xff0c;出了验证回显抓个包看 ffifdyop e58 4611686052576742364这三个md5加密可以自带引号 SELECT master FROM secret WHERE password binary ,b…

文件包含漏洞汇总

文章目录 原理文件包含函数伪协议函数本地包含file协议filter协议input协议data协议 远程文件包含条件http协议 日志文件绕过概念日志路径复现 文件包含之条件竞争概念靶场介绍复现 文件下载文件下载常见的目录系统目录linuxwindows 程序配置文件apachenginxredis 目录遍历与目…