在没有Windows阴影的情况下检索窗口大小

Ric*_*ahl 12 c# windows pinvoke winapi

我正在尝试基于Window句柄捕获C#中的桌面窗口.我正在使用.NET并使用PInvoke来GetWindowRect()来捕获窗口矩形.我有窗口选择和矩形捕获工作正常.

但是,捕获的窗口矩形不仅包括实际窗口大小,还包括Window的装饰,如周围的阴影.当我尝试将窗口剪辑为位图时,位图包含区域和阴影.在Windows 10上,我得到透明阴影区域,包括活动窗口下方可能显示的任何内容:

在此输入图像描述

我使用的代码很简单,通过PInvoke调用使用Win32 GetWindowRect()捕获Window:

var rect = new Rect();
GetWindowRect(handle, ref rect);
var bounds = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);
var result = new Bitmap(bounds.Width, bounds.Height);

using (var graphics = Graphics.FromImage(result))
{
    graphics.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
}

return result;
Run Code Online (Sandbox Code Playgroud)

然后我捕获图像并将其分配到图片框中.

此外,它看起来像窗户之间有一些变化 - 有些窗户有阴影,有些窗户没有.大多数人都这样做,但是像Visual Studio和Chrome这样的人没有,所以它甚至不是一个简单的问题,即剥离无关的像素.

我已经尝试过使用GetClientRect(),但这只是客户区,这不是我所追求的.我想得到的是带有边框但没有阴影的实际窗口矩形.

反正有没有这样做?

dyn*_*ael 6

我正在运行Windows 10,并且在编写将窗口捕捉到屏幕顶部或底部的应用程序时遇到了相同的问题。我发现DwmGetWindowAttribute()可以工作。它返回的RECT值与GetWindowRect()略有不同。

样本窗口中的结果:

GetWindowRect():{X = 88,Y = 26,Width = 871,Height = 363}

DwmGetWindowAttribute():{X = 95,Y = 26,Width = 857,Height = 356}

我的测试表明,GetWindowRect()包含装饰,而DwmGetWindowAttribute()不包含。

如果在带有装饰的窗口上从这两种方法获得相同的结果,则可能是该特定窗口正在绘制自己的装饰,或者该窗口设置了其他一些属性需要考虑。

  • `DwmGetWindowAttribute(handle,DWMWINDOWATTRIBUTE.ExtendedFrameBounds,out var rect,Marshal.SizeOf <Rect>());`在Win10上为我工作。 (2认同)

Riz*_*Riz 6

您可以使用DwmGetWindowAttribute. 请参阅以下示例。您可以使用GetWindowRectangle任何手柄来获取其实际大小。

[DllImport("dwmapi.dll")]
public static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out RECT pvAttribute, int cbAttribute);

    public struct RECT
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }

    [Flags]
    private enum DwmWindowAttribute : uint
    {
        DWMWA_NCRENDERING_ENABLED = 1,
        DWMWA_NCRENDERING_POLICY,
        DWMWA_TRANSITIONS_FORCEDISABLED,
        DWMWA_ALLOW_NCPAINT,
        DWMWA_CAPTION_BUTTON_BOUNDS,
        DWMWA_NONCLIENT_RTL_LAYOUT,
        DWMWA_FORCE_ICONIC_REPRESENTATION,
        DWMWA_FLIP3D_POLICY,
        DWMWA_EXTENDED_FRAME_BOUNDS,
        DWMWA_HAS_ICONIC_BITMAP,
        DWMWA_DISALLOW_PEEK,
        DWMWA_EXCLUDED_FROM_PEEK,
        DWMWA_CLOAK,
        DWMWA_CLOAKED,
        DWMWA_FREEZE_REPRESENTATION,
        DWMWA_LAST
    }

    public static RECT GetWindowRectangle(IntPtr hWnd)
    {
        RECT rect;

        int size = Marshal.SizeOf(typeof(RECT));
        DwmGetWindowAttribute(hWnd, (int)DwmWindowAttribute.DWMWA_EXTENDED_FRAME_BOUNDS, out rect, size);

        return rect;
    }
Run Code Online (Sandbox Code Playgroud)