【问题标题】:Align the window to center screen after stackpanel is collapsed折叠堆栈面板后将窗口与中心屏幕对齐
【发布时间】:2013-05-23 06:12:44
【问题描述】:

在我的应用程序中,单击按钮时,我将 Stackpanel 可见性设置为 Collapsed,然后再次单击另一个按钮设置回 Visible。
这一切都很好。但是,当该堆栈面板可见时,我的窗口未位于中心。
堆栈面板可见性更改时如何自行调整..
更改 StackPanel 的可见性后,我尝试调用此函数。

private void CenterWindowOnScreen()
{
    double screenWidth = System.Windows.SystemParameters.PrimaryScreenWidth;
    double screenHeight = System.Windows.SystemParameters.PrimaryScreenHeight;
    double windowWidth = this.Width;
    double windowHeight = this.Height;
    this.Left = (screenWidth / 2) - (windowWidth / 2);
    this.Top = (screenHeight / 2) - (windowHeight / 2);
}  

但它没有正确对齐。如何做到这一点??

【问题讨论】:

  • 不确定我是否理解正确,但是如果您想将窗口定位到屏幕的中心,您可以使用 WindowStartupLocation: WindowStartupLocation="CenterScreen"
  • 在表单启动期间工作正常。但在显示表单后,我隐藏了堆栈面板。那时表格宽度会减小。隐藏堆栈面板后如何将其对齐到中心
  • 您的重新定位代码工作正常。当您调用它时,这可能是一个问题,因为 Window 到那时我不会调整大小。用户可以调整您的Window 的大小吗?如果没有,请尝试WindowSizeChanged 事件并阅读this

标签: c# wpf visual-studio-2010


【解决方案1】:

这里有多个问题需要处理。

  • WindowResize 在调用CenterWindow() 之前未完成(如果直接调用),因此计算不正确。

解决方案:SizeChanged 事件处理程序中执行CenterWindow(),并使用计时器来避免过于频繁地调用CenterWindow()

  • 接下来,我们需要使用事件处理程序中的this.ActualWidththis.ActualHeight 来获取精确尺寸,而不是this.Width...
  • 您的用户可能有多个屏幕(它们之间也有不同的分辨率)。当您为可用性执行 CenterWindow(...) 时,您通常希望将 当前 屏幕居中而不是在大多数情况下您的代码无法适应的主屏幕。

解决方案: 需要使用一些 WinForms 助手来获取实际屏幕并区分多个屏幕。

  • 最后,WPF 尺寸与 DPI 无关,虽然应用上述步骤可以使其在默认 96dpi 下正常工作(win-8 也可以考虑 win-7 和 vista),但当用户机器上的 dpi 不同时,您会开始看到奇怪的行为.

解决方案: 使用 dpi 独立的措施来解决这个问题。

现在将所有这些放在一起,我们会得到如下结果:

您需要引用System.Windows.Forms.dll

using System;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Interop;
using System.Windows.Media;

private readonly System.Timers.Timer _resizeTimer = new System.Timers.Timer(500);

public MainWindow() {
  InitializeComponent();

  ...

  SizeChanged += (sender, args) => {
    _resizeTimer.Stop();
    _resizeTimer.Start();
  };
  _resizeTimer.Elapsed +=
    (sender, args) =>
    System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(CenterWindowToCurrentScreen));
}

public static double GetDpiFactor(Visual window) {
  HwndSource windowHandleSource = PresentationSource.FromVisual(window) as HwndSource;
  if (windowHandleSource != null && windowHandleSource.CompositionTarget != null) {
    Matrix screenmatrix = windowHandleSource.CompositionTarget.TransformToDevice;
    return screenmatrix.M11;
  }
  return 1;
}

private void CenterWindowToCurrentScreen() {
  _resizeTimer.Stop();
  double dpiFactor = GetDpiFactor(this);
  var screen = Screen.FromHandle(new WindowInteropHelper(this).Handle);
  double screenLeft = screen.Bounds.Left / dpiFactor;
  double screenTop = screen.Bounds.Top / dpiFactor;
  double screenWidth = screen.Bounds.Width / dpiFactor;
  double screenHeight = screen.Bounds.Height / dpiFactor;
  Left = ((screenWidth - ActualWidth) / 2) + screenLeft;
  Top = ((screenHeight - ActualHeight) / 2) + screenTop;
}

注意:

上面的代码还不能适应的一件事是实际的任务栏尺寸。如果需要,您也可以从屏幕尺寸中减去它们,以获得更精确的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    • 2012-06-24
    • 2015-11-18
    • 1970-01-01
    • 2011-01-02
    • 1970-01-01
    • 2012-03-08
    相关资源
    最近更新 更多