2012-10-02 17 views
1

当我使用WRL创建一个winrt组件时,问题是我只能使用ABI::Windows::xxx命名空间,并且我无法在WRL中使用Windows::UI::Xaml::Media::Imaging命名空间。如何使用WRL返回内置winrt组件?

然后,如何创建一个内置的winrt组件作为返回值?

// idl 
import "inspectable.idl"; 
import "Windows.Foundation.idl"; 
import "Windows.UI.Xaml.Media.Imaging.idl"; 

namespace Decoder 
{ 
    interface IPhotoDecoder; 
    runtimeclass PhotoDecoder; 

    interface IPhotoDecoder : IInspectable 
    { 
     HRESULT Decode([in] int width, [in] int height, [out, retval] Windows.UI.Xaml.Media.Imaging.BitmapImage **ppBitmapImage); 
    } 

    [version(COMPONENT_VERSION), activatable(COMPONENT_VERSION)] 
    runtimeclass PhotoDecoder 
    { 
     [default] interface IPhotoDecoder; 
    } 
} 

// cpp 
using namespace Microsoft::WRL; 
using namespace Windows::Foundation; 
using namespace ABI::Windows::UI::Xaml::Media::Imaging; 
namespace ABI 
{ 
    namespace Decoder 
    { 
     class PhotoDecoder: public RuntimeClass<IPhotoDecoder> 
     { 
      InspectableClass(L"Decoder.PhotoDecoder", BaseTrust) 

      public: 
      PhotoDecoder() 
      { 
      } 

      HRESULT __stdcall Decode(_In_ int width, _In_ int height, _Out_ IBitmapImage **ppBitmapImage) 
      { 
       // How to create Windows.UI.Xaml.Media.Imaging.BitmapImage without using Windows::UI::Xaml::Media::Imaging 
      } 

     }; 

     ActivatableClass(PhotoDecoder); 
    } 
} 

回答

5

有两套命名空间:

  • 那些植根于全局命名空间(如Windows::Foundation
  • 那些植根于ABI命名空间(如ABI::Windows::Foundation

的每个内容都是“相同的”。例如,Windows::Foundation::IUriRuntimeClass命名与ABI::Windows::Foundation::IUriRuntimeClass相同的接口。

那么,为什么有两组命名空间?全局命名空间中的命名空间被保留供C++/CX使用:它在这些命名空间中生成运行时类的投影。当您使用WRL时,您将始终使用名称空间中的名称空间(它们是“未投影的”名称,即它们正是ABI层中存在的名称空间)。

运行时类以两种方式之一被实例化(“激活”)。如果该类型是默认可构造的,则可以通过调用RoActivateInstance来构造该默认类型。如果某个类型声明了其他构造函数,则可以通过调用RoGetActivationFactory来获取运行时类型的激活工厂来调用这些构造函数。举个例子,你可以默认构造BitmapImage像这样:

using namespace Microsoft::WRL; 
using namespace Microsoft::WRL::Wrappers; 

using namespace ABI::Windows::UI::Xaml::Media::Imaging; 

HStringReference classId(RuntimeClass_Windows_UI_Xaml_Media_Imaging_BitmapImage); 

ComPtr<IInspectable> inspectable; 
if (FAILED(RoActivateInstance(classId.Get(), inspectable.GetAddressOf()))) 
{ 
    // Handle failure 
} 

ComPtr<IBitmapImage> bitmapImage; 
if (FAILED(inspectable.As(&bitmapImage))) 
{ 
    // Handle failure 
} 

WRL还具有实用的功能模板,Windows::Foundation::ActivateInstance,这两个调用RoActivateInstance并执行QueryInterface期望的目标接口:

using namespace Windows::Foundation; 

ComPtr<IBitmapImage> bitmapImage; 
if (FAILED(ActivateInstance(classId.Get(), bitmapImage.GetAddressOf()))) 
{ 
    // Handle failure 
} 
+0

非常感谢,但是当从UI线程创建的另一个线程调用ActivateInstance时,它将返回'RPC_E_WRONG_THREAD',并且无法创建实例。但我也尝试从不同线程调用'CreateStreamOverRandomAccessStream',我认为它同样会创建一个COM对象,但它可以很好地工作。你知道为什么吗? – user1713871