windows C++-使用 C++/WinRT 创作 API(一)

这个系列中的 "投影” 不太好有准确的翻译,它的原文 是"projection",最开始我觉得可能翻译为 实现,但C++ 本身也有"实现(implementation )",这两个不同的词翻译为一个总觉得怪怪的。

本文展示了如何直接或间接使用 winrt::implements 基本结构来拓展创作 C++/WinRT API 。 在此上下文中,“创作”的同义词有“生成”或“实现” 。 介绍以下在 C++/WinRT 类型上实现 API 的情形(按此顺序)。

下面涉及 Windows 运行时组件,但其中的相关内容仅在 C++/WinRT 上下文中适用。

  • 你不是在创作一个 Windows 运行时类(运行时类);你只是想要实现一个或多个 Windows 运行时接口以便在应用内进行本地使用 。 例如, 你直接从 winrt::implements 派生并实现相关函数 ;
  • 你正在创作一个运行时类 。 你可能正在创作一个要从某个应用中使用的组件。 或者,你可能正在创作一个要从 XAML 用户接口 (UI) 使用的类型,在此情况下,你在同一个编译单元内实现和使用一个运行时类。 在这些情况下,你使用工具为你生成派生自 winrt::implements 的类 ;

在这两种情况下,实现 C++/WinRT API 的类型被称作“实现类型” 。请务必区分实现类型与投影类型的概念。 投影类型将在通过 C++/WinRT 使用 API 中进行介绍。

非创作运行时类

最简单的方案是,你的类型在实现 Windows 运行时接口,并且你将在同一个应用中使用此类型。 在这种情况下,你的类型不需要是运行时类;只是一个普通的 C++ 类。 例如,你可能会基于 CoreApplication 编写一个应用 。

如果你的类型被 XAML UI 引用,那么它确实必须是运行时类,即使它与 XAML 在同一个项目中,也不例外。 在这种情况下,请参阅若要创作要在 XAML UI 中引用的运行时类部分。

有关安装和使用 C++/WinRT Visual Studio 扩展 (VSIX) 和 NuGet 包。

在 Visual Studio 中,“Visual C++”>“Windows 通用”>核心应用 (C++/WinRT)”项目模板阐释了 CoreApplication 模式 。 该模式首先将 Windows::ApplicationModel::Core::IFrameworkViewSource 的实现传递给 CoreApplication::Run:

using namespace Windows::ApplicationModel::Core;
int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
    IFrameworkViewSource source = ...
    CoreApplication::Run(source);
}

// CoreApplication 使用接口来创建应用的第一个视图 。 
// 从概念上来说,IFrameworkViewSource 如下所示 。
struct IFrameworkViewSource : IInspectable
{
    IFrameworkView CreateView();
};

// 同样,从概念上来说,CoreApplication::Run 的实现执行此操作 。
void Run(IFrameworkViewSource viewSource) const
{
    IFrameworkView view = viewSource.CreateView();
    ...
}

// 因此,作为开发人员,应实现 IFrameworkViewSource 接口 。 
// C++/WinRT 具有基结构模板 winrt::implements,从而可以很容易实现一个或多个接口,
// 而不必求助于 COM 样式的编程 。 你可以从 implements 直接派生类型,然后实现接口的函数 。 
// 操作方法如下。
// App.cpp
...
struct App : implements<App, IFrameworkViewSource>
{
    IFrameworkView CreateView()
    {
        return ...
    }
}
...

// 这将由 IFrameworkViewSource 处理 。 下一步是返回实现 IFrameworkView 接口的对象 。 
// 你也可以选择在 App 上实现该接口 。 
// 下一个代码示例表示一个小型应用,该应用将至少会在桌面上运行一个窗口。
// App.cpp
...
struct App : implements<App, IFrameworkViewSource, IFrameworkView>
{
    IFrameworkView CreateView()
    {
        return *this;
    }

    void Initialize(CoreApplicationView const &) {}

    void Load(hstring const&) {}

    void Run()
    {
        CoreWindow window = CoreWindow::GetForCurrentThread();
        window.Activate();

        CoreDispatcher dispatcher = window.Dispatcher();
        dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessUntilQuit);
    }

    void SetWindow(CoreWindow const & window)
    {
        // Prepare app visuals here
    }

    void Uninitialize() {}
};
...

// 由于 App 类型是 IFrameworkViewSource,因此可以直接传递一个到 Run。
using namespace Windows::ApplicationModel::Core;
int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
    CoreApplication::Run(winrt::make<App>());
}
在 winrt 组件中创作一个运行时类

如果你的类型打包在 Windows 运行时组件中,以便从另一个二进制文件(另一个二进制文件通常是应用程序)使用它,则你的类型必须是运行时类。 在 Microsoft 接口定义语言 (IDL) (.idl) 文件中声明运行时类(请参阅将运行时类重构到 Midl 文件 (.idl) 中)。

每个 IDL 文件生成一个 .winmd 文件,Visual Studio 会将所有这些合并为一个与根命名空间同名的文件。 最后生成的 .winmd 文件将是组件使用者将参考的文件。

下面是一个在 IDL 文件中声明运行时类的示例。

// MyRuntimeClass.idl
namespace MyProject
{
    runtimeclass MyRuntimeClass
    {
        // Declaring a constructor (or constructors) in the IDL causes the runtime class to be
        // activatable from outside the compilation unit.
        MyRuntimeClass();
        String Name;
    }
}

// 此 IDL 声明一个 Windows 运行时类。 
// 运行时类是一个可通过现代 COM 接口进行激活和使用(通常跨可执行文件)的类型。 
// 当你向项目和生成中添加 IDL 文件时,C++/WinRT 工具链(midl.exe 和 cppwinrt.exe)将
// 会为你生成一个实现类型。 

// 对于上面的示例 IDL,在名为 \MyProject\MyProject\Generated Files\sources\MyRuntimeClass.h // 和 MyRuntimeClass.cpp 的源代码文件中,实现类型是一个名为 
// winrt::MyProject::implementation::MyRuntimeClass 的 C++ 结构存根 。
// 该实现类型如下所示。
// MyRuntimeClass.h
...
namespace winrt::MyProject::implementation
{
    struct MyRuntimeClass : MyRuntimeClassT<MyRuntimeClass>
    {
        MyRuntimeClass() = default;

        winrt::hstring Name();
        void Name(winrt::hstring const& value);
    };
}

// winrt::MyProject::factory_implementation::MyRuntimeClass is here, too.

// 请注意所使用的 F 边界多态模式(MyRuntimeClass 使用自身作为其基类 
// MyRuntimeClassT 的模板参数)。 这也称为奇异递归模板模式 (CRTP)。 
// 如果你向上查看继承链,你就会发现 MyRuntimeClass_base 。

// 可以使用 Windows 实现库 (WIL)简化简单属性的实现。 操作步骤如下:

// MyRuntimeClass.h
...
namespace winrt::MyProject::implementation
{
    struct MyRuntimeClass : MyRuntimeClassT<MyRuntimeClass>
    {
        MyRuntimeClass() = default;

        wil::single_threaded_rw_property<winrt::hstring> Name;
    };
}

template <typename D, typename... I>
struct MyRuntimeClass_base : implements<D, MyProject::IMyRuntimeClass, I...>

因此,在此情况中,继承层次结构的根同样是 winrt::implements 基结构模板 。 

  • 22
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值