Я здесь немного преувеличил и хотел бы получить совет о том, что делать.
В основном я хочу иметь возможность визуализировать и управлять серебристым светом внутри моего Приложение 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 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 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& callback); // Let the xap file call the application
};
Легче сказать, чем сделать. Я нашел следующие статьи Host Silverlight Contorl в C ++ и Обмен данными между хостом C ++ Silverlight и приложением Silverlight . Моя проблема с ними заключается в том, что предоставленный код, похоже, не работает при компиляции в VS2010, и они создают фактическое окно вместо элемента управления без окон. Кроме того, то, что происходит, не очень хорошо объяснено, и мне не хватает знаний о COM и ATL.
Я также нашел this , который, кажется, имеет более простой способ реализации xcpcontrolhost, чем в статьях выше.
Я нашел некоторую справочную информацию на msdn . Где ISilverlightViewer кажется мне весьма интересным для моих нужд. Я считаю, что для обеспечения безоконного управления мне, вероятно, придется реализовать что-то вроде IOleInPlaceSiteWindowless ?.
Тем не менее, я немного не в себе и не знаю, с чего начать. Я хотел бы спросить совета относительно того, с чего мне следует начать, и есть ли у вас какие-либо общие советы или опыт работы с чем-то вроде этого?
РЕДАКТИРОВАТЬ: Что-то, что также было бы интересно, хотя и довольно второстепенное, было бы, если бы такую реализацию можно было сделать независимой от платформы?
EDIT2: Я изменил код в "TestProject" из одной из статей выше. Я попытался удалить избыточный код и исправил его, чтобы он работал на VS2010 (согласно ответу ниже). Вы можете найти его здесь .
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::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);
}
}
А затем я запускаю обычный цикл обработчика сообщений Windows с помощью GetMessage, TranslateMessage и DispatchMessage.
Однако, по-прежнему все, что я получаю, это чернота. Что я делаю не так?
Кажется, я получаю E_FAIL от следующего вызова в "ActivateXcpControl":
hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, NULL, &m_rcPos);