c++ - 在 C++ 中托管 Silverlight

标签 c++ silverlight com atl

我有点不知所措,想要一些关于如何去做的建议。

基本上,我想做的是能够在我的 C++ 应用程序中渲染和控制 Silverlight。我想要一些东西:

class silverlight_host
{    
public: 
     // Prio 1
     silverlight_host(const std::string& filename); // Load a xap file       
     void draw(void* dest); // Draw with alpha to dest
     std::pair<size_t, size_t> get_size(); // Need to know required size of dest

     // Prio 2
     bool is_dirty() const; // Check for dirty rect since last call to draw
     void send_param(const std::string& param); // Send data to silverlight control or call functions. Alternative name maybe, call_function
     void set_size(size_t width, size_t height); // Set the size of drawing.  

     // Prio 3
     // Some more nice to have functions, although not as important as those above
     double get_desired_frame_rate(); // The desired frame rate which is specified in xap
     std::pair<size_t, size_t> get_desired_size(); // The desired size which is specified in xap
     void tick(); // Tick a synchronous timeline, disable internal asynchronous timer
     void set_param_callback(const std::function<void(const std::string&)>& callback); // Let the xap file call the application
};

说起来容易做起来难。我找到了以下文章Host Silverlight Contorl in C++Communication between C++ Silverlight Host and Silverlight Application .我的问题是,提供的代码在 VS2010 中编译时似乎不起作用,它们创建了一个实际的窗口而不是无窗口控件。发生的事情也没有得到很好的解释,而且我在 COM 和 ATL 知识方面有些缺乏。

我还找到了 this这似乎比上面的文章有更简单的方法来实现 xcpcontrolhost。

我在 msdn 上找到了一些引用信息.在哪里 ISilverlightViewer对我的需要来说似乎很有趣。为了允许无窗口控件,我相信我可能必须实现类似 IOleInPlaceSiteWindowless 的东西?.

但是,我在这里有点不知所措,甚至不确定从哪里开始。我想问一些关于我应该从哪里开始的建议,您是否有任何一般性的建议或经验?

编辑:如果可以使这样的实现独立于平台,也会很有趣,虽然相当次要?

EDIT2:我已经从上面的一篇文章中修改了“TestProject”中的代码。我试图删除冗余代码并修复它,以便它在 VS2010 上运行(根据下面的回答)。你可以找到它here .

EDIT3:

我试图实现一个无窗口的 XcpControlHost 类。我查看了 CAxHostWindow 中的代码并尝试重新创建它。我不使用 CAxHostWindow 创建无窗口控件的原因是它不支持 alpha。

它似乎编译得很好,但是当我调用 DrawControl 时,我只得到一个黑框。

XcpContorlHost.h XcpControlHost.cpp

有什么可能出错的想法吗?

EDIT4:我要后退一步。我使用“TestProject”中的代码我想修改 CreateXcpControl(HWND hWnd) 以便能够采用 hWnd == nullptr(无窗口)并使用 OleDraw 将控件绘制到内存。

我试图做的是简单地绕过对“AttachControl”的调用并直接调用“ActivateXcpControl”。我已经用硬编码值替换了 GetClientRect。

STDMETHODIMP XcpControlHost::AttachControl(IUnknown* pUnKnown, HWND hWnd)
{
    assert(hWnd == nullptr); 
    ReleaseAll();
    // Removed all hWnd related code
    return ActivateXcpControl(pUnKnown);
}

HRESULT XcpControlHost::ActivateXcpControl(IUnknown* pUnKnown) 
{
     // Lots of code
     // GetClientRect(&m_rcPos); // Remove this
     m_rcPos.top = 0;
     m_rcPos.left = 0;
     m_rcPos.right = 720;
     m_rcPos.bottom = 576;
     // Lots of code
}

我使用 CoInitialize 在线程内创建 XcpControlHost:

void run()
{
    struct co_init
    {
        co_init(){CoInitialize(nullptr);}
        ~co_init(){CoUninitialize();}
    } co;

    if(FAILED(CComObject<XcpControlHost>::CreateInstance(&host_)))
        throw std::exception("Failed to create XcpControlHost");

    if(FAILED(host_->CreateXcpControl()))
        throw std::exception("Failed to create XcpControl");

    while(GetMessage(&msg, 0, 0, 0))
    {  
        if(!is_running_)
            PostQuitMessage(0);

        if(msg.message == WM_USER + 1) // Sent from app
            OleDraw(host_->m_pUnKnown, DVASPECT_CONTENT, targetDC, 0);

        TranslateMessage(&msg);
        DispatchMessage(&msg); 
    }
}

然后我使用 GetMessage、TranslateMessage 和 DispatchMessage 运行通常的 Windows 消息处理程序循环。

但是,我得到的仍然是黑暗。我做错了什么?

我似乎从“ActivateXcpControl”中的以下调用中得到 E_FAIL:

hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, NULL, &m_rcPos);

最佳答案

我已经测试了这里可用的代码项目:http://www.codeproject.com/KB/atl/Host_Silverlight_In_ATL.aspx在 Visual Studio 2010 下。以下是使其工作所需的:

  • 在 VS 2010 下加载并将其转换为 VS 2010(不要关心备份日志等...)
  • 去掉注册后构建事件("$(TargetPath)"/RegServer),它只用于项目内部COM组件的注册。如果您愿意,您也可以让该事件发生并忘记错误。
  • 我必须在 XcpControlHost.cpp 中做一个小改动。

这里是变化:

HRESULT CXcpControlHost::CreateXcpControl(HWND hWnd) 
{
    AtlAxWinInit();
    CoInitialize(NULL); // add this line to initialize COM
    ... 
}

它可以工作(我正在运行带有 Silverlight 4 的 Windows 7)。

这确实是要走的路。

但有一点说明:在示例中,作者没有使用官方xcpctrl.idl可从此处获取文件:http://msdn.microsoft.com/en-us/library/cc296246(VS.95).aspx .相反,他重新定义了所有接口(interface)和 GUID,这不是必需的。您可以将 xcpctrl.idl 添加到 Visual Studio 2010 并编译,这将触发 MIDL 编译器,该编译器将创建以下 3 个文件:xcpctrl_h.h、xcpctrl_i.c、xcpctrl_p.c。编译完成后,您可以将它们添加到项目中。

关于c++ - 在 C++ 中托管 Silverlight,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4768619/

相关文章:

c++ - 将 double[,] 转换为 Variant*

c++ - 有模板复制构造函数时不生成默认构造函数

c++ - Qt "tcpserver->write(string)"

c++ - 动态分配内存

c++ - 错误 : not. exe 已停止工作 - 尝试构建 LLVM 时

c# - WP 以编程方式移动 ScrollViewer

wpf - EventAggregator,它是线程安全的吗?

带有代码高亮显示的 Silverlight 控件?

java - 如何通过 COM/native DLL 公开 Java?

c++ - 在 C++ 中访问 COM 接口(interface)的问题