我正在使用Qt Framework和MS RDP组件编写应用程序。我需要的是对远程计算机的桌面图像进行后期处理,然后再在屏幕上进行显示。
因此,主要问题是:有什么方法可以从MsRdpClientNotSafeForScripting实例中获取远程桌面图片位图?换句话说,我需要直接访问包含远程计算机的桌面图像数据的内存。

我正在使用ActiveQt与RDP组件一起使用。我试图从AxWidget获取OLE对象并将其绘制在HBITMAPOnMakeScreenShotSlot()中的代码)上。但是,首先,获取屏幕位图的方法是错误的,而且,此方法毕竟会产生错误的结果:(附加的代码)当我们按下“屏幕截图”按钮时,将出现文件“ screen.bmp”,其中包含文字为“我还活着!”的白色矩形位于中心(但不是远程计算机桌面的图像)。 “我还活着!”是IMsRdpClient实例的ConnectedStatusText属性的值。

附带代码。工作环境: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组件获取原始图像字节。

关于c++ - 有什么方法可以从MS RDP组件(AxMSTSCLib)获取桌面图片位图吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21779054/

10-14 07:59