c# - 如何用sharpdx 和hwnd 捕获窗口?
问题描述
我是编程新手,对不准确之处深表歉意。我试图捕获它指定的窗口并将其保存到位图中。我找到了捕获整个桌面屏幕的方法,当我尝试更改代码以达到我想要的效果时,它返回给我空字节数组。
如果有人知道捕获窗口的答案或其他方法(即使它被覆盖),我将非常感激。
截屏方法:
public static Bitmap ScreanCapture(Window window)
{
//SharpDX.Configuration.EnableObjectTracking = true;
//System.Diagnostics.Debug.Write(SharpDX.Diagnostics.ObjectTracker.ReportActiveObjects());
var d3device = new SharpDX.Direct3D11.Device(DriverType.Hardware, SharpDX.Direct3D11.DeviceCreationFlags.BgraSupport);
var d3dcontext = new SharpDX.Direct3D11.DeviceContext(d3device);
var dxgiDevice = d3device.QueryInterface<SharpDX.DXGI.Device1>();
var dxgiFactory = dxgiDevice.Adapter.GetParent<SharpDX.DXGI.Factory2>();
SwapChainDescription1 swapDesc = new SwapChainDescription1
{
BufferCount = 2,
Format = Format.R8G8B8A8_UNorm,
Usage = Usage.RenderTargetOutput,
Width = window.GetwindowWidth(),
Height = window.GetwindowHeight(),
Stereo = false,
SampleDescription = new SampleDescription(1, 0),
AlphaMode = SharpDX.DXGI.AlphaMode.Ignore,
Scaling = Scaling.None,
Flags = SwapChainFlags.None,
SwapEffect = SwapEffect.FlipSequential
};
var swapChain = new SwapChain1(dxgiFactory, dxgiDevice, window.GetID(), ref swapDesc);
Surface surface;
using (Texture2D backBuffer = swapChain.GetBackBuffer<Texture2D>(0))
{
Texture2DDescription desc = backBuffer.Description;
desc.CpuAccessFlags = CpuAccessFlags.Read;
desc.Usage = ResourceUsage.Staging;
desc.OptionFlags = ResourceOptionFlags.None;
desc.BindFlags = BindFlags.None;
using (Texture2D tempbuffer = new Texture2D(swapChain.GetDevice<SharpDX.Direct3D11.Device>(), desc))
{
backBuffer.Device.ImmediateContext.CopyResource(backBuffer, tempbuffer);
surface = tempbuffer.QueryInterface<Surface>();
}
}
DataStream dataStream;
var map = surface.Map(SharpDX.DXGI.MapFlags.Read, out dataStream);
byte[] data = new byte[surface.Description.Width * surface.Description.Height * 4];
int dataCounter = 0;
int actualWidth = surface.Description.Width * 4;
while (dataCounter < data.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;
data[dataCounter++] = (byte)(b >> 2);
data[dataCounter++] = (byte)(g >> 2);
data[dataCounter++] = (byte)(r >> 2);
data[dataCounter++] = (byte)(a << 6);
while ((dataCounter % map.Pitch) >= actualWidth)
{
dataStream.Read<byte>();
dataCounter++;
}
}
//data array has only 0
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
Bitmap bitmap = null;
try
{
bitmap = new Bitmap(surface.Description.Width, surface.Description.Height, map.Pitch, PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject());
}
finally
{
if (handle.IsAllocated)
{
handle.Free();
}
}
//Disposing COM
dataStream.Dispose();
surface.Unmap();
swapChain.Dispose();
dxgiDevice.Dispose();
dxgiFactory.Dispose();
d3dcontext.Dispose();
d3device.Dispose();
return bitmap;
}
获取窗口hwnd的方法:
public static IReadOnlyList<Window> allWindows()
{
List<Window> list = new List<Window>();
WndEnumProc wndEnumProc = new WndEnumProc(OnWindowsEnum);
EnumWindows(wndEnumProc, 0);
return list;
bool OnWindowsEnum(IntPtr hwnd, IntPtr lparam)
{
IntPtr hwndTry, hwndWalk = IntPtr.Zero;
if (!IsWindowVisible(hwnd) || GetWindowText(hwnd) == String.Empty)
return true;
hwndTry = GetAncestor(hwnd, GA_ROOTOWNER);
while (hwndTry != hwndWalk)
{
hwndWalk = hwndTry;
hwndTry = GetLastActivePopup(hwndWalk);
if (IsWindowVisible(hwndTry))
break;
}
if (hwndWalk != hwnd)
return true;
if (IsWindowCloaked(hwnd))
return true;
if ((GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW) != 0)
return true;
var newWindow = new Window(hwnd, GetWindowText(hwnd), GetAbsoluteClientRect(hwnd));
if(!list.Contains(newWindow))
list.Add(newWindow);
return true;
}
}
解决方案
推荐阅读
- java - 如何在不使用任何额外变量或内置函数的情况下获得数组中的最大数
- unity3d - Unity:使用 FFmpeg 将 Texture2D 转换为 YUV420P
- python - Python - 将局部变量更改为全局变量
- c# - 在 WPF 中保存和检索字符串数组的最佳方法是什么
- haskell - 无法导入 Data.List.\\
- python - 使用 django 根据日期修改模板
- javascript - vue-apollo 3.0.0 测试版配置
- java - how to make a bean prototype using only @scope("prototype) annotation in spring?
- java - 如何使介绍滑块在安装后只出现一次?
- android - IntellIJ 中的 Android 项目 - 错误:无法创建活动