Programming Field - プログラミング Tips

MDI子ウィンドウでのWM_SIZEでの落とし穴

MDI子ウィンドウでのウィンドウプロシージャでWM_SIZEを実装する、あるいはMFCの子フレームでOnSizeをオーバーライドするとき、必ずDefChildProcに渡されるように実装(MFC: CMDIChildWnd::OnSizeを呼び出す)をしなければなりません。これをしないと、子ウィンドウを最大化したときに「最小化」「閉じる」のボタンが消えてしまいます。

またこれに関連して、MDI子ウィンドウを最大化したときに「最小化」「閉じる」のボタンを表示する場所(エリア)は、MDIフレームウィンドウ(MDIClientの親)に関連付けられている標準メニューの上となります。つまり、メニューが関連付けられていないと、上記の手順を踏まえていても「最小化」「閉じる」ボタンは表示されません。逆に表示したくない場合は、メニューを持たせない、などを行います。

VBなどの場合は、この処理はきちんと行われているので、MDI子ウィンドウを最大化してもちゃんと「最小化」「閉じる」などは表示されます。これを意図的に表示したくない場合は、やはりメニューを消去する必要がありますが、ただ単にメニューアイテムを消すのではなく、Win32APIのSetMenuなどを使って、親フレームに関連付けられているメニューを無くす必要があります。

VB 6.0での例

Private Declare Function GetMenu Lib "user32.dll" _
    (ByVal hWnd As Long) As Long
Private Declare Function SetMenu Lib "user32.dll" _
    (ByVal hWnd As Long, ByVal hMenu As Long) As Long
Private Declare Function DestroyMenu Lib "user32.dll" _
    (ByVal hMenu As Long) As Long

' MDIフォームの読み込み時に行う場合
Private Sub MDIForm_Load()
    Dim hMenu As Long
    ' まず割り当てられているメニューのハンドルを取得する
    hMenu = GetMenu(Me.hWnd)
    ' メニューの割り当てを無しにする
    Call SetMenu(Me.hWnd, 0&)
    ' 元のメニューはもう要らないので破棄する
    Call DestroyMenu(hMenu)
End Sub