2011-01-22 7 views
17

Tôi hơi ngó qua đầu của tôi ở đây và muốn một số lời khuyên về cách thực hiện.Hosting Silverlight trong C++

Cơ bản những gì tôi muốn làm là có thể hiển thị và điều khiển Silverlight bên trong ứng dụng C++ của tôi. Tôi muốn một cái gì đó như:

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 
}; 

Nói dễ hơn làm. Tôi đã tìm thấy các bài viết sau đây Host Silverlight Contorl in C++Communication between C++ Silverlight Host and Silverlight Application. Vấn đề của tôi với những điều này là mã được cung cấp dường như không hoạt động khi được biên dịch trong VS2010 và chúng tạo ra một cửa sổ thực tế thay vì một điều khiển không cửa sổ. Ngoài ra những gì xảy ra không được giải thích rất rõ và tôi hơi thiếu kiến ​​thức về COM và ATL.

Tôi cũng đã tìm thấy this dường như có cách đơn giản hơn để triển khai xcpcontrolhost hơn các bài viết ở trên.

Tôi đã tìm thấy một số thông tin tham chiếu trên msdn. Trường hợp ISilverlightViewer có vẻ khá thú vị cho nhu cầu của tôi. Để cho phép một điều khiển không cửa sổ tôi tin rằng tôi có thể phải thực hiện một cái gì đó như IOleInPlaceSiteWindowless?

Tuy nhiên, tôi khá hơn một chút so với đầu của tôi ở đây và tôi không chắc chắn nên bắt đầu từ đâu. Tôi muốn hỏi một số lời khuyên về nơi tôi nên bắt đầu và nếu bạn có bất kỳ lời khuyên chung hoặc kinh nghiệm với một cái gì đó như thế này?

CHỈNH SỬA: Một cái gì đó cũng sẽ thú vị, mặc dù khá phụ, sẽ là nếu việc triển khai như vậy có thể được làm nền tảng độc lập không?

EDIT2: Tôi đã sửa đổi mã trong "TestProject" từ một trong các bài viết ở trên. Tôi đã cố gắng để loại bỏ mã dự phòng và cố định nó để nó chạy trên VS2010 (theo câu trả lời dưới đây). Bạn có thể tìm thấy nó here.

EDIT3:

Tôi đã cố gắng thực hiện một lớp XcpControlHost cửa sổ. Tôi đã nhìn vào mã trong CAxHostWindow và cố gắng tái tạo nó. Lý do tôi không sử dụng CAxHostWindow để tạo ra một điều khiển không cửa sổ là nó không hỗ trợ alpha.

Dường như biên dịch tốt, tuy nhiên khi tôi gọi DrawControl tôi chỉ lấy lại một khung màu đen.

XcpContorlHost.h XcpControlHost.cpp

Bất kỳ ý tưởng về những gì có thể là sai?

EDIT4: Tôi đang tiến hành một bước trở lại. Tôi sử dụng mã từ "TestProject" Tôi muốn sửa đổi CreateXcpControl (HWND hWnd) để có thể lấy hWnd == nullptr (không cửa sổ) và sử dụng OleDraw để vẽ điều khiển vào bộ nhớ.

Soo những gì tôi đã cố gắng làm là chỉ cần bỏ qua cuộc gọi đến "AttachControl" và gọi trực tiếp "ActivateXcpControl". Và tôi đã thay thế GetClientRect bằng các giá trị mã hóa cứng.

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 
} 

tôi tạo XcpControlHost bên a thread với 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); 
    } 
} 

Và sau đó tôi chạy các cửa sổ nhắn handler vòng lặp thông thường với GetMessage, TranslateMessage và DispatchMessage.

Tuy nhiên, tôi vẫn nhận được màu đen. Tôi đang làm gì sai?

tôi dường như để có được E_FAIL từ cuộc gọi sau đây trong "ActivateXcpControl":

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

+1 cho chủ đề hay này. Tôi cũng cần phải biết về điều này .. tôi đã cố gắng để làm những việc này: http://stackoverflow.com/questions/4744522/handle-to-silverlight-usercontrol ... và http://stackoverflow.com/questions/4758568/deploying-xbap-with-win32-dll – Nawaz

+0

Phiên bản Silverlight nào? –

+0

Tốt nhất có thể. – ronag

Trả lời

8

Tôi đã thử nghiệm dự án mã có sẵn ở đây: http://www.codeproject.com/KB/atl/Host_Silverlight_In_ATL.aspx dưới Visual Studio 2010. Dưới đây là những gì cần thiết để làm cho nó làm việc:

  • tải nó dưới VS 2010 và chuyển nó sang VS 2010 (không quan tâm đến backupgs bản ghi, vv ...)
  • loại bỏ các sự kiện đăng ký sau xây dựng ("$ (TargetPath)"/regserver) , nó chỉ được sử dụng để đăng ký của các thành phần COM bên trong projet. Bạn cũng có thể để sự kiện đó và quên đi lỗi nếu muốn.
  • Tôi phải thực hiện một thay đổi nhỏ trong XcpControlHost.cpp.

Đây là sự thay đổi:

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

Và nó hoạt động (Tôi đang chạy Windows 7 với Silverlight 4).

Đây thực sự là cách để đi.

Một nhận xét mặc dù: Trong mẫu, tác giả không sử dụng tệp xcpctrl.idl chính thức có sẵn tại đây: http://msdn.microsoft.com/en-us/library/cc296246(VS.95).aspx. Thay vào đó, ông định nghĩa lại tất cả các giao diện và GUID, và điều này là không cần thiết. Bạn chỉ có thể thêm xcpctrl.idl vào Visual Studio 2010 và biên dịch, điều này sẽ kích hoạt trình biên dịch MIDL sẽ tạo ra 3 tệp sau: xcpctrl_h.h, xcpctrl_i.c, xcpctrl_p.c. Khi chúng được biên soạn, bạn có thể thêm chúng vào dự án.

+0

Công việc tốt. Tôi đã thêm một liên kết đến một tập tin mà tôi đã sửa dự án "TestProject" theo đề xuất của bạn. – ronag

+0

Một vấn đề với ví dụ này là nó không thể gửi tin nhắn bàn phím đến điều khiển máy chủ Silverlight. Cách giải quyết vấn đề này? –

+0

@IslamYahiatene - Đăng câu hỏi khác –