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

フォームを移動できないようにする

フォームを移動できないようにすることが適当なケースは限られると思いますが、ここではフォームの位置を固定する幾つかの方法を紹介します。

なおフォームが移動できる範囲を制限する方法は「フォームが移動できる範囲を制限する」で、フォームのサイズを変更できないようにする方法は「フォームのサイズを変更できないようにする」で説明しています。

タイトルバーを消す方法

最も簡単な方法は、「タイトルバーを消す」で紹介した方法を使って、フォームのタイトルバーを消すことでしょう。どうしてもタイトルバーが必要という場合は、ピクチャボックスなどで偽物のタイトルバー作って表示させるという手があります。

Moveイベントでフォームの位置を元に戻す方法

また、フォームのMoveやLocationChangedイベントハンドラでフォームの位置を元に戻すという方法があります。この方法では、フォームを移動させようとすると一瞬フォームの位置が変わるため、ちかちかして見た目がよくありません。

これらのイベントについては「フォームの位置や大きさが変更されたことを知る」で説明していますので、詳しくはそちらをご覧ください。

WndProcをオーバーライドする方法

さらに、WndProcメソッドをオーバーライドする方法もあります。これは、「32.18 How do I prevent a user from moving a form at run time?」や「Re: Fixing form on the screen」で紹介されている方法です。両者のコードは若干異なり、前者ではWM_NCLBUTTONDOWNとHTCAPTIONを、後者ではWM_NCHITTESTとHTCAPTIONを調べています。しかし実際に試してみるとこの部分は必要なく、以下のようなコードだけで移動できなくなるようです。(ただしフォームのサイズが変更できる場合は、フォームのサイズを変更することにより、移動できてしまいます。)

VB.NET
コードを隠すコードを選択
'Imports System.Security.Permissions

<SecurityPermission(SecurityAction.Demand, _
    Flags:=SecurityPermissionFlag.UnmanagedCode)> _
Protected Overrides Sub WndProc(ByRef m As Message)
    Const WM_SYSCOMMAND As Integer = &H112
    Const SC_MOVE As Long = &HF010L

    If m.Msg = WM_SYSCOMMAND AndAlso _
        (m.WParam.ToInt64() And &HFFF0L) = SC_MOVE Then
        m.Result = IntPtr.Zero
        Return
    End If

    MyBase.WndProc(m)
End Sub
C#
コードを隠すコードを選択
//using System.Security.Permissions;

[SecurityPermission(SecurityAction.Demand,
    Flags = SecurityPermissionFlag.UnmanagedCode)]
protected override void WndProc(ref Message m)
{
    const int WM_SYSCOMMAND = 0x0112;
    const long SC_MOVE = 0xF010L;

    if (m.Msg == WM_SYSCOMMAND &&
        (m.WParam.ToInt64() & 0xFFF0L) == SC_MOVE)
    {
        m.Result = IntPtr.Zero;
        return;
    }

    base.WndProc(ref m);
}
  • 履歴:
  • 2010/6/30 WndProcにSecurityPermissionAttributeを付けた。
  • 2012/4/9 「WndProcをオーバーライドする方法」のコードが64ビット環境でうまくいかない不具合を修正。
  • 2013/12/9 SecurityAction.LinkDemandの代わりにSecurityAction.Demandを使うようにした。

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

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