Windows 95 と Windows XP で動作が異なる。新規メニューアイテムが追加される位置が違うようだ。
ここでは Windows XP 用として記述する。
'デフォルトのウィンドウ・プロシージャを呼ぶ
'ウィンドウの属性を設定する
'システムメニューのハンドルを取得する
'メニューを挿入する
Public Const MF_BYCOMMAND = &H0& Public Const MF_BYPOSITION = &H400& Public Const MF_STRING = &H0& Public Const MF_SEPARATOR = &H800& Public Const SC_SIZE = &HF000 'サイズ変更 Public Const SC_MOVE = &HF010 '移動 Public Const SC_MINIMIZE = &HF020 '最小化 Public Const SC_MAXIMIZE = &HF030 '最大化 Public Const SC_CLOSE = &HF060 '閉じる Public Const SC_RESTORE = &HF120 '元に戻す Public Const GWL_WNDPROC = -4 Public Const WM_SYSCOMMAND = &H112 '独自の定数で"InsertMenu"関数の第4引数で使用する。 '&HF000より小さい任意の定数を設定しなければならない。 Public Const MY_MENU1 = &H1000 Public Const MY_MENU2 = &H1001 Public OldWindowhWnd As Long '----------------------------------------------------------------------- ' 関数名 : SubClass ' 機能 : サブクラス化を開始する ' 引数 : (in) hWnd … コールバック対象となるウインドウのハンドル ' 戻り値 : なし '----------------------------------------------------------------------- Public Function SubClass(ByVal hWnd As Long) As Long OldWindowhWnd = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc) SubClass = OldWindowhWnd End Function '----------------------------------------------------------------------- ' 関数名 : UnSubClass ' 機能 : サブクラス化を終了する ' 引数 : (in) hWnd … コールバック対象となるウインドウのハンドル ' 戻り値 : なし '----------------------------------------------------------------------- Public Sub UnSubClass(ByVal hWnd As Long) Dim FuncRet As Long If OldWindowhWnd <> 0 Then '元のプロシージャアドレスに設定する FuncRet = SetWindowLong(hWnd, GWL_WNDPROC, OldWindowhWnd) OldWindowhWnd = 0 End If End Sub '----------------------------------------------------------------------- ' 関数名:WindowProc ' 機 能:いわずとしれたウインドウプロシージャ '----------------------------------------------------------------------- Private Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, _ ByVal wParam As Long, ByVal lParam As Long) As Long Select Case uMsg Case WM_SYSCOMMAND Select Case wParam Case MY_MENU1 Call MsgBox("メニュー1が選択されました") Case MY_MENU2 Call MsgBox("メニュー2が選択されました") End Select End Select WindowProc = CallWindowProc(OldWindowhWnd, hWnd, uMsg, wParam, lParam) End Function 以下、面倒なので Form_Load() イベントに記述するということで(あまりよろしくは無いが…)。メニューの追加には InsertMenu() 関数、AppendMenu() 関数のどちらも使える模様。好みと流行に応じて使い分けましょう。私はどちらが流行っているかは知りません。 真面目に書くと AppendMenu() は追加位置は必ず最後尾となる。一方 InsertMenu() は第2引数で追加位置を指定できるからこちらの方が使いやすいかもしれない。と言ったものの、追加位置を指定しても最後尾に追加されてしまう。何でじゃ?第3引数に MF_BYPOSITION を指定して、第2引数に追加位置を数字で指定したらその指定位置にメニューが追加されたが…。 #素直に InsertMenuItem() 関数を使った方が良いのか?
Private Sub Form_Load() Dim hSystemMenu As Long 'システムメニューのハンドルを取得 hSystemMenu = GetSystemMenu(Me.hWnd, False) '※※※ MF_BYCOMMAND を指定する場合 - 開始 ※※※ '区切り線を挿入 Call InsertMenu(hSystemMenu, SC_CLOSE, MF_BYCOMMAND Or MF_SEPARATOR, 0, vbNullString) '独自メニューを挿入 Call InsertMenu(hSystemMenu, SC_CLOSE, MF_BYCOMMAND Or MF_STRING, MY_MENU1, "メニュー1(&1)") Call InsertMenu(hSystemMenu, SC_CLOSE, MF_BYCOMMAND Or MF_STRING, MY_MENU2, "メニュー2(&2)") '※※※ MF_BYCOMMAND を指定する場合 - 終了 ※※※ '※※※ MF_BYPOSITION を指定する場合 - 開始 ※※※ '区切り線を挿入 'Call InsertMenu(hSystemMenu, 2, MF_BYPOSITION Or MF_SEPARATOR, 0, vbNullString) '独自メニューを挿入 'Call InsertMenu(hSystemMenu, 3, MF_BYPOSITION Or MF_STRING, MY_MENU1, "メニュー1(&1)") 'Call InsertMenu(hSystemMenu, 4, MF_BYPOSITION Or MF_STRING, MY_MENU2, "メニュー2(&2)") '区切り線を挿入 'Call InsertMenu(hSystemMenu, 5, MF_BYPOSITION Or MF_SEPARATOR, 0, vbNullString) '※※※ MF_BYPOSITION を指定する場合 - 終了 ※※※ '※※※ AppendMenu() 関数を使う場合 - 開始 ※※※ '区切り線を挿入 'Call AppendMenu(hSystemMenu, MF_BYCOMMAND Or MF_SEPARATOR, 0, vbNullString) '独自メニューを挿入 'Call AppendMenu(hSystemMenu, MF_BYCOMMAND Or MF_STRING, MY_MENU1, "メニュー1(&1)") 'Call AppendMenu(hSystemMenu, MF_BYCOMMAND Or MF_STRING, MY_MENU2, "メニュー2(&2)") '※※※ AppendMenu() 関数を使う場合 - 終了 ※※※ Call SubClass(Me.hWnd) End Sub Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) Call UnSubClass(Me.hWnd) End Sub |