システムメニューの「閉じる」をメニュー上から削除する

ウィンドウの最小化・最大化ボタンは有効にしたいけど閉じるボタンは無効にしたい場合のテクニックです。

通常、ControlBoxプロパティをFalseにしてしまうと最小化・最大化ボタンも表示されなくなります。しかし、終了処理の関係上、最小化・最大化ボタンは有効にしたいけど閉じるボタンは無効にしたい場合があります。
最小化・最大化・閉じるボタンはシステムメニューを連動しており、システムメニューを無効化するとそれに対応するボタンが無効になります。

サンプル(32bit)

'システムメニューの取得API
Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Long, ByVal bRevert As Long) As Long


'メニューの無効化
Declare Function DeleteMenu Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long

Public Const SC_CLOSE = &HF060      'システムメニューの「閉じる」
Public Const MF_BYCOMMAND = &H0&    'メニュー項目指定
Public Const MF_BYPOSITION = &H400& 'ポジション指定


Private Sub Form_Load()

    Dim nDUMMY As Long
    
    'フォームの初期化
    Me.Left = (Screen.Width - Me.Width) / 2
    Me.Top = (Screen.Height - Me.Height) / 2

    '「区切り線」・「閉じる」の無効化
    nDUMMY = DeleteMenu(GetSystemMenu(Me.hwnd, 0), 5, MF_BYPOSITION)
    nDUMMY = DeleteMenu(GetSystemMenu(Me.hwnd, 0), SC_CLOSE, MF_BYCOMMAND)

End Sub

サンプル解説

まず、GetSystemMenu関数でシステムメニューのハンドルを取得します。

引数は次の通りです。
(引数の名前は、Declare Functionで指定したものです)

メンバー I/O 説明
hwnd In 取得したいシステムメニューのあるウィンドウハンドル
bRevert In 0ならシステムメニューのハンドルを返します
0以外の場合、標準のシステムメニューに戻します

 

その次に、DeleteMenu関数でシステムメニューの項目を削除します。

引数は次の通りです。
(引数の名前は、Declare Functionで指定したものです)

メンバー I/O 説明
hMenu In システムメニューのハンドル
nPosition In メニュー番号、または、メニューID
wFlags In 動作フラグ
  • MF_BYPOSITION : nPositionにセットしたのはメニュー番号である
  • MF_BYCOMMAND : nPositionにセットしたのはメニューIDである

引数 nPosition と wFlags がポイントになります。定数 SC_CLOSEはメニューIDになり"閉じる"を直接指定する事になります。
そのためDeleteMenu関数に「引数 nPositionにはメニューIDをセットしたよ」と知らせるため引数 wFlags に定数 MF_BYCOMMANDをセットします。

また、その上の行で区切り線を消すため、引数 nPositionにメニュー番号5をセットしています。
メニュー番号とはメニューを上から数えた番号の事です。

  例えばシステムメニューの場合

←となっていますが、メニュー番号は

  • 「元のサイズに戻る(R)」が、0
  • 「移動(M)」が、1
  • 「サイズ変更(S)」が、2

となって

  • 区切り線が、5

となります。

メニュー番号で指定する場合、引数 wFlags にはメニュー番号をセットしたことを示す定数 MF_BYPOSITION をセットします。


[ Window Close ]