【c#】閉じるボタンを無効化する方法【Win32API】

C#

Windowsフォームアプリケーション(.NetFramework)にて、Win32APIを用いてフォーム画面の閉じるボタンを無効にしてみたので、やり方を残しておこうと思います。

実装前
実装後

実装方法

下記のようなコードを用いれば良いです。

[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool RemoveMenu(IntPtr hMenu, uint uPosition, uint uFlags);

private void Form1_Load(object sender, EventArgs e)
{
    const uint MF_BYPOSITION = 0x400;
    const uint MF_BYCOMMAND = 0x0;
    const uint SC_CLOSE = 0xF060;

    IntPtr systemMenu = GetSystemMenu(this.Handle, false);
    RemoveMenu(systemMenu, 5, MF_BYPOSITION);
    RemoveMenu(systemMenu, SC_CLOSE, MF_BYCOMMAND);
}

補足

GetSystemMenuメソッドとRemoveSystemメニューを用いました。GetSystemMenuの第一引数には閉じるボタンがあるフォームのウィンドウハンドルを指定します。第二引数はfalseを指定したらシステムメニューのハンドルコピーを返し、trueを指定したら標準状態に戻す仕様のようです。

RemoveMenuは、第一引数に閉じるボタンを無効にしたいシステムメニューのハンドル(GetSystemMenuで取得した値)を指定します。第二引数は第三引数の値によって意味合いが変わってくるようです。

  • 第三引数に0x0(MF_BYCOMMAND)を指定した場合、第二引数はメニューIDとして識別されます。この場合は、第二引数に0xF060(SC_CLOSE)を指定すれば閉じるボタンを無効化できました。
  • 第三引数に0x400(MF_BYPOSITION)を指定した場合は第二引数はアイテムの位置のインデックスとして認識されるようです。この場合は、第二引数に6を指定すれば閉じるボタンは無効化できました。

RemoveMenu を使って、画面右上の閉じるボタンを無効にし、またシステムメニューの閉じるボタンおよび区切り線を削除しました。※RemoveMenu(systemMenu, 5, MF_BYPOSITION);は区切り線を削除するための構文です。

また、閉じるボタンを無効化するためには、RemoveSystemの使用後にDrawMenuBarメソッドを使う必要がある、と書かれているサイトもあったのですが、筆者環境の場合はDrawMenuBarを使用しなくても閉じるボタンを無効にできました。動作を検証したところ特に問題はなかったのでDrawMenuBarを使わない方向で進めました。

参考にしたサイト

  • http://www.alato.ne.jp/kazu-/vb/tip16.htm
  • https://www.tokovalue.jp/function/GetSystemMenu.htm
  • http://chokuto.ifdef.jp/urawaza/api/RemoveMenu.html
タイトルとURLをコピーしました