0

我有一个带边框的 MainWindow 和一个 ChildWindow 作为没有边框的对话框。当子窗口打开时,无法移动主窗口或调整其大小。

我希望应用程序的行为就像它只是一个窗口一样。

我尝试使用以下链接中的行为,但这只是将我的子窗口移动到主窗口内。

DragBahvior

4

3 回答 3

3

有一种更简单的方法可以实现无边框Windows 的拖动或移动。有关更多详细信息,请参阅 MSDN 上的Window.DragMove方法页面,但简而言之,您只需将此行添加到您的代码中的鼠标按下事件处理程序之一:

public YourWindow()
{
    InitializeComponent();
    MouseLeftButtonDown += YourWindow_MouseLeftButtonDown;
}

...

private void YourWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    DragMove(); // <-- this is all you need to add
}

然后,用户将能够单击任何区域Window(取决于您在其中放置的内容)并将其拖到屏幕上。

更新>>>

因此,您的要求似乎比我最初注意到的要多。为了实现你想要的,你必须做很多事情。首先,您需要将孩子Window放置在相对于MainWindow.xaml Window. 当您打开它时,请执行以下操作:

Window window = new Window();
window.Top = this.Top;
window.Left = this.Left;
window.LocationChanged += Window_LocationChanged;
window.ShowDialog();

Window位置可以偏移一些设定的量:

Window window = new Window();
window.Top = this.Top + someHorizontalOffsetAmount;
window.Left = this.Left + someVerticalOffsetAmount;
window.LocationChanged += Window_LocationChanged;
window.ShowDialog();

然后你需要一个Window.LocationChanged事件处理程序(当孩子被移动时引发Window):

private void Window_LocationChanged(object sender, EventArgs e)
{
    Window window = (Window)sender;
    this.Top = window.Top;
    this.Left = window.Left;
}

而已!现在两个Windows 将一起移动。显然,如果您在第一个示例中使用偏移量,那么您将需要在Window_LocationChanged处理程序中使用相同的偏移量。

于 2014-05-20T10:10:22.193 回答
1

听起来您的对话框是Modal,即它被调用ShowDialog()并阻止您使用应用程序的其余部分,直到它被关闭,包括移动主窗口。

如果这不是您想要的行为,那么您将需要通过调用来使您的对话框无模式Show(),或者更好的是,因为您似乎希望它表现为一个窗口,为什么不按预期使用 WPF 并摆脱完全对话?

于 2014-05-20T10:29:06.033 回答
0

所以我终于找到了解决办法。我为 Windows 类写了一个扩展,它很复杂:)

namespace MultiWindowWPF
{
  using System;
  using System.Drawing;
  using System.Linq;
  using System.Threading;
  using System.Windows;
  using System.Windows.Forms;
  using System.Windows.Input;
  using System.Windows.Media;
  using System.Windows.Threading;

  using Application = System.Windows.Application;

