Estoy un poco loco y quisiera recibir algunos consejos sobre cómo hacerlo.Hosting Silverlight en C++
Básicamente lo que quiero hacer es poder renderizar y controlar Silverlight dentro de mi aplicación C++. Me gustaría algo como:
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
};
Es más fácil decirlo que hacerlo. He encontrado los siguientes artículos Host Silverlight Contorl in C++ y Communication between C++ Silverlight Host and Silverlight Application. Mi problema con estos es que el código provisto no parece funcionar cuando se compila en VS2010 y crean una ventana real en lugar de un control sin ventana. Además, lo que sucede no está muy bien explicado y me falta cierto conocimiento de COM y ATL.
También encontré this que parece tener una forma más simple de implementar el xcpcontrolhost que los artículos anteriores.
He encontrado información de referencia en msdn. Donde ISilverlightViewer parece bastante interesante para mis necesidades. Para permitir un control sin ventanas, creo que probablemente tenga que implementar algo como IOleInPlaceSiteWindowless?.
Sin embargo, estoy un poco sobre mi cabeza aquí y no estoy seguro de por dónde empezar. Me gustaría pedir algunos consejos sobre dónde debo comenzar y si tienes algún consejo general o experiencia con algo como esto.
EDITAR: ¿Algo que también sería interesante, aunque bastante secundario, sería si tal implementación pudiera hacerse independiente de la plataforma?
EDIT2: He modificado el código en "TestProject" de uno de los artículos anteriores. Intenté eliminar el código redundante y lo corrigí para que funcione en VS2010 (según la respuesta a continuación). Puede encontrarlo here.
Edit3:
he tratado de implementar una clase XcpControlHost sin ventanas. Miré el código en CAxHostWindow e intenté volver a crearlo. La razón por la que no uso CAxHostWindow para crear un control sin ventana es que no admite alfa.
Parece compilar bien, sin embargo, cuando llamo a DrawControl solo obtengo un marco negro.
XcpContorlHost.h XcpControlHost.cpp
Alguna idea de lo que podría estar mal?
EDIT4: Estoy dando un paso atrás. Uso el código de "TestProject" Deseo modificar CreateXcpControl (HWND hWnd) para poder tomar hWnd == nullptr (sin ventana) y usar OleDraw para dibujar el control en la memoria.
Soo lo que traté de hacer es simplemente omitir la llamada a "AttachControl" y llamar directamente a "ActivateXcpControl". Y reemplacé GetClientRect por valores codificados.
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
}
Crío XcpControlHost el interior de un hilo con 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);
}
}
Y entonces corro el mensaje de ventanas bucle habitual manejador con GetMessage, TranslateMessage y DispatchMessage.
Sin embargo, todavía todo lo que obtengo es negrura. ¿Qué estoy haciendo mal?
Me parece conseguir E_FAIL de la siguiente llamada en "ActivateXcpControl":
hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, NULL, &m_rcPos);
+1 para este buen tema. También necesito saber sobre esto ... cuando intentaba hacer estas cosas: http://stackoverflow.com/questions/4744522/handle-to-silverlight-usercontrol ... y http://stackoverflow.com/questions/4758568/deploying-xbap-with-win32-dll – Nawaz
¿Qué versión de Silverlight? –
Lo más preferiblemente posible. – ronag