2011-01-22 8 views
17

私はここで私の頭を少し上回り、行き先についていくつかのアドバイスをしたいと思います。SilverlightをC++でホストしています

基本的には、私の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の知識には多少欠けています。

また、上記の記事よりもxcpcontrolhostを実装する方法が簡単であると思われるthisが見つかりました。

msdnに関する参考情報があります。 ISilverlightViewerは私のニーズにとって非常に興味深いようです。ウィンドウレスの制御を可能にするために、おそらくIOleInPlaceSiteWindowlessのようなものを実装する必要があると私は信じています。

しかし、私はここで私の頭の上に少しですが、私はどこから始めてもわかりません。私はどこで始めるべきか、これについて何か一般的なアドバイスや経験があるかどうかについてアドバイスをしたいと思います。

EDIT:このような実装がプラットフォームに依存しないようにすることができれば、かなり興味深いものがあります。

EDIT2:上記のいずれかの記事から「TestProject」のコードを修正しました。私は冗長なコードを削除しようとし、VS2010上で実行されるように修正しました(以下の回答によると)。あなたはそれを見つけることができますhere

EDIT3:

私は窓のXcpControlHostクラスを実装しようとしています。私はCAxHostWindowのコードを見て、それを再作成しようとしました。ウィンドウレスコントロールを作成するためにCAxHostWindowを使用しない理由は、それがアルファをサポートしていないからです。

私は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を持つ通常のウィンドウメッセージハンドラループを実行します。

しかし、まだ私が得るのは黒さです。私は間違って何をしていますか?

私は「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 ... and http://stackoverflow.com/questions/4758568/deploying-xbap-with-win32-dl​​l – Nawaz

+0

Silverlightのどのバージョンですか? –

+0

可能な限り最新のもの。 – ronag

答えて

8

:ここでのVisual Studio 2010の下http://www.codeproject.com/KB/atl/Host_Silverlight_In_ATL.aspxはそれを動作させるために必要なものです:

  • VS 2010の下に負荷をし、VS 2010に変換(...など、backupgsログを気にしない)
  • 登録ビルド後のイベント( "$(TargetPathが)"/REGSERVERを)削除それは登録のためだけに使用されますプロジェクタ内部のCOMコンポーネントのまた、そのイベントを許可し、好きな場合はエラーを忘れることもできます。
  • 私はXcpControlHost.cppに小さな変更を加えなければなりませんでした。 (私はSilverlightの4でWindows 7を実行している)

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

    そして、それは動作します:ここで

は変化です。

これは実際に行く方法です。

ただし、このサンプルでは、​​著者はhttp://msdn.microsoft.com/en-us/library/cc296246(VS.95).aspxの公式xcpctrl.idlファイルを使用していません。代わりに、彼はすべてのインターフェイスとGUIDを再定義しますが、これは必要ありません。 Visual Studio 2010にxcpctrl.idlを追加してコンパイルするだけで、次の3つのファイルを作成するMIDLコンパイラがトリガーされます。xcpctrl_h.h、xcpctrl_i.c、xcpctrl_p.c。コンパイルしたら、プロジェクトに追加することができます。

+0

いい仕事です。あなたの提案に従って "TestProject"プロジェクトを修正したファイルへのリンクを追加しました。 – ronag

+0

この例の1つの問題は、キーボードメッセージをSilverlightホストコントロールに送信できないことです。これを回避するには? –

+0

@IslamYahiatene - 別の質問を投稿 –

関連する問題