在.NET 4中最大化窗口时,窗口顶部和左侧值未正确更新

Jen*_*sen 13 .net c# wpf

我试图将窗口居中到所有者窗口.我还需要子窗口沿所有者窗口移动.可以在此处找到MSDN WPF论坛上的交叉帖子.

要做到这一点我订阅LocationChangedSizeChanged事件(以及StateChanged事件),我的子窗口的所有者.当这些事件被触发时,我重新计算子窗口的位置.我在子窗口的代码隐藏中执行此操作.

代码很直接:

Top = Owner.Top + ((Owner.ActualHeight - ActualHeight) / 2);
Left = Owner.Left + ((Owner.ActualWidth - ActualWidth) / 2);
Run Code Online (Sandbox Code Playgroud)

如果您编译并运行我提供的示例程序,您将看到它在主窗口原样并且四处移动时有效.这部分是有效的.

所有者窗口最大化时出现问题.(并且在最大化之后,恢复正常.)因为我订阅了三个事件,所以我进入三次重定位函数.打印出所有者数据后,我得到不同的结果.最烦人的TopLeft所有者窗口的值了.当状态改变时,它似乎得到正确的Top和Left值,但是ActualWidthActualHeight值是错误的.当LocationChangedSizeChanged事件触发的ActualWidthActualHeight值是OK,但顶部和左侧值不正确.看来这些是以前的价值观.怎么会这样?是什么造成的?是否有适当的解决方案?

由于相同的代码似乎在.net 3.5中工作,我的印象是在.net 4中发生了一些变化.(或者我有一个奇怪的计时问题导致问题不会出现.)但是我找不到任何记录在案的变化部分.

.NET 3.5:

OnOwnerLocationChanged
T: -8; L: -8; W: 640; H: 480
OnOwnerStateChanged
T: -8; L: -8; W: 640; H: 480
OnOwnerSizeChanged
T: -8; L: -8; W: 1936; H: 1066
Run Code Online (Sandbox Code Playgroud)

.NET 4.0:

OnOwnerLocationChanged
T: -8; L: -8; W: 640; H: 480
OnOwnerStateChanged
T: 494; L: 33; W: 640; H: 480
OnOwnerSizeChanged
T: 494; L: 33; W: 1936; H: 1066
Run Code Online (Sandbox Code Playgroud)

所以主要问题仍然存在:为什么所有者的Top和Left值不正确?

Jen*_*sen 14

Mataniko关于.NET 4.0中迁移问题的评论是正确的.由于我的代码在WindowState设置时工作Normal,我可以保留它.我不得不预见的东西时WindowStateMaximized.

我实现了原生的GetWindowRect()函数来实现这一点,因为它可以给我合适的尺寸.

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

// Make sure RECT is actually OUR defined struct, not the windows rect.
public static RECT GetWindowRectangle(Window window)
{
    RECT rect;
    GetWindowRect((new WindowInteropHelper(window)).Handle, out rect);

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

接下来,当Owner.WindowStateMaximized,我们使用GetWindowRectangle函数来获取实际尺寸.此时我们不关心边框,但如果需要,可以使用GetSystemMetrics函数合并它.

if (Owner.WindowState == WindowState.Maximized)
{
    var rect = GetWindowRectangle(Owner);

    Top = rect.Top + ((rect.Bottom - ActualHeight) / 2);
    Left = rect.Left + ((rect.Right - ActualWidth) / 2);
}
Run Code Online (Sandbox Code Playgroud)