Form の右上の閉じるボタンの使用可不可
31 WinSystemButtonDisabled 動作確認 Delphi2007 更新日 2010/01/05(火)

Formの右上には最小化/最大化/閉じるボタンがあります。
文字で記入すると [_][□][×] こんなやつです。

この最少化ボタンや最大化ボタンは
FormのBorderIconsプロパティを設定することで
使用不可能にすることができます。

ところが、[×]閉じるボタンは
プロパティで設定できるようにはなっていません。


特殊なFormや何かの処理中などの時にFormを閉じなくするために
[×]閉じるボタンを使用不可能にしたい場合はよくあります。

BorderIconsプロパティからbiSystemMenuを消すことによって
システムメニューを消すと、[×]閉じるボタン自体も消えますが
操作性として違和感のあるものになってしまいますので

[×]閉じるボタンを使用不可能にする方法をメモしておきます。

次のやり方があります。
    [1]  Disabledにする
    [2]  押されても無視する
    [3]  Menu項目自体を削除する
それぞれのやり方をまとめてみました。

────────────────────
◆[1]   Disabledにする
グレーアウトさせるこのやり方が一番自然な動作です。

// システムメニューの「閉じる」ボタンやMenuを無効にする
// 閉じるボタンを無効にする
procedure TForm1.Button1Click(Sender: TObject);
var
  hMenuHandle : HMENU;
begin
  hMenuHandle := GetSystemMenu(Self.Handle,False);
  if hMenuHandle <> 0 then
  begin
    EnableMenuItem(hMenuHandle, SC_CLOSE, (MF_BYCOMMAND or MF_DISABLED
or MF_GRAYED));
  end;
  DrawMenuBar(Self.Handle);
end;

// 閉じるボタンを有効にする
procedure TForm1.Button2Click(Sender: TObject);
var
  hMenuHandle : HMENU;
begin
  hMenuHandle := GetSystemMenu(Self.Handle,False);
  if hMenuHandle <> 0 then
  begin
    EnableMenuItem(hMenuHandle, SC_CLOSE, (MF_BYCOMMAND or MF_ENABLED));
  end;
  DrawMenuBar(Self.Handle);
end;

MF_GRAYED単独でもDisabledの効果はあるようですが
MF_DISABLED or MF_GRAYED と指定した方がより正確です。

Application.MainFormOnTaskbar := False; の場合には、
上記のやり方でハンドル指定する場合に
Self.Handleではなく、Application.Handleを指定すれば
タスクバーに登録されているApplicationWindowのシステムメニュー
に対して[閉じる]メニューがDisabledになるので
アプリケーション全体の終了を不可能にすることもできます。

────────────────────
◆[2]   押されても無視する

システムメニューの「閉じる」や
[×]閉じるボタンを押されても無視する方法があります。
グレー表示にはならないですが、押しても無視されます。
また、このやり方の場合は
ボタンが押された時にのみ処理をするという記述も可能です。

type
  TForm1 = class(TForm)
  private
    procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
  :
  end;

procedure TForm1.WMSysCommand(var Msg: TWMSysCommand);
var
  Ignore: Boolean;
begin
  Ignore := False;
  case Msg.CmdType of
    SC_CLOSE:       Ignore := True; //閉じるを無視
    SC_MINIMIZE:    Ignore := True; //最小化を無視
    SC_MAXIMIZE:    Ignore := True; //最大化を無視
    SC_MOVE,
    SC_MOVE + 2:    Ignore := True; //移動を無視
    SC_SIZE..SC_SIZE + 8:
                    Ignore := True; //サイズ変更を無視
  end;

  if Ignore then
    Msg.Result := 0
  else
    inherited;
end;

Ignoreフラグの値をTrueにすることでメッセージを
無視することができます。

SC_MOVEはキーボードでの移動
SC_MOVE + 2はマウスでの移動
SC_SIZEはキーボードでのサイズ変更
SC_SIZE..8はマウスでのサイズ変更を意味します。

────────────────────
◆[3]   Menu項目自体を削除する

DeleteMenuを使ってシステムメニューを削除してしまう方法です。

procedure TForm1.Button3Click(Sender: TObject);
var
  insMenu  :  HMenu;
begin
  insMenu     :=     GetSystemMenu(Handle, False);
  DeleteMenu  (insMenu, 6, MF_BYPOSITION); //閉じるのメニュー
  DeleteMenu  (insMenu, 5, MF_BYPOSITION); //閉じるの上のバー
  DrawMenuBar (Handle);
end;

この場合、システムメニューからは削除されますが
ボタンの表示は特に変更されませんし、
Vista環境ではForm上で押せるように見えます。
閉じる機能自体は削除されるので、押しても無効なボタンになります。

それぞれ場面に応じて使ってください。

参考────────────────────
FormのBoderStyleとBoderIconsの関係
http://delfusa.main.jp/delfusafloor/technic/technic/082_FormBorder.html

[1]
Borland DelphiQ&A Q.タイトルバーにある閉じるアイコンを有効/無効にしたいのですが・・・
http://www.borland.co.jp/qanda/delphi/d0009423.html
→http://support.codegear.com/article/37295#tocentry48

[2]
[Delphi-ML:26505] RE:閉じるボタンを使用不可にする方法を教えてください。
http://www2.big.or.jp/~osamu/Delphi/browse.cgi?index=26505

[3]
AcidFloor「フォーム右上のXボタンを無効にする」方法
http://homepage2.nifty.com/boheme/delphi/tips/tec0390.htm
→http://www.wwlnk.com/boheme/delphi/tips/tec0390.htm