我挂钩对话框(CommonDialog
和MessageBox
),以便在显示后可以将它们置于父Form
中。对于MessageBox
关注的问题,一切都像魅力一样,但当对话继承自CommonDialog
(OpenFileDialog
,SaveFileDialog
等...)时,我检索到的矩形总是错误的并且中心变得搞砸了。这是我用来获取对话框矩形的代码:
[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
返回错误的矩形Width
和Height
中心继承自CommonDialog
。在我的测试中,我发现GetWindowRect
和DwmGetWindowAttribute
都返回相同的值,因此我实现的主要解决方法完全没用。我还发现检索到的矩形总是比实际的宽40像素左右(我测量了它的截图)。
现在,这让我很生气。我能想出的唯一解决方案是:
检测窗口处理程序是否属于CommonDialog
,在这种情况下,手动修复矩形大小。我不知道怎么做,因为GetClassName
会为#32770
和MessageBox
返回CommonDialog
。我还怀疑GetWindowLong
可以提供有用的信息,让我能够识别对话框类型。
在显示CommonDialog
后立即手动调整大小,以便我知道它的实际大小。
任何其他建议都非常受欢迎。