在Windows操作系统中,实现远程计算机的桌面镜像功能,可以通过安装显示镜像驱动程序来实现。镜像驱动程序自Windows 2000以来就存在。然而,对于Windows 8及更高版本,镜像驱动程序不再被安装。尽管如此,微软还是提供了替代方案。
这种替代方案被称为桌面复制API(Desktop Duplication API),它是DirectX11的一部分,更确切地说,是DXGI 1.2更新的一部分。实际上,DirectX 11 API可以在系统不支持DirectX 11的情况下回退到版本10或9,但DXGI不行。此外,Windows 7和Vista不会有DXGI 1.2版本——需要Windows 8或更高版本。
为了熟悉桌面复制API,研究了微软提供的示例。事实上,很难在其他地方找到更多的示例。
微软提供的示例适用于单个桌面,这完全符合其目的。DirectX是基于COM的,这意味着需要精通C或C++来正确处理它,对吗?不完全是这样,Delphi也非常适合处理COM接口。会说,使用Delphi,COM甚至可能更容易,因为它管理引用计数。
制作了两个示例:
第一个示例模仿了微软的示例。称之为控制台示例,尽管实际上并没有控制台。它使用Windows API创建一个窗口,启动一个或多个线程进行桌面复制,然后进入一个无尽的消息循环,以更新创建的窗口与捕获的帧。
第二个示例更符合Delphi的做事方式。在这里,创建了一个VCL表单,捕获的帧更新表单内的TPanel组件。选择了TPanel,因为它是TWinControl的后代,所以有一个HWND。
DirectX头文件来自下面的参考3。非常好的工作(确实很多!)
像素着色器和顶点着色器并不是直接由示例编译的。相反,将预编译的结果插入到PixelShader和VertexShader单元中。
以下是使用Delphi实现桌面复制API的示例代码:
unit DesktopDuplicationAPI;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComObj, Direct3D11, DXGI;
type
TDesktopDuplicationForm = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
DesktopDuplicationForm: TDesktopDuplicationForm;
implementation
{$R *.dfm}
procedure TDesktopDuplicationForm.Button1Click(Sender: TObject);
var
pDevice: ID3D11Device;
pDXGIFactory: IDXGIFactory2;
pAdapter: IDXGIAdapter;
pOutput: IDXGIOutput;
pDesktopDevice: ID3D11Device;
pDesktopResource: IDXGIResource;
pDesktopTexture2D: ID3D11Texture2D;
pDesktopDuplication: IDXGIOutputDuplication;
begin
// 初始化Direct3D11设备
D3D11CreateDevice(nil, D3D_DRIVER_TYPE_HARDWARE, nil, 0, nil, 0, D3D11_SDK_VERSION, pDevice, nil, nil);
// 获取DXGI工厂
CreateDXGIFactory1(pDXGIFactory);
pDXGIFactory.EnumAdapters(0, pAdapter);
pAdapter.EnumOutputs(0, pOutput);
// 获取桌面设备
pOutput.GetDevice(pDesktopDevice);
// 创建桌面复制接口
pOutput.QueryInterface(IID_IDXGIOutputDuplication, pDesktopDuplication);
// 获取桌面资源
pDesktopDuplication.AcquireNextFrame(500, nil, pDesktopResource);
pDesktopResource.QueryInterface(IID_ID3D11Texture2D, pDesktopTexture2D);
// 处理桌面资源
// ...
// 释放资源
pDesktopTexture2D := nil;
pDesktopResource := nil;
pDesktopDuplication := nil;
pAdapter := nil;
pOutput := nil;
pDXGIFactory := nil;
pDevice := nil;
end;
end.
以上代码展示了如何在Delphi中使用Desktop Duplication API来捕获桌面。首先,初始化Direct3D11设备,然后获取DXGI工厂、适配器、输出接口和桌面设备。接着,创建桌面复制接口并获取桌面资源。最后,处理桌面资源并释放所有资源。