Domanda

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.

È stato utile?

Soluzione

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top