  public static class WindowExtensions
  {
    /// <summary>
    /// Shows the Dialog Modal.
    /// </summary>
    /// <param name="dialogWindow">The dialog window.</param>
    public static void ShowModal(this Window dialogWindow)
    {
      Window window = Application.Current.Windows.OfType<Window>().FirstOrDefault(w => w.IsKeyboardFocusWithin) ?? Application.Current.MainWindow;
      IInputElement lastFocused = FocusManager.GetFocusedElement(window);
      IInputElement lastKeyboardSelected = Keyboard.FocusedElement;
      EventHandler locationChanged = (sender, args) => ParentWndMove(dialogWindow);
      SizeChangedEventHandler sizeChanged = (sender, args) => ParentWndMove(dialogWindow);
      EventHandler stateChanged = (sender, args) => ParentWndStateChanged(dialogWindow);

      window.LocationChanged += locationChanged;
      window.SizeChanged += sizeChanged;
      window.StateChanged += stateChanged;

      EventHandler close = (sender, args) =>
      {

        if (dialogWindow.Dispatcher.CheckAccess())
        {
          dialogWindow.Close();
        }
        else
        {
          dialogWindow.Dispatcher.Invoke(dialogWindow.Close);
        }

        window.LocationChanged -= locationChanged;
        window.SizeChanged -= sizeChanged;
        window.StateChanged -= stateChanged;
      };

      EventHandler closed = (sender, args) =>
      {
        Window self = sender as Window;
        Enable();
        if (self != null)
        {
          self.Owner = null;
        }
      };

      ExitEventHandler exit = (sender, args) => close(sender, args);

      DependencyPropertyChangedEventHandler isEnabledChanged = null;
      isEnabledChanged = (o, eventArgs) =>
        {
          window.Dispatcher.BeginInvoke(
            DispatcherPriority.ApplicationIdle,
            new Action(
              () =>
                {
                  FocusManager.SetFocusedElement(window, lastFocused);
          Keyboard.Focus(lastKeyboardSelected);
        }));

        ((Window)o).IsEnabledChanged -= isEnabledChanged;
      };
      window.IsEnabledChanged += isEnabledChanged;
      dialogWindow.Closed += closed;
      Application.Current.Exit += exit;

      dialogWindow.Show();
      ParentWndMove(dialogWindow);

      while (Application.Current != null)
      {
        DoEvents();
      }
    }

    private static void DoEvents()
    {
      DispatcherFrame frame = new DispatcherFrame();
      Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(ExitFrame), frame);
      Dispatcher.PushFrame(frame);
      Thread.Sleep(10);
    }

    private static void Enable()
    {
      foreach (Window window in Application.Current.Windows.OfType<Window>().Where(window => !window.OwnedWindows.OfType<Window>().Any()))
      {
        window.IsEnabled = true;
      }
    }

    /// <summary>
    /// Exits the frame.
    /// </summary>
    /// <param name="f">The f.</param>
    /// <returns></returns>
    public static object ExitFrame(object f)
    {
      ((DispatcherFrame)f).Continue = false;
      return null;
    }

    /// <summary>
    /// Parents the WND state changed.
    /// </summary>
    /// <param name="dialogWindow">The dialog window.</param>
    public static void ParentWndStateChanged(Window dialogWindow)
    {
      Window owner = dialogWindow.Owner;
      if (owner.WindowState != WindowState.Maximized)
      {
        dialogWindow.WindowState = owner.WindowState;
      }
      ParentWndMove(dialogWindow);
    }

    /// <summary>
    /// Parents the WND move.
    /// </summary>
    /// <param name="dialogWindow">The dialog window.</param>
    public static void ParentWndMove(Window dialogWindow)
    {
      Window owner = dialogWindow.Owner;
      PresentationSource presentationsource = PresentationSource.FromVisual(dialogWindow);
      Matrix m = presentationsource.CompositionTarget.TransformToDevice;

      double centerWidth = owner.Left + owner.ActualWidth / 2;
      double centerHeight = owner.Top + owner.ActualHeight / 2;
      if (owner.WindowState == WindowState.Normal)
      {
        dialogWindow.Top = centerHeight - dialogWindow.ActualHeight / 2;
        dialogWindow.Left = centerWidth - dialogWindow.ActualWidth / 2;
      }
      if (owner.WindowState == WindowState.Maximized)
      {
        //there is no current main window position to use, center on working screen
        Rectangle frame = Screen.FromPoint(new System.Drawing.Point((int)(dialogWindow.Left * m.M11), (int)(dialogWindow.Top * m.M22))).Bounds;

        dialogWindow.Left = frame.X / m.M11 + (frame.Width / m.M11 - dialogWindow.ActualWidth) / 2;
        dialogWindow.Top = frame.Y / m.M22 + (frame.Height / m.M22 - dialogWindow.ActualHeight) / 2;
      }
    }
  }
}
于 2014-05-20T13:01:36.210 回答