« フリーソフトウェア開発所のバナー | メイン | 任意の文字ごとに読み進めたい - ノベルゲーム風テキストビューア »

2006/02/12(日)

オーディオプレイヤ開発記 その10

 それでは、前回作成した CMenu クラスを継承した CMenu_MainWnd クラスを作り、メインウィンドウ用のメニューを管理させることにします。

//----------------------------------------------------------------------------
// Menu_MainWnd.h : メインウィンドウ用メニューの作成・管理を行う
//----------------------------------------------------------------------------
#ifndef Menu_MainWndH
#define Menu_MainWndH

class CApp;
class CMainWnd;
#include "../Common/Menu.h"
//----------------------------------------------------------------------------
// メインウィンドウ用メニューの作成・管理を行うクラス
//----------------------------------------------------------------------------
class CMenu_MainWnd : public CMenu
{
public: // 関数

    CMenu_MainWnd(CApp & app, CMainWnd & mainWnd)
        : m_rApp(app), m_rMainWnd(mainWnd) { }
    virtual ~CMenu_MainWnd() { }

    virtual BOOL Create();

private: // メンバ変数

    CApp & m_rApp;
    CMainWnd & m_rMainWnd;

    CMenu m_fileMenu;
    CMenu m_viewMenu;
    CMenu m_systemMenu;
    CMenu m_helpMenu;

public: // 定数

    // コマンド ID
    enum {
        ID_FILE = 11,
            ID_OPENFILE,
            ID_SAVEFILE,
            ID_EXIT,
        ID_VIEW,
            ID_CONTROLBAR,
            ID_LIST,
        ID_SYSTEM,
            ID_HEAD,
            ID_PLAY,
            ID_PAUSE,
            ID_STOP,
            ID_PREV,
            ID_NEXT,
            ID_SEP1,
            ID_SLOOP,
            ID_ALOOP,
            ID_RANDOM,
            ID_ABLOOP_A,
            ID_ABLOOP_B,
        ID_HELP,
            ID_VERSIONINFO,
    };
};
//----------------------------------------------------------------------------

#endif
//----------------------------------------------------------------------------
// Menu_MainWnd.cpp : メインウィンドウ用メニューの作成・管理を行う
//----------------------------------------------------------------------------
#include <windows.h>
#include "../App.h"
#include "MainWnd.h"
#include "Menu_MainWnd.h"
//----------------------------------------------------------------------------
// 作成された
//----------------------------------------------------------------------------
BOOL CMenu_MainWnd::Create()
{
    CMenu::Create();

    // ファイルメニュー
    m_fileMenu.CreatePopup();
    m_fileMenu.Append(MFS_DISABLED, ID_OPENFILE, TEXT("開く(&O)...\tCtrl+O"));
    m_fileMenu.Append(MFS_DISABLED, ID_SAVEFILE, TEXT("保存(&S)...\tCtrl+E"));
    m_fileMenu.AppendSeparator();
    m_fileMenu.Append(MFS_DISABLED, ID_EXIT, TEXT("終了(&X)"));
    Append(MF_POPUP, (UINT_PTR)(HMENU)m_fileMenu, TEXT("ファイル(&F)"));

    // 表示メニュー
    m_viewMenu.CreatePopup();
    m_viewMenu.Append(MFS_DISABLED, ID_CONTROLBAR, TEXT("コントロールバー(&C)"));
    m_viewMenu.Append(MFS_DISABLED, ID_LIST, TEXT("プレイリスト(&P)"));
    Append(MF_POPUP, (UINT_PTR)(HMENU)m_viewMenu, TEXT("表示(V)"));

    // システムメニュー
    m_systemMenu.CreatePopup();
    m_systemMenu.Append(MFS_DISABLED, ID_PAUSE, TEXT("再生/一時停止(&P)\tCtrl+P"));
    m_systemMenu.Append(MFS_DISABLED, ID_STOP, TEXT("停止(&S)\tCtrl+S"));
    m_systemMenu.AppendSeparator();
    m_systemMenu.Append(MFS_DISABLED, ID_HEAD, TEXT("頭出し(&H)"));
    m_systemMenu.Append(MFS_DISABLED, ID_PREV, TEXT("前へ(&V)\tCtrl+B"));
    m_systemMenu.Append(MFS_DISABLED, ID_NEXT, TEXT("次へ(&N)\tCtrl+F"));
    m_systemMenu.AppendSeparator();
    m_systemMenu.Append(MFS_DISABLED, ID_SLOOP, TEXT("1曲ループ(&1)"));
    m_systemMenu.Append(MFS_DISABLED, ID_ALOOP, TEXT("全曲ループ(&A)"));
    m_systemMenu.Append(MFS_DISABLED, ID_RANDOM, TEXT("ランダム再生(&R)"));
    Append(MF_POPUP, (UINT_PTR)(HMENU)m_systemMenu, TEXT("システム(&S)"));

    // ヘルプメニュー
    m_helpMenu.CreatePopup();
    m_helpMenu.Append(MFS_DISABLED, ID_VERSIONINFO, TEXT("バージョン情報(&A)..."));
    Append(MF_POPUP, (UINT_PTR)(HMENU)m_helpMenu, TEXT("ヘルプ(&H)"));

    if(!m_hMenu || !(HMENU)m_fileMenu || !(HMENU)m_viewMenu ||
        !(HMENU)m_systemMenu || !(HMENU)m_helpMenu)
        return FALSE;
    return TRUE;
}
//----------------------------------------------------------------------------

 これで、MainWnd.h で Menu_MainWnd.h をインクルードしておき、CMainWnd クラスのメンバ変数に CMenu_MainWnd m_menu; を追加し、コンストラクタで、

