Sono un po 'fuori di testa qui e vorrei qualche consiglio su come fare.Hosting Silverlight in C++
In linea di principio ciò che voglio fare è essere in grado di eseguire il rendering e il controllo di Silverlight all'interno dell'applicazione C++. Vorrei qualcosa come:
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
};
Più facile a dirsi che a farsi. Ho trovato i seguenti articoli Host Silverlight Contorl in C++ e Communication between C++ Silverlight Host and Silverlight Application. Il mio problema con questi è che il codice fornito non sembra funzionare quando compilato in VS2010 e creano una finestra effettiva invece di un controllo senza finestra. Inoltre, ciò che accade non è spiegato molto bene e mi manca un po 'di conoscenza di COM e ATL.
Ho anche trovato this che sembra avere un modo più semplice per implementare xcpcontrolhost rispetto agli articoli precedenti.
Ho trovato alcune informazioni di riferimento su msdn. Dove ISilverlightViewer sembra abbastanza interessante per le mie esigenze. Per consentire un controllo senza finestre credo che probabilmente dovrò implementare qualcosa come IOleInPlaceSiteWindowless?.
Tuttavia, sono un po 'sopra la mia testa e non so da dove iniziare. Vorrei chiedere qualche consiglio su dove dovrei iniziare e se hai qualche consiglio generale o esperienza con qualcosa del genere?
EDIT: Qualcosa che sarebbe anche interessante, anche se piuttosto secondario, sarebbe se tale implementazione potesse essere resa indipendente dalla piattaforma?
EDIT2: Ho modificato il codice in "TestProject" da uno degli articoli precedenti. Ho provato a rimuovere il codice ridondante e l'ho risolto in modo che venga eseguito su VS2010 (in base alla risposta di seguito). Lo puoi trovare here.
Edit3:
ho cercato di implementare una classe XcpControlHost senza finestre. Ho esaminato il codice in CAxHostWindow e ho provato a ricrearlo. Il motivo per cui non utilizzo CAxHostWindow per creare un controllo senza finestra è che non supporta l'alpha.
Sembra compilare bene, tuttavia quando chiamo DrawControl torno solo una cornice nera.
XcpContorlHost.h XcpControlHost.cpp
Tutte le idee su quello che potrebbe essere sbagliato?
EDIT4: Sto facendo un passo indietro. Uso il codice da "TestProject" Voglio modificare CreateXcpControl (HWND hWnd) per poter prendere hWnd == nullptr (senza finestre) e usare OleDraw per disegnare il controllo in memoria.
Quindi, ciò che ho cercato di fare è semplicemente bypassare la chiamata a "AttachControl" e chiamare direttamente "ActivateXcpControl". E ho sostituito GetClientRect con valori hardcoded.
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
}
ho creare il XcpControlHost all'interno di una discussione 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);
}
}
E poi ho eseguito il ciclo gestore di finestre messaggio al solito con GetMessage, TranslateMessage e DispatchMessage.
Tuttavia, tutto ciò che ottengo è l'oscurità. Che cosa sto facendo di sbagliato?
mi sembra di ottenere E_FAIL dal seguente chiamata in "ActivateXcpControl":
hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, NULL, &m_rcPos);
+1 per questo buon argomento. Ho anche bisogno di sapere questo ... come stavo cercando di fare queste cose: http://stackoverflow.com/questions/4744522/handle-to-silverlight-usercontrol ... e http://stackoverflow.com/questions/4758568/deploying-xbap-with-win32-dll – Nawaz
Quale versione di Silverlight? –
Il preferibilmente il più recente possibile. – ronag