如何订阅在 C++/CX 中的 Windows 运行时组件中引发的事件?

Mat*_*cey 2 c++ windows-8 windows-runtime windows-store-apps

我在引发事件的 Windows 运行时组件(用 C# 编写)中有一个类。
我无法弄清楚如何在引用该组件的 C++/CX 应用程序中订阅这些事件。

C# 代码(在 Windows 运行时组件中):

public sealed class Messenger {

    private EventRegistrationTokenTable<EventHandler<MessageReceivedEventArgs>> messageReceivedTokenTable;


public event EventHandler<MessageReceivedEventArgs> MessageReceived
{
    add
    {
        return EventRegistrationTokenTable<EventHandler<MessageReceivedEventArgs>>
            .GetOrCreateEventRegistrationTokenTable(ref this.messageReceivedTokenTable)
            .AddEventHandler(value);
    }

    remove
    {
        EventRegistrationTokenTable<EventHandler<MessageReceivedEventArgs>>
            .GetOrCreateEventRegistrationTokenTable(ref this.messageReceivedTokenTable)
            .RemoveEventHandler(value);
    }
}

internal void OnMessageReceived(string message, string location)
{
    EventHandler<MessageReceivedEventArgs> temp =
        EventRegistrationTokenTable<EventHandler<MessageReceivedEventArgs>>
        .GetOrCreateEventRegistrationTokenTable(ref this.messageReceivedTokenTable)
        .InvocationList;

    temp(this, new MessageReceivedEventArgs(message, location));
}

}
Run Code Online (Sandbox Code Playgroud)

MessageReceivedEventArgs 是:

public sealed class MessageReceivedEventArgs : object
{
    public MessageReceivedEventArgs(string message, string location)
    {
        this.Message = message;
        this.SenderLocation = location;
    }

    public string Message { get; set; }


    public string SenderLocation { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

请注意,根据MSDN,它来自对象而不是 EventArgs。

然后在 C++ 中:

msngr = ref new Messenger();

msngr->MessageReceived += ?????????
Run Code Online (Sandbox Code Playgroud)

之后又该何去何从+=,并在相关方法(和其他地方-在C#和/或C ++),这样我可以接受在C ++应用程序的消息?

我尝试了各种方法,遇到的各种编译器警告都无法为我指明解决方案。

我发现的所有使用用 C# 编写但在 C++ 应用程序中使用的 Windows 运行时组件的示例都是微不足道的,仅显示使用属性和调用方法。两者我都可以毫无问题地做到。我在订阅在 C# 中引发的 C++ 事件的示例之后。

Han*_*ant 5

有必要创建一个代理来使用这些类型。

这确实是您的问题,需要一个 COM 代理/存根来将您的 MessageReceivedEventArgs 类从 C# 编组到 C++/CX。是的,记录很差。我将尝试解释这个过程。开始使用此WinRT 示例,它演示了设置解决方案以获取所需代理的方法,并完全按照您的意愿执行操作。

起点是 ProxyStubForWinRTComponents_server 项目,这是一个声明共享类的 C# 项目。该项目的重要部分是 Post-Build 事件,它看起来像这样:

call "$(DevEnvDir)..\..\VC\vcvarsall.bat" x86
winmdidl /outdir:"$(ProjectDir)\" "$(TargetPath)"
Run Code Online (Sandbox Code Playgroud)

第一条语句设置运行 SDK 工具的环境。第二步运行 winmdidl.exe,这是一个完全未公开的构建工具,它将项目生成的 .winmd 文件反编译为 IDL 文件,然后对其进行编译。此构建步骤的输出是:

  • Microsoft.SDKSamples.Kitchen.idl - IDL 格式的反编译 .winmd 文件,用于生成其余文件
  • Microsoft.SDKSamples.Kitchen.h - 包含 C++ 格式的 C# 类型声明,适合 #included 在您的 C++/CX 项目中
  • Microsoft.SDKSamples.Kitchen_i.c - 包含 C# 类型的 GUID,用于构建代理
  • Microsoft.SDKSamples.Kitchen_p.c - 包含生成代理和存根的 goo
  • dlldata.c - 用于构建代理。

接下来看看 ProxyStubsForWinRTComponentsPS 项目,它是构建代理/存根 DLL 的项目。它使用由 winmdidl.exe 生成的文件,唯一添加的文件是声明从 DLL 导出的 .def 文件。COM 调用那些使用代理,您可以按原样使用该文件。最好按原样使用这个项目,只更改文件的名称,这样您就可以正确设置所有编译器和链接器设置。

毫无疑问,令人不快和很多方法都会出错。希望能帮助到你。