C#对话框窗口矩形

时间:2016-12-01 19:33:37

标签: c# .net winforms native

我挂钩对话框(CommonDialogMessageBox),以便在显示后可以将它们置于父Form中。对于MessageBox关注的问题,一切都像魅力一样,但当对话继承自CommonDialogOpenFileDialogSaveFileDialog等...)时,我检索到的矩形总是错误的并且中心变得搞砸了。这是我用来获取对话框矩形的代码:

[DllImport("User32.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Unicode, ExactSpelling=true, SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern Boolean GetWindowRect([In] IntPtr handle, [Out] out RECT rectangle);

[DllImport("Dwmapi.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Unicode, ExactSpelling=true, SetLastError=true)]
private static extern UInt32 DwmGetWindowAttribute([In] IntPtr handle, [In] DWMWINDOW_ATTRIBUTE attribute, [In, Out] IntPtr attributeValue, [In] UInt32 attributeSize);

[DllImport("Dwmapi.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Unicode, ExactSpelling=true, SetLastError=true)]
private static extern UInt32 DwmIsCompositionEnabled([Out, MarshalAs(UnmanagedType.Bool)] out Boolean enabled);

internal static Boolean AeroThemeEnabled
{
    get
    {
        Boolean result = false;

        if (Environment.OSVersion.Version.Major >= 6)
            DwmIsCompositionEnabled(out result);

        return result;
    }
}

internal static Boolean GetRectangle(IntPtr windowHandle, out Rectangle rectangle)
{
    RECT nativeRectangle;

    if (AeroThemeEnabled)
    {
        IntPtr attributeValue = IntPtr.Zero;
        UInt32 size = GetSize(typeof(RECT));

        try
        {
            attributeValue = Marshal.AllocCoTaskMem((Int32)size);

            UInt32 result = DwmGetWindowAttribute(windowHandle, DWMWINDOW_ATTRIBUTE.DWMWA_EXTENDED_FRAME_BOUNDS, attributeValue, size);

            if (result == 0)
                nativeRectangle = Marshal.PtrToStructure<RECT>(attributeValue);
            else if (!GetWindowRect(windowHandle, out nativeRectangle))
            {
                rectangle = Rectangle.Empty;
                return false;
            }
        }
        finally
        {
            if (attributeValue != IntPtr.Zero)
                Marshal.FreeCoTaskMem(attributeValue);
        }
    }
    else if (!GetWindowRect(windowHandle, out nativeRectangle))
    {
        rectangle = Rectangle.Empty;
        return false;
    }

    Int32 x = nativeRectangle.Left;
    Int32 y = nativeRectangle.Top;
    Int32 width = nativeRectangle.Right - x;
    Int32 height = nativeRectangle.Bottom - y;

    rectangle = new Rectangle(x, y, width, height);

    return true;
}

在我的工作环境(带有VS2013和Framework 4.6.2的Win7)中,正如我之前所说,当我有对话框时,方法GetRectangle返回错误的矩形WidthHeight中心继承自CommonDialog。在我的测试中,我发现GetWindowRectDwmGetWindowAttribute都返回相同的值,因此我实现的主要解决方法完全没用。我还发现检索到的矩形总是比实际的宽40像素左右(我测量了它的截图)。

现在,这让我很生气。我能想出的唯一解决方案是:

  1. 检测窗口处理程序是否属于CommonDialog,在这种情况下,手动修复矩形大小。我不知道怎么做,因为GetClassName会为#32770MessageBox返回CommonDialog。我还怀疑GetWindowLong可以提供有用的信息,让我能够识别对话框类型。

  2. 在显示CommonDialog后立即手动调整大小,以便我知道它的实际大小。

  3. 任何其他建议都非常受欢迎。

0 个答案:

没有答案
相关问题