窗口.使用Windows+Shift+箭头键移动最大化的窗口时,向左是错误的



我在WPF(C#(中遇到了一个问题,我需要在父窗口中的某个点上放置一个弹出窗口。我用Application.Current.MainWindow.LeftApplication.Current.MainWindow.Top获得父位置,只要我不使用Windows快捷键Windows+Shift+将窗口从一个监视器移动到另一个监视器,它就可以工作◄/。如果我使用快捷方式,属性将与移动窗口前保持不变。

窗口必须是WindowState.Maximized,如果没有最大化,它就可以工作。

我也试过用Window.GetWindow(this)代替Application.Current.MainWindow,结果是一样的。

似乎Application.Current.MainWindow没有发生positionchanged事件,也没有更新LeftTop属性。

我在SO或谷歌上没有找到任何关于这方面的信息。非常感谢提供变通方法、提示或解决方案。

尝试使用这个:

WindowInteropHelper windowInteropHelper = new WindowInteropHelper(Application.Current.MainWindow);
Screen screen = System.Windows.Forms.Screen.FromHandle(windowInteropHelper.Handle);

Screen Bounds属性提供了整个窗口的坐标,WorkingArea提供了没有标题栏和停靠窗口的区域的边界。

您应该使用win32API来检索您想要的信息,因为.NET公开的事件不足以检测这种情况。

你必须做两件事:

  1. 收听与窗口移动相对应的WndProc消息(此处为完整列表(。我们想要的是WM_MOVE,并且等于0x0003。有关详细信息,请参阅此线程
  2. 即使处于Maximized状态,也能够确定Window的真实位置,这可以通过使用GetWindowRect方法来实现。有关详细信息,请参阅此线程

这是组装好的代码,当Window被移动时,它会打印它的左上角位置,包括使用您描述的快捷方式。

public partial class MainWindow : Window {
HwndSource source;
const short WM_MOVE = 0x0003;
public MainWindow() {
InitializeComponent();
// Loaded event needed to make sure the window handle has been created.
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e) {
// Subscribe to win32 level events
source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
source.AddHook(new HwndSourceHook(WndProc));
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
if (msg == WM_MOVE) {
Console.WriteLine("Window has moved!");
GetWindowRect(new HandleRef(this, new WindowInteropHelper(this).Handle), out RECT rect);
Console.WriteLine("New location is " + (rect.Left, rect.Top));
}
return IntPtr.Zero;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT {
public int Left;
public int Top;
public int Right;
public int Bottom;
}
}

最新更新