Windows 应用 SDK 是一组新的开发人员组件和工具,它们代表着 Windows 应用开发平台的下一步发展。 Windows 应用 SDK 提供一组统一的 API 和工具,可供从 Windows 11 到 Windows 10 版本 1809 上的任何桌面应用以一致的方式使用。
Windows 应用 SDK 不会用 C++ 替换 Windows SDK 或现有桌面 Windows 应用类型,例如 .NET(包括 Windows 窗体和 WPF)和桌面 Win32。 相反,Windows 应用 SDK 使用一组通用 API 来补充这些现有工具和应用类型,开发人员可以在这些平台上依赖这些 API 来执行操作。 有关更多详细信息,请参阅Windows 应用 SDK 的优势。
这个WASDK目前是微软主推的开源的,UI部分是结合了WinUI 3。
欢迎使用 Windows Presentation Foundation (WPF) 桌面指南,这是一个与分辨率无关的 UI 框架,使用基于矢量的呈现引擎,构建用于利用现代图形硬件。 WPF 提供一套完善的应用程序开发功能,这些功能包括 Extensible Application Markup Language (XAML)、控件、数据绑定、布局、二维和三维图形、动画、样式、模板、文档、媒体、文本和版式。 WPF 属于 .NET,因此可以生成整合 .NET API 其他元素的应用程序。
目前WPF也已经开源,而且整体上更为成熟,Visual Studio就是WPF 4.x开发的,生态也比较好。
欢迎使用 Windows 窗体的桌面指南,Windows 窗体是一个可创建适用于 Windows 的丰富桌面客户端应用的 UI 框架。 Windows 窗体开发平台支持广泛的应用开发功能,包括控件、图形、数据绑定和用户输入。 Windows 窗体采用 Visual Studio 中的拖放式可视化设计器,可轻松创建 Windows 窗体应用。
这个也是开源的,Winform算是上手即用的开发框架了,通过拖拉拽可以很轻松的创建出UI和编写对应的功能,对于UI美观程度不太重要的工业领域,这个用来做工具开发很简单,上手也容易。
UWP 是创建适用于 Windows 的客户端应用程序的众多方法之一。 UWP 应用使用 WinRT API 来提供强大的 UI 和高级异步功能,这些功能非常适用于 Internet 连接的设备。
微软对于UWP,只能说曾经爱过,当初UWP可是当红炸子鸡,号称跨windows全平台,不过现在也是跨windows全平台,可惜没搞好,不过虽然不够受重视,但是一时半会还是死不掉,毕竟WASDK还不够成熟。
通过上面的介绍,大家对于windows下的原生UI开发框架应该有了一些了解,如果抛开语言限制的话还有更多的选择,比如QT,各种前端的跨平台,像微软自己家的MAUI什么的,我之前还写了一篇WinUI迁移到即将"过时"的.NET MAUI个人体验。
最近的微软Windows App SDK 1.1版本发布了,意味着BUG应该少了很多,也可以正式的在一些项目中使用了。通过官方的WinUI库,我们可以轻松的构建符合Win11设计规范的UI,由于UWP的种种问题,WPF和WinForms又是只开源,应该不会有大的新特性了,外加本人以前也经常玩玩UWP,通过前景和自己的喜好,肯定是选择WASDK了。

上图为应用的展示图,采用的WASDK1.1版本开发,目前已经上架了Windows商店,打包方式为MSIX,目前x64和arm64是分开的MSIX包,文档里提到可以多个MSIX包合成一个集合包,不过我采用上传多个包,让商店自动匹配。
此应用是为稚晖君的ElectronBot开发的第三方的上位机,名字就叫电子脑壳。下图是效果图展示,结合Surface平板,触摸体验良好,个人感觉很优雅。

ElectronBot本身连接电脑采用的是libusb生成的驱动吧,这个不知道叙述的是否正确。
看下图大体能明白电脑和ElectronBot通过高速USB进行连接,当我们驱动安装成功就可以进行操作了。

电子脑壳应用=>ElectronBot.DotNet SDK=>LibUsbDotNet
底层调用采用的是LibUsbDotNet这个库进行底层数据传输的操作,我根据稚晖君提供的c++版本的sdk进行了封装。
目前c#版本的SDKElectronBot.DotNet是开源的,demo示例也是windowsAppSDK的,大家感兴趣的可以star一下。
开始创建项目前最好安装下Template Studio for WinUI


选择模板进行创建,可以根据需要进行选择,本人选择如下。

由于ElectronBot .Net SDK本身已经开源,直接以上位机主体应用做讲解。下图为应用的依赖项,主要包含SDK和OpenCV相关的nuget包。

