【问题标题】:Write an RDP client that dumps the pixels of the screen编写转储屏幕像素的 RDP 客户端
【发布时间】:2014-01-03 14:17:50
【问题描述】:

我想在C++ 中实现一个 RDP 客户端,它能够获取屏幕所有像素的颜色值并将它们转储到文件中。我知道这在概念上与 RDP 的工作方式不同,但我的应用程序需要它。我正在尝试使用freerdp,但我不确定如何有效地编写一个简单地将所有像素转储到文件中的客户端。

到目前为止,我最好的尝试是使用函数gdi_GetPixel_32bpp,但当然为每个像素依次调用这个函数远没有效率。

使用另一个库的解决方案也将不胜感激。

【问题讨论】:

  • 你真正想做什么?也就是为什么需要截图。可能有比实施 RDP 更简单的方法。
  • @selbie 我尝试将 RDP 的(至少屏幕部分)翻译为 VNC。由于 VNC 非常简单,我最终必须能够决定屏幕的像素值。
  • 我假设您的客户端应该是 Windows 应用程序?它需要便携吗?
  • @Useless 它应该能够在 Linux 上运行,并且不必是跨平台的。免费 RDP 在 Linux 上运行,所以这应该不是什么大问题。
  • 好的,那么你有什么理由不能只运行 vnc X 服务器,然后在其中全屏运行 rdp 客户端?

标签: c++ rdp freerdp


【解决方案1】:

这应该很容易使用 libfreerdp-gdi 以非常有效的方式完成。 FreeRDP 可以将所有内容渲染到软件缓冲区,然后您可以将其转储到文件中,如果您愿意,您可以完全在内存中完成此操作,无需 X11 环境。由于提到了 Linux,一种快速入门的方法是使用带有 /gdi:sw 选项的 xfreerdp 来使用 libfreerdp-gdi(默认是使用基于 X11 的实现),然后将像素作为更新转储进来吧。你可以把自己挂在 xf_sw_end_paint 中,它在更新数组的末尾被调用。您可以访问无效区域和像素缓冲区(都在 rdpGdi* gdi 结构下)。重要的字段是 gdi->primary_buffer、gdi->dstBpp、gdi->bytesPerPixel、gdi->width 和 gdi->height。在大多数情况下,您将获得一个易于处理的 XRGB32 缓冲区。有疑问,看一下 gdi_init() 内部缓冲区的初始化。

【讨论】:

    【解决方案2】:

    你可以试试这个(免责声明未经测试的伪代码):

    HGDI_DC memDC = gdi_CreateCompatibleDC ( hDC );
    HGDI_BITMAP memBM = gdi_CreateCompatibleBitmap ( hDC, screenWidth, screenHeight );
    gdi_SelectObject ( memDC, memBM );
    gdi_BitBlt(memDC, 0, 0, screenWidth, screenHeight, hDC, 0, 0, GDI_SRCCOPY);
    

    现在您应该在memBM->data 中拥有完整的像素数据数组。 memBM->数据大小如下:memBM->width * memBM->height * memBM->bytesPerPixel

    希望这至少对您有所帮助。

    【讨论】:

    • 这个答案缺少上下文的重要部分。 hDC 是什么?这段代码应该在哪里执行?
    • @IvayloStrandjev 可以肯定的是,您可以使用 gdi_GetPixel_32bpp 吗?澄清一下:如果可以的话,您实际上可以关闭上面的 4 个调用并直接使用您正在使用的句柄上的数据。我没有意识到这个函数实际上已经在 BitMap 对象上运行了。
    • 我不确定。我没有尝试实施我提到的解决方案,因为它似乎存在严重缺陷。
    • 此调用无法编译:gdi_SelectObject ( memDC, memBM ); 因为 memBM 不是 HGDIOBJECT 类型
    • 我给你赏金,因为你的回答给了我一些关于如何解决我的问题的提示。还有一些问题我没有解决,但我现在有了一个工作原型。
    【解决方案3】:

    如果您运行 VNC X 服务器并在其中全屏启动 RDP 客户端(没有窗口管理器等),则绘图顺序应类似于:

    1. RDP 客户端从远程会话接收更新
    2. RDP 客户端将更新转换为 X11 消息,很可能通过共享内存传输发送
    3. VNC 服务器接收 X11 请求并使用它们来渲染位图

    所以开销应该只是 X11 协议,它固然笨重,但至少应该通过共享内存段发送。

    老实说,我会先尝试这种零编码方法,看看性能是否真的是个问题。

    【讨论】:

    • 我将评估这种方法。您能否提供有关最后第三步的更多信息?我不确定如何将 X11 消息呈现为位图。
    • 我建议 VNC X 服务器已经为您执行此操作。
    【解决方案4】:

    WebRTC 可能有一些代码可供您参考,例如 screen capturer 或 window capturer。

    桌面捕获器更复杂,因为它 (1) 进行差异化以捕获最少的内容,并且 (2) 也捕获鼠标。由于桌面只是一个特殊的“窗口”,用::GetDesktopWindow() 检索,它的DC 可以用那个窗口或只是GetDC(NULL) 检索,您可以使用窗口捕获器并忽略更复杂的位。检查窗口捕获器的捕获功能以了解详细信息,以及有关处理 Aero 和其他合成/离屏问题的一些有用提示。

    【讨论】:

    • 在我看来,这使用了自己的协议而不是 RDP。我已经有 RDP 流量,需要“即时”翻译它,所以我没有切换到另一个应用程序的选项。
    • 我不是说将它用于 chrome 远程桌面,如果这就是你的意思。我链接到的代码是为了(我认为)您所要求的:将屏幕内容捕获到内存中。实际的通信格式应该是分开的。无论如何,祝你好运!
    猜你喜欢
    • 2013-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-24
    相关资源
    最近更新 更多