Я пишу приложение, используя Qt Framework и компонент MS RDP. Что мне нужно, это постобработать изображение на рабочем столе удаленного компьютера, прежде чем представить его на экране.
Итак, основной вопрос: есть ли способ получить растровое изображение с удаленного рабочего стола из экземпляра MsRdpClientNotSafeForScripting? Другими словами, мне нужен прямой доступ к памяти, содержащей данные изображения рабочего стола удаленного компьютера.
Я использую ActiveQt для работы с компонентом RDP. Я пытался получить объект OLE из AxWidget
и нарисовать его на HBITMAP
(код в OnMakeScreenShotSlot()
). Но, во-первых, это неправильный способ получить растровое изображение экрана, и, в конце концов, этот метод дает неправильный результат: (прикрепленный код), когда мы нажимаем кнопку «Снимок экрана», появляется файл «screen.bmp», который содержит белый прямоугольник с текстом «Я жив!» в центре (но не изображение рабочего стола удаленного компьютера). «Я живой!» это значение ConnectedStatusText
свойство экземпляра IMsRdpClient.
Код прилагается. Рабочая среда: Windows 8, MSVC 2012, Qt 4.8.5, x86.
main.cpp:
#include <QApplication>
#include "containerwidget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ContainerWidget *w = new ContainerWidget();
w->show();
return a.exec();
}
containerwidget.h:
#ifndef CONTAINERWIDGET_H
#define CONTAINERWIDGET_H
#include <QWidget>
#include <QAxWidget>
#include <QAxObject>
#include <QPushButton>
class ContainerWidget : public QWidget
{
Q_OBJECT
QAxWidget *m_rdpWidget;
QPushButton *m_screenshotButton;
void initRdpWidget();
public:
ContainerWidget(QWidget *parent = 0);
~ContainerWidget();
public slots:
void OnMakeScreenshotSlot();
};
#endif // CONTAINERWIDGET_H
containerwidget.cpp:
#include "containerwidget.h"#include <QBoxLayout>
#include <QDebug>
#include <QUuid>
#include <comdef.h>
ContainerWidget::ContainerWidget(QWidget *parent) :
QWidget(parent)
{
initRdpWidget();
m_screenshotButton = new QPushButton("Make screenshot", this);
connect(m_screenshotButton, SIGNAL(clicked()), this, SLOT(OnMakeScreenshotSlot()));
QHBoxLayout *mainLayout = new QHBoxLayout(this);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->addWidget(m_rdpWidget);
mainLayout->addWidget(m_screenshotButton);
}
ContainerWidget::~ContainerWidget()
{
if (m_rdpWidget) {
m_rdpWidget->dynamicCall("Disconnect()");
}
}void ContainerWidget::initRdpWidget()
{
m_rdpWidget = new QAxWidget();
m_rdpWidget->setControl("{7cacbd7b-0d99-468f-ac33-22e495c0afe5}");
m_rdpWidget->dynamicCall("SetDesktopWidth(int)", 800);
m_rdpWidget->dynamicCall("SetDesktopHeight(int)", 600);
m_rdpWidget->dynamicCall("SetServer(QString)", "ip");
m_rdpWidget->dynamicCall("SetUserName(QString)", "user");
m_rdpWidget->dynamicCall("SetConnectedStatusText(QString)", "I'm alive!");
QAxObject *advancedSettings2 = m_rdpWidget->querySubObject("AdvancedSettings2");
if (advancedSettings2) {
advancedSettings2->dynamicCall("SetClearTextPassword(QString)", "password");
advancedSettings2->dynamicCall("SetAuthenticationLevel(int)", 2);
}
m_rdpWidget->dynamicCall("Connect()");
m_rdpWidget->setFixedSize(800, 600);
m_rdpWidget->setVisible(true);
}
void ContainerWidget::OnMakeScreenshotSlot()
{
if (m_rdpWidget != NULL) {
IOleObject *oleObj = NULL;
m_rdpWidget->queryInterface((QUuid)IID_IOleObject, (void **)&oleObj);
if (oleObj == NULL) {
qDebug() << "bad ole obj.";
return;
}
IViewObject2 *iviewObj2 = NULL;
HRESULT hres = oleObj->QueryInterface(IID_IViewObject2, (void **)&iviewObj2);
if (SUCCEEDED(hres)) {
SIZE picSize;
hres = iviewObj2->GetExtent(DVASPECT_CONTENT, -1, NULL, &picSize);
if (SUCCEEDED(hres)) {
HDC dc = GetDC(0);
SIZE adjustedSize;
adjustedSize.cx = MulDiv(picSize.cx, GetDeviceCaps(dc, LOGPIXELSX), 2540);
adjustedSize.cy = MulDiv(picSize.cy, GetDeviceCaps(dc, LOGPIXELSY), 2540);
ReleaseDC(0, dc);
RECT r;
SetRect(&r, 0, 0, adjustedSize.cx, adjustedSize.cy);
HDC tmpDC = GetDC(0);
HDC memDC = CreateCompatibleDC(tmpDC);
HBITMAP hBmp = CreateCompatibleBitmap(memDC, adjustedSize.cx, adjustedSize.cy);
HBITMAP oldBmp = (HBITMAP)SelectObject(memDC, hBmp);
OleDraw(oleObj, DVASPECT_CONTENT, memDC, &r);
QPixmap p = QPixmap::fromWinHBITMAP(hBmp);
p.save(QString("screen.bmp"));
SelectObject(memDC, oldBmp);
DeleteDC(memDC);
ReleaseDC(0, tmpDC);
} else {
qDebug() << "bad picSize.";
}
} else {
qDebug() << "bad iviewobj2.";
}
}
}
Что ж, похоже, что нет способа получить необработанные байты изображения из компонента MsTsc.
Других решений пока нет …