DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

フォームが最大化、最小化している時、通常状態の位置と大きさを取得する

ここでは、フォームが最大化、あるいは最小化状態の時、実際にフォームを通常状態に戻すことをせずに、通常状態時の位置と大きさ(サイズ)を取得する方法を紹介します。アプリケーション終了時にフォームの位置と大きさを保存しておきたい時に役に立ちます。

なおフォームの位置と大きさを取得する方法は「フォームの位置と大きさを取得、変更する」で、フォームの状態を調べる方法は「フォームの現在の状態(最大化、最小化)を調べる」で説明しています。

RestoreBoundsプロパティを使用する

.NET Framework 2.0以降では、RestoreBoundsプロパティが使えます。

このプロパティは、現在のフォームの状態が最大化、あるいは最小化の時のみ有効です。通常状態の時は、無意味な値になります。

以下の例では、自分自身のフォームが現在通常状態の時はBoundsプロパティの値を表示し、それ以外(最大化、最小化状態)の時はRestoreBoundsプロパティの値を表示しています。

VB.NET
コードを隠すコードを選択
If Me.WindowState = FormWindowState.Normal Then
    'フォームが通常状態の時は、現在の位置と大きさを表示
    Console.WriteLine(Me.Bounds)
Else
    'フォームが最大化か最小化状態の時は、
    ' 通常状態に戻った時の位置と大きさを表示
    Console.WriteLine(Me.RestoreBounds)
End If
C#
コードを隠すコードを選択
if (this.WindowState == FormWindowState.Normal)
{
    //フォームが通常状態の時は、現在の位置と大きさを表示
    Console.WriteLine(this.Bounds);
}
else
{
    //フォームが最大化か最小化状態の時は、
    // 通常状態に戻った時の位置と大きさを表示
    Console.WriteLine(this.RestoreBounds);
}

フォームの位置とサイズが変更された時に覚えておく方法

.NET Framework 1.1以前でRestoreBoundsプロパティを使用できない場合は、通常状態のフォームの位置とサイズを覚えておくという方法があります。フォームの位置が変更されるとLocationChangedイベントとMoveイベントが、サイズが変更されるとSizeChangedイベントとResizeイベントが発生しますので(詳しくは、「フォームの位置や大きさが変更されたことを知る」)、その時フォームが通常状態だったら、位置とサイズを覚えておくようにします。

VB.NET
コードを隠すコードを選択
'フォームが通常状態の時の位置とサイズ
Private normalLocation As Point
Private normalSize As Size

'フォームのLoadイベントハンドラ
Private Sub Form1_Load(sender As Object, e As EventArgs) _
    Handles MyBase.Load

    'はじめのフォームの位置とサイズを覚えておく
    '(この時フォームは通常状態である必要がある)
    Me.normalLocation = Me.Location
    Me.normalSize = Me.Size
End Sub

'フォームのLocationChangedイベントハンドラ
Private Sub Form1_LocationChanged(sender As Object, e As EventArgs) _
    Handles MyBase.LocationChanged

    'フォームが通常状態だったら、位置を覚えておく
    If Me.WindowState = FormWindowState.Normal Then
        Me.normalLocation = Me.Location
    End If
End Sub

'フォームのSizeChangedイベントハンドラ
Private Sub Form1_SizeChanged(sender As Object, e As EventArgs) _
    Handles MyBase.SizeChanged

    'フォームが通常状態だったら、サイズを覚えておく
    If Me.WindowState = FormWindowState.Normal Then
        Me.normalSize = Me.Size
    End If
End Sub
C#
コードを隠すコードを選択
//フォームが通常状態の時の位置とサイズ
private Point normalLocation;
private Size normalSize;

//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, EventArgs e)
{
    //はじめのフォームの位置とサイズを覚えておく
    //(この時フォームは通常状態である必要がある)
    this.normalLocation = this.Location;
    this.normalSize = this.Size;
}

