●オーディオプレイヤ開発記 その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 ) 。
あとは、現段階で実装できるメニューは、バージョン情報ぐらいですね。