visual tutorial template microsoft libreria library active c++ silverlight com atl

tutorial - Alojamiento de Silverlight en C++



microsoft foundation (1)

Estoy un poco desconcertado y me gustaría recibir algunos consejos sobre cómo hacerlo.

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 en C ++ y Comunicación entre C ++ Silverlight Host y la aplicación Silverlight . Mi problema con estos son que el código proporcionado no parece funcionar cuando se compila en VS2010 y crean una ventana real en lugar de un control sin ventanas. Además, lo que sucede no está muy bien explicado y me faltan conocimientos de COM y ATL.

También encontré this que parece tener una forma más sencilla de implementar xcpcontrolhost que los artículos anteriores.

He encontrado alguna información de referencia en msdn . Donde ISilverlightViewer parece bastante interesante para mis necesidades. Para permitir un control sin ventanas, creo que probablemente tengo que implementar algo como IOleInPlaceSiteWindowless ?

Sin embargo, aquí estoy bastante por encima de mi cabeza y no estoy seguro de por dónde empezar. Me gustaría pedirle algunos consejos sobre dónde debería comenzar y si tiene 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. He intentado eliminar el código redundante y lo arreglé para que se ejecute en VS2010 (de acuerdo con la respuesta a continuación). Puedes encontrarlo here .

EDIT3:

He intentado implementar una clase XcpControlHost sin ventanas. He mirado el código en CAxHostWindow y he intentado recrearlo. La razón por la que no uso CAxHostWindow para crear un control sin ventanas es que no es compatible con alfa.

Parece que se compila bien, sin embargo, cuando llamo a DrawControl solo recupero un marco negro.

XcpContorlHost.h XcpControlHost.cpp

¿Alguna idea sobre lo que podría estar mal?

EDIT4: Estoy dando un paso atrás. Utilizo el código de "TestProject" Quiero modificar CreateXcpControl (HWND hWnd) para poder tomar hWnd == nullptr (sin ventanas) y usar OleDraw para dibujar el control en la memoria.

Entonces, lo que intenté hacer es simplemente pasar por alto la llamada a "AttachControl" y llamar directamente a "ActivateXcpControl". Y he reemplazado 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 }

Creo el XcpControlHost dentro 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 luego ejecuto el bucle habitual del manejador de mensajes de Windows con GetMessage, TranslateMessage y DispatchMessage.

Sin embargo, todavía todo lo que consigo es negrura. ¿Qué estoy haciendo mal?

Parece que obtengo E_FAIL de la siguiente llamada en "ActivateXcpControl":

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


He probado el proyecto de código disponible aquí: http://www.codeproject.com/KB/atl/Host_Silverlight_In_ATL.aspx en Visual Studio 2010. Esto es lo que se necesita para que funcione:

  • cárguelo bajo VS 2010 y conviértalo a VS 2010 (no importa los registros de backupgs, etc ...)
  • elimine el registro Post-Build Event ("$ (TargetPath)" / RegServer), solo se usa para el registro de componentes COM dentro del proyecto. También puede dejar ese evento y simplemente olvidarse del error si lo prefiere.
  • Tuve que hacer un pequeño cambio en XcpControlHost.cpp.

Aquí está el cambio:

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

Y funciona (estoy ejecutando Windows 7 con Silverlight 4).

Este es realmente el camino a seguir.

Sin embargo, una observación: en el ejemplo, el autor no usa el archivo oficial xcpctrl.idl disponible desde aquí: http://msdn.microsoft.com/en-us/library/cc296246(VS.95).aspx . En su lugar, redefine todas las interfaces y GUID, y esto no es necesario. Solo puede agregar xcpctrl.idl a Visual Studio 2010 y compilar, esto activará el compilador MIDL que creará los 3 archivos siguientes: xcpctrl_h.h, xcpctrl_i.c, xcpctrl_p.c. Una vez compilados, puedes agregarlos al proyecto.