//フォームのLocationChangedイベントハンドラ
private void Form1_LocationChanged(object sender, EventArgs e)
{
    //フォームが通常状態だったら、位置を覚えておく
    if (this.WindowState == FormWindowState.Normal)
    {
        this.normalLocation = this.Location;
    }
}

//フォームのSizeChangedイベントハンドラ
private void Form1_SizeChanged(object sender, EventArgs e)
{
    //フォームが通常状態だったら、サイズを覚えておく
    if (this.WindowState == FormWindowState.Normal)
    {
        this.normalSize = this.Size;
    }
}

GetWindowPlacementを使用する方法

また、GetWindowPlacement functionを使用するという方法もあります。ただしこの関数はデスクトップ座標で位置を返すようで、タスクバーが画面の左や上にある場合は、フォームのLeftやTopプロパティとは違った値になってしまいます。なおフォームの位置をデスクトップ座標で設定する方法は、「フォームの位置と大きさを取得、変更する」で説明しています。

この方法で、通常状態のフォームの位置とサイズを返すメソッドの例を以下に示します。

VB.NET
コードを隠すコードを選択
'Imports System.Runtime.InteropServices

<DllImport("user32.dll")> _
Private Shared Function GetWindowPlacement( _
    hWnd As IntPtr, ByRef lpwndpl As WINDOWPLACEMENT) As _
        <MarshalAs(UnmanagedType.Bool)> Boolean
End Function

Private Structure WINDOWPLACEMENT
    Public length As Integer
    Public flags As Integer
    Public showCmd As Integer
    Public ptMinPosition As Point
    Public ptMaxPosition As Point
    Public rcNormalPosition As Rectangle
End Structure

'このメソッドがあるフォームの通常状態時の位置とサイズを返す
Public Function GetNormalBounds() As Rectangle
    Dim wp As New WINDOWPLACEMENT()
    wp.length = Marshal.SizeOf(wp)
    GetWindowPlacement(Me.Handle, wp)
    'rcNormalPositionのWidthがRight、HeightがBottomとなっているので、修正
    Return New Rectangle( _
        wp.rcNormalPosition.X, _
        wp.rcNormalPosition.Y, _
        wp.rcNormalPosition.Width - wp.rcNormalPosition.X, _
        wp.rcNormalPosition.Height - wp.rcNormalPosition.Y)
    'または、以下のようにしても同じ
    'Return Rectangle.FromLTRB( _
    '    wp.rcNormalPosition.X, _
    '    wp.rcNormalPosition.Y, _
    '    wp.rcNormalPosition.Width, _
    '    wp.rcNormalPosition.Height)
End Function
C#
コードを隠すコードを選択
//using System.Runtime.InteropServices;

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowPlacement(
    IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);

private struct WINDOWPLACEMENT
{
    public int length;
    public int flags;
    public int showCmd;
    public Point ptMinPosition;
    public Point ptMaxPosition;
    public Rectangle rcNormalPosition;
}

//このメソッドがあるフォームの通常状態時の位置とサイズを返す
public Rectangle GetNormalBounds()
{
    WINDOWPLACEMENT wp = new WINDOWPLACEMENT();
    wp.length = Marshal.SizeOf(wp);
    GetWindowPlacement(this.Handle, ref wp);
    //rcNormalPositionのWidthがRight、HeightがBottomとなっているので、修正
    return new Rectangle(
        wp.rcNormalPosition.X,
        wp.rcNormalPosition.Y,
        wp.rcNormalPosition.Width - wp.rcNormalPosition.X,
        wp.rcNormalPosition.Height - wp.rcNormalPosition.Y);
    //または、以下のようにしても同じ
    //return Rectangle.FromLTRB(
    //    wp.rcNormalPosition.X,
    //    wp.rcNormalPosition.Y,
    //    wp.rcNormalPosition.Width,
    //    wp.rcNormalPosition.Height);
}

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。