- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
在有人提到它之前,我提到了 this链接以了解我需要如何将后备缓冲区复制到位图。
现状
期望的情况
正确截图,让目标进程继续正常执行。
代码
注意 Hook 类与链接中的相同。我只添加了它的一个 UnmodifiableHook 版本,它的功能与它的名字一样。我省略了所有不重要的部分。
TestSwapChainHook.cs
using System;
using System.Runtime.InteropServices;
namespace Test
{
public sealed class TestSwapChainHook : IDisposable
{
private enum IDXGISwapChainVirtualTable
{
QueryInterface = 0,
AddRef = 1,
Release = 2,
SetPrivateData = 3,
SetPrivateDataInterface = 4,
GetPrivateData = 5,
GetParent = 6,
GetDevice = 7,
Present = 8,
GetBuffer = 9,
SetFullscreenState = 10,
GetFullscreenState = 11,
GetDesc = 12,
ResizeBuffers = 13,
ResizeTarget = 14,
GetContainingOutput = 15,
GetFrameStatistics = 16,
GetLastPresentCount = 17,
}
public static readonly int VIRTUAL_METHOD_COUNT_LEVEL_DEFAULT = 18;
private static IntPtr[] SWAP_CHAIN_VIRTUAL_TABLE_ADDRESSES;
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)]
public delegate int DXGISwapChainPresentDelegate(IntPtr thisPtr, uint syncInterval, SharpDX.DXGI.PresentFlags flags);
public delegate int DXGISwapChainPresentHookDelegate(UnmodifiableHook<DXGISwapChainPresentDelegate> hook, IntPtr thisPtr, uint syncInterval, SharpDX.DXGI.PresentFlags flags);
private DXGISwapChainPresentHookDelegate _present;
private Hook<DXGISwapChainPresentDelegate> presentHook;
static TestSwapChainHook()
{
SharpDX.DXGI.Rational rational = new SharpDX.DXGI.Rational(60, 1);
SharpDX.DXGI.ModeDescription modeDescription = new SharpDX.DXGI.ModeDescription(100, 100, rational, SharpDX.DXGI.Format.R8G8B8A8_UNorm);
SharpDX.DXGI.SampleDescription sampleDescription = new SharpDX.DXGI.SampleDescription(1, 0);
using (SharpDX.Windows.RenderForm renderForm = new SharpDX.Windows.RenderForm())
{
SharpDX.DXGI.SwapChainDescription swapChainDescription = new SharpDX.DXGI.SwapChainDescription();
swapChainDescription.BufferCount = 1;
swapChainDescription.Flags = SharpDX.DXGI.SwapChainFlags.None;
swapChainDescription.IsWindowed = true;
swapChainDescription.ModeDescription = modeDescription;
swapChainDescription.OutputHandle = renderForm.Handle;
swapChainDescription.SampleDescription = sampleDescription;
swapChainDescription.SwapEffect = SharpDX.DXGI.SwapEffect.Discard;
swapChainDescription.Usage = SharpDX.DXGI.Usage.RenderTargetOutput;
SharpDX.Direct3D11.Device device = null;
SharpDX.DXGI.SwapChain swapChain = null;
SharpDX.Direct3D11.Device.CreateWithSwapChain(SharpDX.Direct3D.DriverType.Hardware, SharpDX.Direct3D11.DeviceCreationFlags.BgraSupport, swapChainDescription, out device, out swapChain);
try
{
IntPtr swapChainVirtualTable = Marshal.ReadIntPtr(swapChain.NativePointer);
SWAP_CHAIN_VIRTUAL_TABLE_ADDRESSES = new IntPtr[VIRTUAL_METHOD_COUNT_LEVEL_DEFAULT];
for (int x = 0; x < VIRTUAL_METHOD_COUNT_LEVEL_DEFAULT; x++)
{
SWAP_CHAIN_VIRTUAL_TABLE_ADDRESSES[x] = Marshal.ReadIntPtr(swapChainVirtualTable, x * IntPtr.Size);
}
device.Dispose();
swapChain.Dispose();
}
catch (Exception)
{
if (device != null)
{
device.Dispose();
}
if (swapChain != null)
{
swapChain.Dispose();
}
throw;
}
}
}
public TestSwapChainHook()
{
this._present = null;
this.presentHook = new Hook<DXGISwapChainPresentDelegate>(
SWAP_CHAIN_VIRTUAL_TABLE_ADDRESSES[(int)IDXGISwapChainVirtualTable.Present],
new DXGISwapChainPresentDelegate(hookPresent),
this);
}
public void activate()
{
this.presentHook.activate();
}
public void deactivate()
{
this.presentHook.deactivate();
}
private int hookPresent(IntPtr thisPtr, uint syncInterval, SharpDX.DXGI.PresentFlags flags)
{
lock (this.presentHook)
{
if (this._present == null)
{
return this.presentHook.original(thisPtr, syncInterval, flags);
}
else
{
return this._present(new UnmodifiableHook<DXGISwapChainPresentDelegate>(this.presentHook), thisPtr, syncInterval, flags);
}
}
}
public DXGISwapChainPresentHookDelegate present
{
get
{
lock (this.presentHook)
{
return this._present;
}
}
set
{
lock (this.presentHook)
{
this._present = value;
}
}
}
}
}
使用代码
初始化
private TestSwapChain swapChainHook;
private bool capture = false;
private object captureLock = new object();
this.swapChainHook = new TestSwapChainHook();
this.swapChainHook.present = presentHook;
this.swapChainHook.activate();
编辑
我使用了不同的方法来捕获 this 中描述的屏幕截图关联。但是我的屏幕截图是这样的:
现在这似乎是我的转换设置或其他任何问题,但我无法确定我需要做些什么来修复它。我知道我正在转换为位图的表面使用 DXGI_FORMAT_R10G10B10A2_UNORM 格式(我认为是 32 位,每种颜色 10 位,alpha 位 2 位?)。但我不确定这在 for 循环中是如何工作的(跳过字节和东西)。我只是简单地复制粘贴它。
新的钩子函数
private int presentHook(UnmodifiableHook<IDXGISwapChainHook.DXGISwapChainPresentDelegate> hook, IntPtr thisPtr, uint syncInterval, SharpDX.DXGI.PresentFlags flags)
{
try
{
lock (this.captureLock)
{
if (this.capture)
{
SharpDX.DXGI.SwapChain swapChain = (SharpDX.DXGI.SwapChain)thisPtr;
using (SharpDX.Direct3D11.Texture2D backBuffer = swapChain.GetBackBuffer<SharpDX.Direct3D11.Texture2D>(0))
{
SharpDX.Direct3D11.Texture2DDescription texture2DDescription = backBuffer.Description;
texture2DDescription.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.Read;
texture2DDescription.Usage = SharpDX.Direct3D11.ResourceUsage.Staging;
texture2DDescription.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None;
texture2DDescription.BindFlags = SharpDX.Direct3D11.BindFlags.None;
using (SharpDX.Direct3D11.Texture2D texture = new SharpDX.Direct3D11.Texture2D(backBuffer.Device, texture2DDescription))
{
//DXGI_FORMAT_R10G10B10A2_UNORM
backBuffer.Device.ImmediateContext.CopyResource(backBuffer, texture);
using (SharpDX.DXGI.Surface surface = texture.QueryInterface<SharpDX.DXGI.Surface>())
{
SharpDX.DataStream dataStream;
SharpDX.DataRectangle map = surface.Map(SharpDX.DXGI.MapFlags.Read, out dataStream);
try
{
byte[] pixelData = new byte[surface.Description.Width * surface.Description.Height * 4];
int lines = (int)(dataStream.Length / map.Pitch);
int dataCounter = 0;
int actualWidth = surface.Description.Width * 4;
for (int y = 0; y < lines; y++)
{
for (int x = 0; x < map.Pitch; x++)
{
if (x < actualWidth)
{
pixelData[dataCounter++] = dataStream.Read<byte>();
}
else
{
dataStream.Read<byte>();
}
}
}
GCHandle handle = GCHandle.Alloc(pixelData, GCHandleType.Pinned);
try
{
using (Bitmap bitmap = new Bitmap(surface.Description.Width, surface.Description.Height, map.Pitch, PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject()))
{
bitmap.Save(@"C:\Users\SOMEUSERNAME\Desktop\test.bmp");
}
}
finally
{
if (handle.IsAllocated)
{
handle.Free();
}
}
}
finally
{
surface.Unmap();
dataStream.Dispose();
}
}
}
}
this.capture = false;
}
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
return hook.original(thisPtr, syncInterval, flags);
}
回答
原来 DXGI_FORMAT_R10G10B10A2_UNORM 格式是这种位格式:
A=alpha
B=blue
G=green
R=red
AABBBBBB BBBBGGGG GGGGGGRR RRRRRRRR
而 Format32bppArgb 是这样的字节顺序:
BGRA
所以最后的循环代码是:
while (pixelIndex < pixelData.Length)
{
uint currentPixel = dataStream.Read<uint>();
uint r = (currentPixel & 0x3FF);
uint g = (currentPixel & 0xFFC00) >> 10;
uint b = (currentPixel & 0x3FF00000) >> 20;
uint a = (currentPixel & 0xC0000000) >> 30;
pixelData[pixelIndex++] = (byte)(b >> 2);
pixelData[pixelIndex++] = (byte)(g >> 2);
pixelData[pixelIndex++] = (byte)(r >> 2);
pixelData[pixelIndex++] = (byte)(a << 6);
while ((pixelIndex % map.Pitch) >= actualWidth)
{
dataStream.Read<byte>();
pixelIndex++;
}
}
最佳答案
该屏幕截图确实看起来像是 R10G10B10A2 被塞进了 R8G8B8A8。我没有测试过你的代码,但我们应该有这个位布局
xxxxxxxx yyyyyyyy zzzzzzzz wwwwwwww
RRRRRRRR RRGGGGGG GGGGBBBB BBBBBBAA
你可以如下提取它们
byte x = data[ptr++];
byte y = data[ptr++];
byte z = data[ptr++];
byte w = data[ptr++];
int r = x << 2 | y >> 6;
int g = (y & 0x3F) << 4 | z >> 4;
int b = (z & 0xF) << 6 | w >> 2;
int a = w & 0x3;
其中 r、g、b 现在有 10 位分辨率。如果您想将它们缩减为字节,您可以使用 (byte)(r >> 2) 来实现。
更新
这将取代您的双重 for 循环。我无法对此进行测试,所以我不想进一步插入它,但我相信这个想法是正确的。最后一次检查应跳过每行中的填充字节。
while(dataCounter < pixelData.Length)
{
byte x = dataStream.Read<byte>();
byte y = dataStream.Read<byte>();
byte z = dataStream.Read<byte>();
byte w = dataStream.Read<byte>();
int r = x << 2 | y >> 6;
int g = (y & 0x3F) << 4 | z >> 4;
int b = (z & 0xF) << 6 | w >> 2;
int a = w & 0x3;
pixelData[dataCounter++] = (byte)(r >> 2);
pixelData[dataCounter++] = (byte)(g >> 2);
pixelData[dataCounter++] = (byte)(b >> 2);
pixelData[dataCounter++] = (byte)(a << 6);
while((dataCounter % map.Pitch) >= actualWidth)
{
dataStream.Read<byte>();
dataCounter++;
}
}
关于c# - 使用 SharpDX 和 EasyHook 捕获全屏 DX11 程序的屏幕截图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38109018/
我无法从主题做一个场景。 我安装了 DirectX 2009 年 3 月 9 日的 SDK,它是 9,“sub”-version c,但是“sub-sub”-version 是 41,所以库 (d3d
我的团队和我一直在努力解决我们在进入 Beta 版之前尝试混淆我们的 Android 应用程序时遇到的异常。 我们得到的异常是: Error:Uncaught translation error: c
我在将同事的 Android 源代码编译为 APK 时遇到问题。这是控制台中显示的错误 :app:transformClassesWithDexForDebug AGPBI: {"kind":"err
我最近在尝试为 Android 构建 apk 时遇到了我的 Azure CI 管道问题。 我收到以下错误: Build-tool 31.0.0 is missing DX at /usr/local/
我的 HelloWorld.java 中有以下代码: public class HelloWorld { public static void main(String[] args) {
我的 Android 应用程序使用了大量非常重要的外部库。这些库都是用 Java 编写的,并简单地添加到构建路径中。 从 Eclipse 中启动应用程序需要很长时间,大约 5 分钟。这非常令人沮丧!
所以我的问题有点简单。我有一个顶点缓冲区,我用创建它 pDevice->CreateVertexBuffer( m_dwCount * sizeof(CUSTOMVERTEX)
eclipse 中有没有办法将参数传递给 dx(--no-optimize 等)以提高 dx 处理速度? 最佳答案 创建少于 300 行的方法,在我创建了一个 2000 行的方法之前,在 Dx 处理中
有没有关于“dx”的文档? 我特别想知道 --core-library 选项的作用。 最佳答案 什么是“dx”工具? dx 工具将 Java 类文件转换为 *.dex(Dalvik 可执行文件)* 文
我目前正在为x86汇编学习考试。 我没有太多运气来搜索“:”,这太常见了标点符号:/ IDIV - Signed Integer Division Usage: IDIV src Modifies f
我有一个输出 jcamp-dx (*.jdx) 文件的仪器。有我可以用来查看数据的软件,但我宁愿用它做一些其他事情,比如在网页上绘制它,这在我必须访问数据的软件中是不允许的。 数据文件是纯文本,但它们
我正在尝试根据是否选中复选框来设置按钮的启用/禁用。下面是我的 javascript 和 asp 代码,它不起作用。我不确定是否根本没有调用该函数,或者我禁用按钮的方式有问题。 function O
我需要从命令行构建我的 android 应用程序(我正在使用 Java7 编译代码),但是当我尝试创建 dex 文件时出现以下错误 trouble processing: bad class file
我尝试使用这段代码缩放矩阵: D3DXMATRIX & rMatrix = m_Matrices[i]; D3DXMatrixScaling(&rMatrix, 2.0
最近我又回到了 C++ 中。我已经离开 C++/CLI 而使用 C# 至少一年了,我有点生疏了。我正在查看适用于 Windows 8 的 Direct3D 应用程序的基本示例,但找不到任何可以解释
当我在 eclipse ADT 中运行 android 应用程序时,“Dx 写入输出时遇到问题:已经准备好”出现在控制台中,然后应用程序照常运行。出现此消息的原因是什么?我该如何解决? 最佳答案 我遇
我想使用 C++ 进行插件开发。在开发 VST 或 DX 之间犹豫不决。有什么考虑?我知道有些主机更容易支持一种或另一种格式(Cubase:VSTs,Cakewalk:DXs),但这就是我所知道的。
我正在尝试根据类型可视化一些评分,但是我很难找到如何根据类型对系列进行分组。 图表选项如下: $scope.chartOptions = { dataSource: data,
如何为 d/d(n*x) 运算符生成模板? 我正在编写一个需要计算图像中线导数的程序。如果我们想计算关于 d/dx 的最简单的导数近似,我们可以运行以下操作: diff[x] = -1.0 * ima
我使用 dev extreme Angular 应用程序中的 UI 框架。 在文档中我找到了如何设置 focus 它说使用 method focus() 但是DxTextBoxComponent中没有
我是一名优秀的程序员,十分优秀!