سؤال

The Background (Or, look how far I've gone on my own!)

I'm starting from the Windows 8 Media Extension Sample. I'm using the grayscale example as a starting point to learn how to pass values from managed code into a COM object, and how to pass values from my COM object back to managed code. In my IDL file, I've got a GrayscaleEffect class (taken exactly from the example) and a custom interface that should let me query a string over in the c# world.

The IDL file:

namespace GrayscaleTransform
{
    [version(NTDDI_WIN8), uuid(553B5684-4C22-4D21-8638-1E7D86D84F10)]
    interface MyInterface : IInspectable {
        HRESULT GetMsg([out] HSTRING *message);
    }

    [version(NTDDI_WIN8)]
    runtimeclass GrayscaleEffect {
        interface Windows.Media.IMediaExtension;
        interface MyInterface;
    }
}

My GrayscaleEffect class implementation implements GetMsg to return the string "Woozle"

The relevant c#:

cap = new MediaCapture();
await cap.InitializeAsync();

previewElement1.Source = cap;
await cap.StartPreviewAsync();

PropertySet props = new PropertySet();
await cap.AddEffectAsync(
    Windows.Media.Capture.MediaStreamType.VideoPreview,
    "GrayscaleTransform.GrayscaleEffect",
    props);

if (this.props.ContainsKey("ref"))
{
    var augGui = (GrayscaleTransform.MyInterface)this.props["ref"];
    string message;
    augGui.GetMsg(out message);
}

After the call to GetMsg, I can see that message contains the string "Woozle" just like I expect - Excellent!

The Problem

Now I want to do something a little bit fancier. Instead of a method that lets me pass a string from COM to C#, I want to implement a method that lets me pass a delegate from C# to COM. I'd like to get the MFT class to call this method every 10th video frame or something - that part's not important. I want my interface to have a method called SubscribeEvent that takes a delegate as a parameter. For now, it can be a void delegate that takes no arguments.

This page leads me to believe that I should be able to declare a WinRT delegate over in the COM world and be able to pass a delegate of the same type from C# (see the 3rd item from the end). Cool - seems easy. My best try so far has been something like this in the idl:

delegate void CallbackMethod();

[version(NTDDI_WIN8), uuid(553B5684-4C22-4D21-8638-1E7D86D84F10)]
interface MyInterface : IInspectable {
    HRESULT Subscribe(CallbackMethod cb);
}

Unfortunately this results in an error - seems to be related to the declaration of the delegate CallbackMethod:

error MIDL9008: internal compiler problem - See documentation for suggestions on how to find a workaround.

Edit This one is obvious. That syntax is a C++/cx thing. Upon closer inspection, I don't have the C++/CX extensions turned on. This is a WRL project which means it's regular flavor c++ with template magic.

I also tried to wire up an event by implementing the IConnectionPoint interface, but when I include OCIdl.h I get a compile error that desktop components cannot be compiled for ARM.

The Question Am I barking up the wrong tree here? Should I be making my GrayscaleEffect class be a WinRT runtime class using C++/CX? Maybe we're venturing into "New question" territory here, but when I try to implement IMFTransform with a WinRT class in C++/CX, I get

error C2811: 'GrayscaleRT::Class1' : cannot inherit from 'IMFTransform', a ref class can only inherit from a ref class or interface class

A better question: How about this: Can I pass a delegate here at all? I fell like I ought to be able to, if only I knew the magic combination of WRL templates to make it work.

هل كانت مفيدة؟

المحلول

It looks like this is the answer. In WRL, you declare an event in your idl like this:

[uuid(3FBED04F-EFA7-4D92-B04D-59BD8B1B055E), version(NTDDI_WIN8)]
delegate HRESULT WhateverEvent();

See the To add an event that fires when a prime number is calculated section

My problem was that I initially didn't understand that I wasn't using c++/cx. I was using regular c++ with WRL which is a template library similar to ATL that makes WinRT programming easier and doesn't use non-standard language extensions.

Once I understood that, it was relatively easy to find an example of an event handler using WRL

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top