CMainWnd(const CApp & app): m_rApp(app), m_menu(app, *this) { }

と初期化しておき、CMainWnd::OnCreate で、

// メニューの作成
if(!m_menu.Create() || !SetMenu(m_menu))
{
    MessageBox(m_hWnd, TEXT("メニューの作成に失敗しました。"
                "アプリケーションを終了します。"), TEXT("エラー"), MB_ICONERROR);
    Destroy();
    return FALSE;
}

などとすることで、メニューが表示されるようになりました。ここまでのソースコードはこちら ( Hayaemon20060212_src.lzh ) 。

 ただ、このままだとメニューがクリックされたとしても何も起こりません。クリックされた後の処理を実装していく必要がありますね。まずは手始めに、ファイル → 終了 メニューがクリックされたら、アプリケーションが終了するようにしてみます。

 メニューがクリックされると、ウィンドウプロシージャに WM_COMMAND というメッセージが飛んでくるので、このメッセージを受け取り次第、コマンド ID などをメニューを管理しているクラスに流すようにします。今回は終了処理なので、まず、CWnd クラスに、

virtual void Close() {
    SendMessage(m_hWnd, WM_CLOSE, 0, 0);
}

および、

virtual void OnCommand(int id, HWND hwndCtl, UINT codeNotify) {
    WindowProc(WM_COMMAND, MAKEWPARAM((UINT)id, (UINT)codeNotify), (LPARAM)hwndCtl);
}

を追加しておき、CWnd::WndProc の、

case WM_CREATE:
    return pWnd->OnCreate((LPCREATESTRUCT)lParam);

となっている部分を、

case WM_COMMAND:
    pWnd->OnCommand((int)LOWORD(wParam), (HWND)lParam, (UINT)HIWORD(wParam));
    return 0;
case WM_CREATE:
    return pWnd->OnCreate((LPCREATESTRUCT)lParam);

と書き換えます。そして、CMainWnd クラスに、

virtual void OnCommand(int id, HWND hwndCtl, UINT codeNotify) {
    if(!hwndCtl)
        m_menu.OnCommand(id, hwndCtl, codeNotify);
    CFrameWnd::OnCommand(id, hwndCtl, codeNotify);
}

を追加し、Menu_MainWnd.h に、

virtual void OnCommand(int id, HWND hwndCtl, UINT codeNotify);
void OnExitMenuSelected();

を追加してから、これらの関数を Menu_MainWnd.cpp で、

//----------------------------------------------------------------------------
// メニューが選択された
//----------------------------------------------------------------------------
void CMenu_MainWnd::OnCommand(int id, HWND/* hwndCtl*/, UINT/* codeNotify*/)
{
    switch(id)
    {
    case ID_EXIT:
        OnExitMenuSelected();
        break;
    }
}
//----------------------------------------------------------------------------
// 終了メニューが選択された
//----------------------------------------------------------------------------
void CMenu_MainWnd::OnExitMenuSelected()
{
    m_rMainWnd.Close();
}
//----------------------------------------------------------------------------

などとします。

 これで、ファイル → 終了 メニューが選択されたら、アプリケーションが終了するようになりました。ここまでのソースコードはこちら ( Hayaemon20060212_2_src.lzh ) 。

 あとは、現段階で実装できるメニューは、バージョン情報ぐらいですね。

トラックバックURL

このエントリーのトラックバックURL:
http://www.edolfzoku.com/diary/mt-tb.cgi/131

コメントする