2011-01-22 40 views
17

我在這裏有點頭痛,想要提供一些關於如何去做的建議。在C++中託管Silverlight

基本上我想要做的是能夠呈現和控制我的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

任何想法可能是什麼問題?

編輯4:我退後一步。我使用「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 
} 

我創建XcpControlHost一個線程中使用的CoInitialize:

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通常窗口消息處理循環。

但是,我仍然得到的是黑暗。我究竟做錯了什麼?

我似乎從「ActivateXcpControl」下面的調用獲取E_FAIL:

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

+1這個好主題。我也需要知道這個..因爲我試圖做這些事情:http://stackoverflow.com/questions/4744522/handle-to-silverlight-usercontrol ...和http://stackoverflow.com/questions/4758568 /部署-xbap -with-win32-dl​​l – Nawaz 2011-01-22 15:20:41

+0

哪個版本的Silverlight? – 2011-01-22 17:02:33

回答

8

我已經測試可用的代碼項目位置:http://www.codeproject.com/KB/atl/Host_Silverlight_In_ATL.aspx在Visual Studio 2010中這是使它工作所需的內容:

  • 加載VS 2010下並將其轉換爲VS 2010(不關心backupgs日誌等)
  • 刪除註冊的生成後事件( 「$(TARGETPATH)」/ RegServer添加) ,它只用於註冊projet中的COM組件。如果您願意,您也可以讓該事件並忘記錯誤。
  • 我不得不在XcpControlHost.cpp中做一些小改動。

這裏的變化:

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

和它的作品(我運行Windows 7的Silverlight 4)。

這真的是要走的路。

雖然有一點注意:在示例中,作者不使用官方xcpctrl.idl文件可從此處獲得:http://msdn.microsoft.com/en-us/library/cc296246(VS.95).aspx。相反,他重新定義了所有接口和GUID,這不是必需的。您可以將xcpctrl.idl添加到Visual Studio 2010並編譯,這將觸發MIDL編譯器,該編譯器將創建以下3個文件:xcpctrl_h.h,xcpctrl_i.c,xcpctrl_p.c。編譯完成後,可以將它們添加到項目中。