2011-01-22 2 views
17

Я немного нахожусь здесь, и мне хотелось бы посоветовать, как это сделать.Хостинг Silverlight в C++

В основном я хочу, чтобы визуализировать и контролировать silverlight внутри моего приложения на C++. Я бы хотел:

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?.

Однако я совсем немного над головой, и я не знаю, с чего начать. Я хотел бы задать несколько советов относительно того, где я должен начать, и если у вас есть общие советы или опыт с чем-то подобным?

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 
} 

Я создаю 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.

Однако все же я получаю черноту. Что я делаю не так?

я, кажется, получают E_FAIL из следующего вызова в «ActivateXcpControl»:

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/deploying-xbap-with-win32-dll – Nawaz

+0

Какая версия Silverlight? –

+0

Предпочтительно последнее возможно. – ronag

ответ

8

Я протестировал проект код доступен здесь: http://www.codeproject.com/KB/atl/Host_Silverlight_In_ATL.aspx под Visual Studio 2010. Вот то, что нужно, чтобы сделать его работу:

  • нагрузки под VS 2010 и преобразовать его в VS 2010 (не заботятся о backupgs журналах, и т.д. ...)
  • удалить регистрацию после сборки событие ("$ (TargetPath)"/RegServer) , он используется только для регистрации 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. После их компиляции вы можете добавить их в проект.

+0

Хорошая работа. Я добавил ссылку на файл, где я исправил проект «TestProject» в соответствии с вашим предложением. – ronag

+0

Одна из проблем с этим примером заключается в том, что он не может отправлять сообщения клавиатуры в элемент управления Silverlight. Как это решить? –

+0

@IslamYahiatene - Напишите еще один вопрос –

Смежные вопросы