在非 UWP 应用程序中使用 Windows 混合现实
Using Windows Mixed Reality in non-UWP application
我正在维护一个 C# WPF 应用程序,我想向其添加 Windows 混合现实支持。
将应用程序移植到 UWP 可能不是一个好主意,因为该应用程序支持许多其他 API 没有 UWP 变体的应用程序。例如 Oculus、OSVR 和 OpenVR(Vive) 支持。不过,我没有足够的 UWP 经验可以肯定。
那么,是否可以在非 UWP 应用程序中使用混合现实 UWP APIs?或者也许将中间件 API 移植到 UWP 并不那么可怕?
遗憾的是,混合现实 API 全部内置于 UWP 平台,对于 运行 MR,它需要在 UWP 应用程序中。
唯一的另一种方法是将项目构建为 Steam VR 应用程序,但我认为这与您想要实现的目标不兼容。
我最好的建议是尽量使您的项目成为 cross-platform。将所有逻辑放在 Netcore / PCL 项目中,并在单独的项目中为 WPF 和 UWP 设置两个不同的 UI 层。
是的,可以在任何非 UWP 应用程序中使用 UWP API,因为所有 UWP API 实际上都是 COM。我通常更喜欢使用 C++/WinRT,但它在 C++17 语言中有限制。
如果您无法接受该限制,您可以使用经典的 COM,例如
Microsoft::WRL::ComPtr<ABI::Windows::UI::Input::Spatial::ISpatialInteractionManagerStatics> interactionManagerStatic;
Windows::Foundation::GetActivationFactory(
Microsoft::WRL::Wrappers::HStringReference(InterfaceName_Windows_UI_Input_Spatial_ISpatialInteractionManagerStatics).Get(),
&interactionManagerStatic);
Microsoft::WRL::ComPtr<ABI::Windows::UI::Input::Spatial::ISpatialInteractionManager> interactionManager;
if (FAILED(interactionManagerStatic->GetForCurrentView(interactionManager.GetAddressOf())))
{
return -1;
}
如果您想从您的 WPF/winforms 项目访问它,您也可以在 c# 中实现该接口。要使用下面的代码,请添加对 Microsoft.Windows.SDK.Contracts nuget 包的引用,例如:https://www.nuget.org/packages/Microsoft.Windows.SDK.Contracts/10.0.18362.2002-preview
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using Windows.UI.Input.Spatial;
namespace UWPInterop
{
//MIDL_INTERFACE("5C4EE536-6A98-4B86-A170-587013D6FD4B")
//ISpatialInteractionManagerInterop : public IInspectable
//{
//public:
// virtual HRESULT STDMETHODCALLTYPE GetForWindow(
// /* [in] */ __RPC__in HWND window,
// /* [in] */ __RPC__in REFIID riid,
// /* [iid_is][retval][out] */ __RPC__deref_out_opt void** spatialInteractionManager) = 0;
//};
[System.Runtime.InteropServices.Guid("5C4EE536-6A98-4B86-A170-587013D6FD4B")]
[System.Runtime.InteropServices.InterfaceType(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIInspectable)]
interface ISpatialInteractionManagerInterop
{
SpatialInteractionManager GetForWindow(IntPtr Window, [System.Runtime.InteropServices.In] ref Guid riid);
}
//Helper to initialize SpatialInteractionManager
public static class SpatialInteractionManagerInterop
{
public static SpatialInteractionManager GetForWindow(IntPtr hWnd)
{
ISpatialInteractionManagerInterop spatialInteractionManagerInterop = (ISpatialInteractionManagerInterop)WindowsRuntimeMarshal.GetActivationFactory(typeof(SpatialInteractionManager));
Guid guid = typeof(SpatialInteractionManager).GUID;
return spatialInteractionManagerInterop.GetForWindow(hWnd, ref guid);
}
}
}
我正在维护一个 C# WPF 应用程序,我想向其添加 Windows 混合现实支持。
将应用程序移植到 UWP 可能不是一个好主意,因为该应用程序支持许多其他 API 没有 UWP 变体的应用程序。例如 Oculus、OSVR 和 OpenVR(Vive) 支持。不过,我没有足够的 UWP 经验可以肯定。
那么,是否可以在非 UWP 应用程序中使用混合现实 UWP APIs?或者也许将中间件 API 移植到 UWP 并不那么可怕?
遗憾的是,混合现实 API 全部内置于 UWP 平台,对于 运行 MR,它需要在 UWP 应用程序中。 唯一的另一种方法是将项目构建为 Steam VR 应用程序,但我认为这与您想要实现的目标不兼容。
我最好的建议是尽量使您的项目成为 cross-platform。将所有逻辑放在 Netcore / PCL 项目中,并在单独的项目中为 WPF 和 UWP 设置两个不同的 UI 层。
是的,可以在任何非 UWP 应用程序中使用 UWP API,因为所有 UWP API 实际上都是 COM。我通常更喜欢使用 C++/WinRT,但它在 C++17 语言中有限制。
如果您无法接受该限制,您可以使用经典的 COM,例如
Microsoft::WRL::ComPtr<ABI::Windows::UI::Input::Spatial::ISpatialInteractionManagerStatics> interactionManagerStatic;
Windows::Foundation::GetActivationFactory(
Microsoft::WRL::Wrappers::HStringReference(InterfaceName_Windows_UI_Input_Spatial_ISpatialInteractionManagerStatics).Get(),
&interactionManagerStatic);
Microsoft::WRL::ComPtr<ABI::Windows::UI::Input::Spatial::ISpatialInteractionManager> interactionManager;
if (FAILED(interactionManagerStatic->GetForCurrentView(interactionManager.GetAddressOf())))
{
return -1;
}
如果您想从您的 WPF/winforms 项目访问它,您也可以在 c# 中实现该接口。要使用下面的代码,请添加对 Microsoft.Windows.SDK.Contracts nuget 包的引用,例如:https://www.nuget.org/packages/Microsoft.Windows.SDK.Contracts/10.0.18362.2002-preview
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using Windows.UI.Input.Spatial;
namespace UWPInterop
{
//MIDL_INTERFACE("5C4EE536-6A98-4B86-A170-587013D6FD4B")
//ISpatialInteractionManagerInterop : public IInspectable
//{
//public:
// virtual HRESULT STDMETHODCALLTYPE GetForWindow(
// /* [in] */ __RPC__in HWND window,
// /* [in] */ __RPC__in REFIID riid,
// /* [iid_is][retval][out] */ __RPC__deref_out_opt void** spatialInteractionManager) = 0;
//};
[System.Runtime.InteropServices.Guid("5C4EE536-6A98-4B86-A170-587013D6FD4B")]
[System.Runtime.InteropServices.InterfaceType(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIInspectable)]
interface ISpatialInteractionManagerInterop
{
SpatialInteractionManager GetForWindow(IntPtr Window, [System.Runtime.InteropServices.In] ref Guid riid);
}
//Helper to initialize SpatialInteractionManager
public static class SpatialInteractionManagerInterop
{
public static SpatialInteractionManager GetForWindow(IntPtr hWnd)
{
ISpatialInteractionManagerInterop spatialInteractionManagerInterop = (ISpatialInteractionManagerInterop)WindowsRuntimeMarshal.GetActivationFactory(typeof(SpatialInteractionManager));
Guid guid = typeof(SpatialInteractionManager).GUID;
return spatialInteractionManagerInterop.GetForWindow(hWnd, ref guid);
}
}
}