应用整体不复杂,通过.Net框架自带的DI容器进行对象生命周期的管理,通过MVVM进行数据的绑定和更新。
结合Win2D和OpenCV进行图形数据处理,然后通过SDK写入到usb设备里进行控制和展示。

下面的代码是通过切换Combox事件,动态创建不同的表盘并绑定到MainWindows的控件上。
private ICommand _clockChangedCommand;
public ICommand ClockChangedCommand =>
_clockChangedCommand ?? (_clockChangedCommand = new RelayCommand(ClockChanged));
private async void ClockChanged()
{
var clockName = _clockComboxSelect.DataKey;
if (!string.IsNullOrWhiteSpace(clockName))
{
var viewProvider = _viewProviderFactory.CreateClockViewProvider(clockName);
Element = viewProvider.CreateClockView(clockName);
}
await Task.CompletedTask;
}
public UIElement Element
{
get => _element;
set => SetProperty(ref _element, value);
}
xaml代码如下。

通过此操作,能够正常显示表盘,数据刷新也能正常使用。
当切换到时钟模式的时候,另外一个定时器会定时抓取表盘并将xaml转化成图片进行传输,主要涉及到Win2D库的使用,代码如下。
if (_electron.Connect())
{
var bitmap = new RenderTargetBitmap();
await bitmap.RenderAsync(Element);
var pixels = await bitmap.GetPixelsAsync();
// Transfer the pixel data from XAML to Win2D for further processing.
using CanvasDevice canvasDevice = CanvasDevice.GetSharedDevice();
using CanvasBitmap canvasBitmap = CanvasBitmap.CreateFromBytes(
canvasDevice, pixels.ToArray(), bitmap.PixelWidth, bitmap.PixelHeight,
Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized);
using IRandomAccessStream stream = new InMemoryRandomAccessStream();
await canvasBitmap.SaveAsync(stream, CanvasBitmapFileFormat.Png);
Bitmap image = new Bitmap(stream.AsStream());
var mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(image);
var mat1 = mat.Resize(new OpenCvSharp.Size(240, 240), 0, 0, OpenCvSharp.InterpolationFlags.Area);
var mat2 = mat1.CvtColor(OpenCvSharp.ColorConversionCodes.RGBA2BGR);
var dataMeta = mat2.Data;
var data = new byte[240 * 240 * 3];
Marshal.Copy(dataMeta, data, 0, 240 * 240 * 3);
await Task.Run(() =>
{
if (_electron.Connect())
{
_electron.SetImageSrc(data);
_electron.Sync();
}
});
}
上面代码通过RenderTargetBitmap和Win2D将Xaml元素转化成CanvasBitmap,然后再通过OpenCV将canvasBitmap转化成下位机可识别的字节数组,通过SDK进行传输到下位机。
整体的开发过程和UWP很相似,UI部分用到的很多API都是UWP的改名版本,上位机目前没有开源,所以只能截取部分代码进行讲解了,如果想交流大家可以评论区见。
目前Windows App SDK有一些BUG,在我使用的过程中主要发现使用WinRT的串口监听事件失效,已在github提了bug,回头应该能够修复,还有WinRT里的一些API只认UWP UI Api windows.UI开头的一些对象,还需要大家多使用多反馈,这样WASDK开发才能良性循环。
public async Task InitAsync()
{
// Target all Serial Devices present on the system
var deviceSelector = SerialDevice.GetDeviceSelector();
var myDevices = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(deviceSelector);
deviceWatcher = DeviceInformation.CreateWatcher(deviceSelector);
deviceWatcher.Added += new TypedEventHandler<DeviceWatcher, DeviceInformation>(this.OnDeviceAdded);
deviceWatcher.Removed += new TypedEventHandler<DeviceWatcher, DeviceInformationUpdate>(this.OnDeviceRemoved);
}
上面代码注册的事件,在目前1.1版本的WASDK不生效,官方已经标注为BUG,当然在UWP里就正常,UWP在有些时候还是挺靠谱的嘛。
通过这个上位机应用的开发,也是对WASDK和UWP相关技术的使用能熟练一些了,从WPF到UWP再到WASDK和MAUI,XAML相关的开发都是可继承的,开发方式很相似,对于技术的迁移来说也算是没什么障碍吧,经常会听到很多人说微软出了这么多技术,都学不动了什么的,其实大家掌握内涵,对于新技术的接受还是很快的。
感谢dino.c大佬的一个番茄钟,因为我的表盘其实就是抄他番茄钟的代码。
当然还要感谢超超,毕竟有些代码还是抄他的。
参考推荐文档如下
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI
这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub
我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain