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

时间:2013-02-02 23:53:02

标签: 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));
}

}

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; }
}

请注意,根据MSDN,它从对象而不是EventArgs下降。

然后在C ++中:

msngr = ref new Messenger();

msngr->MessageReceived += ?????????

+=之后以及相关方法(以及其他任何地方 - 在C#和/或C ++中)应该怎样才能在C ++应用程序中接收消息?

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

我发现使用用C#编写但在C ++应用程序中使用的Windows运行时组件的所有示例都很简单,只显示使用属性和调用方法。我可以毫无问题地做到这两点。我是在C#中使用C#订阅一个事件的例子。

3 个答案:

答案 0 :(得分:4)

  

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

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

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

call "$(DevEnvDir)..\..\VC\vcvarsall.bat" x86
winmdidl /outdir:"$(ProjectDir)\" "$(TargetPath)"

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

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

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

毫无疑问,不愉快且有很多方法可以解决这个问题。希望它有所帮助。

答案 1 :(得分:0)

假设您在C ++ ref类中编写此代码,假设使用CPPClass,您的代码将如下所示:

CPPClass::MyEventHandler(Platform::Object^ obj, MessageReceivedEventArgs^ args)
{
    // handler code
}


CPPClass::SomeMethod()
{
    msngr = ref new Messenger(this->SpecifedServer->Text);
    msngr->MessageReceived += ref new EventHandler<MessageReceivedEventArgs^>(this, &CPPClass::MyEventHandler);
}

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

顺便说一句,下面是一个类似的示例代码,对我来说很合适:

在C#中定义类和事件:

namespace WindowsRuntimeComponent3
{
    public sealed class MyEventsArgs
    {
    }

    public sealed class Class1
    {
        public Class1()
        {
        }

        public event EventHandler<MyEventsArgs> MyEvent;
    }
}

在C ++中使用事件:

App::App()
{
    InitializeComponent();
    Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending);

    auto obj = ref new WindowsRuntimeComponent3::Class1();
    obj->MyEvent += ref new EventHandler<WindowsRuntimeComponent3::MyEventsArgs^>(this, &App::MyEventHandler);
}

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

答案 2 :(得分:0)

此方案的官方文档可在MSDN上找到:Raising Events in Windows Runtime Components