web-dev-qa-db-ja.com

WPFでメインウィンドウをどのように中央に配置しますか?

WPFアプリケーションがあり、プログラムで(XAMLではなく)ウェインウィンドウを中央に配置する方法を知る必要があります。

起動時と特定のユーザーイベントへの応答の両方でこれを実行できる必要があります。ウィンドウサイズ自体は動的であるため、動的に計算する必要があります。

これを行う最も簡単な方法は何ですか?古いWin32コードでは、システムメトリックス関数を呼び出してすべてを実行します。それはまだそれが行われている方法ですか、私が今呼び出すことができる簡単なCenterWindowOnScreen()関数があります。

51
paxdiablo
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);
}

このメソッドを使用して、ウィンドウの位置を画面の中央に設定できます。

74

さて、起動時間には、 起動場所 を設定できます。

window.WindowStartupLocation = WindowStartupLocation.CenterScreen;

後で、クエリを実行する必要があります。情報(少なくともプライマリ画面の場合)は、 SystemParameters.PrimaryScreenWidth /Heightを介して利用できます。

95
Reed Copsey

設定するのは簡単ではありませんか

WindowStartupLocation="CenterScreen"

ウィンドウのXAML定義内。

67
naskew
Rect workArea = System.Windows.SystemParameters.WorkArea;
this.Left = (workArea.Width - this.Width) / 2 + workArea.Left;
this.Top = (workArea.Height - this.Height) / 2 + workArea.Top;

これには、タスクバーのサイズが考慮されます(System.Windows.SystemParameters.WorkArea)および位置(workArea.LeftおよびworkArea.Top

22
Wild_A

私の場合、これらの回答のいくつかを組み合わせて、すべてのベースをカバーする必要がありました。

  • Peterのメソッド 現在のモニターを見つけるために-プライマリーモニターだけではなく(真剣に1台のモニターだけを使用している人はいますか?)
  • @ Wild_Aのメソッド タスクバーのスペースを考慮するためにscreen boundsではなくworkareaを使用します。
  • 特に1280x800を1024x640として表示するタブレットの場合、DPIスケーリングを追加する必要がありましたが、これは here の答えを見つけたEdgeケースをカバーするのに役立ちます。 UIが表示される前に最初のロードで呼び出された場合、dpiScaling変数はnullであることに注意してください( ここで説明
//get the current monitor
Screen currentMonitor = Screen.FromHandle(new System.Windows.Interop.WindowInteropHelper(Application.Current.MainWindow).Handle);

//find out if our app is being scaled by the monitor
PresentationSource source = PresentationSource.FromVisual(Application.Current.MainWindow);
double dpiScaling = (source != null && source.CompositionTarget != null ? source.CompositionTarget.TransformFromDevice.M11 : 1);

//get the available area of the monitor
Rectangle workArea = currentMonitor.WorkingArea;
var workAreaWidth = (int)Math.Floor(workArea.Width*dpiScaling);
var workAreaHeight = (int)Math.Floor(workArea.Height*dpiScaling);

//move to the centre
Application.Current.MainWindow.Left = (((workAreaWidth - (myWindowWidth * dpiScaling)) / 2) + (workArea.Left * dpiScaling));
Application.Current.MainWindow.Top = (((workAreaHeight - (myWindowHeight * dpiScaling)) / 2) + (workArea.Top * dpiScaling));

ここで、myWindowWidthmyWindowHeightは、以前にウィンドウのサイズを手動で設定するために使用した変数です。

15
JumpingJezza

複数画面環境でウィンドウを描画する必要がある場合。次のメソッドを再利用できる静的クラスを作成しました。

public static void PostitionWindowOnScreen(Window window, double horizontalShift = 0, double verticalShift = 0)
{
    Screen screen = Screen.FromHandle(new System.Windows.Interop.WindowInteropHelper(window).Handle);
    window.Left = screen.Bounds.X + ((screen.Bounds.Width - window.ActualWidth) / 2) + horizontalShift;
    window.Top = screen.Bounds.Y + ((screen.Bounds.Height - window.ActualHeight) / 2) + verticalShift;        
}

Windowのコンストラクタで、メソッドを呼び出すだけです:

this.Loaded += (s, a) => Globals.PostitionWindowOnScreen(this, 0, 0)
7
Peter

ウィンドウ要素に、次の属性と値のペアを追加します。WindowStartupLocation = "CenterScreen"

5
Husam Hilal

基本的な解決策として、ウィンドウのStartupLocationプロパティを使用して、System.Windows.WindowStartupLocation列挙で定義された列挙値の1つに設定できます。画面の中央に1つあります。

_wpfWindow.StartupLocation = System.Windows.WindowStartupLocation.CenterScreen;

残念ながら、必ずしもそれほど単純ではありません。複数のモニター、タスクバーなどに対応する必要があります。「CenterScreen」オプションは、マウスカーソルがある画面の中央にウィンドウを開きます。多くの情報については this SO question を参照するか、 api を参照してください。

4
Guy Starbuck

私のアプリで使用しているものは、複数のディスプレイと異なるDPI設定で動作しています

    //center a window on chosen screen
    public static void CenterWindow(Window w, System.Windows.Forms.Screen screen = null)
    {
        if(screen == null)
            screen = System.Windows.Forms.Screen.PrimaryScreen;

        int screenW = screen.Bounds.Width;
        int screenH = screen.Bounds.Height;
        int screenTop = screen.Bounds.Top;
        int screenLeft = screen.Bounds.Left;

        w.Left = PixelsToPoints((int)(screenLeft + (screenW - PointsToPixels(w.Width, "X")) / 2), "X");
        w.Top = PixelsToPoints((int)(screenTop + (screenH - PointsToPixels(w.Height, "Y")) / 2), "Y");
    }

    public static double PixelsToPoints(int pixels, string direction)
    {
        if (direction == "X")
        {
            return pixels * SystemParameters.WorkArea.Width / System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width;
        }
        else
        {
            return pixels * SystemParameters.WorkArea.Height / System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height;
        }
    }

    public static double PointsToPixels(double wpfPoints, string direction)
    {
        if (direction == "X")
        {
            return wpfPoints * System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width / SystemParameters.WorkArea.Width;
        }
        else
        {
            return wpfPoints * System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height / SystemParameters.WorkArea.Height;
        }
    }
1
vinsa

一度に最大化する場合
this.WindowState = System.Windows.WindowState.Maximized;

0
EpiGen

@Wild_Aの回答に基づいて、SizeChangedイベントにサブスクライブし、このイベントハンドラーを追加しました。

private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
    try
    {
        Rect workArea = SystemParameters.WorkArea;
        this.Left = (workArea.Width - e.NewSize.Width) / 2 + workArea.Left;
        this.Top = (workArea.Height - e.NewSize.Height) / 2 + workArea.Top;
    }
    catch (Exception ex) { ... Handel exception; }
}
0
Viking