首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用PInvoke时,DwmGetWindowAttribute返回0

使用PInvoke时,DwmGetWindowAttribute返回0
EN

Stack Overflow用户
提问于 2016-07-31 23:17:05
回答 2查看 2.7K关注 0票数 4

我试图通过捕获一个特定的窗口来进行屏幕捕获,为了准确地计算出要捕获的窗口的大小,我想使用DwmGetWindowAttribute()。当我在Windows10上使用PInvoke调用此函数时,即使结果值为0(成功),Rect结构也始终为空。传入的窗口句柄也是有效的,因为有调用GetWindowRect()的回退代码,可以正常工作(尽管有边界问题)。

我有点不知所措。我以前用过同样的代码(可能是在Windows8.1上?)同样的代码似乎也在工作,但是现在不管我做什么,对函数的调用总是返回一个空结构。

下面是相关的代码。

定义:

代码语言:javascript
复制
    [DllImport("dwmapi.dll")]
    static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out Rect pvAttribute, int cbAttribute);


    [Flags]
    public 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
    }

    [Serializable, StructLayout(LayoutKind.Sequential)]
    public struct Rect
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;

        public Rectangle ToRectangle()
        {
            return Rectangle.FromLTRB(Left, Top, Right, Bottom);
        }
    }

执行捕获的代码:

代码语言:javascript
复制
    public static Rectangle GetWindowRectangle(IntPtr handle)
    {
        Rectangle rected = Rectangle.Empty;

        Rect rect = new Rect();
        if (Environment.OSVersion.Version.Major < 6)
        {
            GetWindowRect(handle, out rect);
            rected = rect.ToRectangle();
        }      
        else
        {

            int size = Marshal.SizeOf(typeof(Rect));
            int res = DwmGetWindowAttribute(handle, (int)DwmWindowAttribute.DWMWA_EXTENDED_FRAME_BOUNDS, out rect, size);

            Debug.WriteLine(res.ToString("x") + " " + size + " " + handle + " " + (int) DwmWindowAttribute.DWMWA_EXTENDED_FRAME_BOUNDS);

            // allow returning of desktop and aero windows
            if (rected.Width == 0)
            {
                GetWindowRect(handle, out rect);
                rected = rect.ToRectangle();
                Debug.WriteLine("Using GetWindowRect");
            }
        }

        Debug.WriteLine(rected.ToString());
        return rected;
    }

感觉这里缺少了一些简单的东西。有什么想法吗?

EN

回答 2

Stack Overflow用户

发布于 2021-01-06 17:30:26

基于GetWindowsRectangle.的Rick Strahl原始代码和Hans Passant校正,我创建了一个更紧凑的版本我在Windows10上测试了它,这是它的代码,以防它在未来对某人有帮助:

代码语言:javascript
复制
public static Rectangle GetWindowRectangle(IntPtr handle)
    {
        Rect rect = new Rect();
                        
        if (Environment.OSVersion.Version.Major >= 6)
        {
            int size = Marshal.SizeOf(typeof(Rect));
            DwmGetWindowAttribute(handle, (int)DwmWindowAttribute.DWMWA_EXTENDED_FRAME_BOUNDS, out rect, size);
        }
        else if (Environment.OSVersion.Version.Major < 6 || rect.ToRectangle().Width == 0)
        {
            GetWindowRect(handle, out rect);
        }

        return rect.ToRectangle();
    }
票数 2
EN

Stack Overflow用户

发布于 2018-06-08 20:41:20

使用GetWindowRect而不是DwmGetWindowAttribute接收窗口的RECT

代码语言:javascript
复制
[DllImport("user32.dll", SetLastError = true)]
public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38685405

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档