首页 > 解决方案 > 如何用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;
                }


            }

标签: c#directx-11sharpdxhwnd

解决方案


推荐阅读