描画ができたら次は音を再生したいと思うのが自然な流れです サウンドを扱う場合は「winmm.lib」をリンクさせる必要があります #pragma comment(lib,"winmm.lib") ただ鳴らすだけなら PlaySound関数一行で鳴らせますが・・・ PlaySound(WAVEファイル名, NULL, SND_FILENAME | SND_ASYNC); ファイルの読み込みを毎回行うせいで遅い上 Waveファイル(.wav)しか読めません 細かい制御も利きません 細かい制御やmp3やAVIなどのマルチメディアを取り扱うには MCI(Media Control Interface / Multimedia Control Interface)を使います 今回はメディアをオブジェクトとして扱いため、クラス化しています 今回以降はクラスを積極的に使っていく(というか使わざるを得ない)ので 不安な人はC++のクラスを勉強してください すでに講座も作ってあります 今回は3つのコードファイルが必要です ・MCI.h ・MCI.cpp ・main.cpp --------------------------------------------------------------- MCI.hです WAV,MP3,MIDI,CD_AUDIO,AVI の読み込みと再生、停止などを扱うことができます //--------------------------------------------// // ファイル名:MCI.h // 概要: 音ファイル再生関係 // // 作成者:Daiki Terai // 作成日:2010/10/23 // 修正履歴: //--------------------------------------------// #ifndef _MCI_H_ #define _MCI_H_ #include <windows.h> #include <tchar.h> #pragma comment(lib, "winmm.lib") // メディアタイプ enum EMEDIA { WAVE, MIDI, MP3, CD_AUDIO, AVI }; // MCIクラス class CMCI { private: MCIDEVICEID m_ID; // ID public: CMCI(); virtual ~CMCI(); // メディアを開く bool Open(const TCHAR* FileName,EMEDIA Media); //-------------------------------------------------------------------// // 再生 // ループ再生するときは通知メッセージ処理するので // ウィンドウハンドルを渡すこと // // 引数: bLoop ループ再生フラグ // hWnd 処理終了通知メッセージを受け取るウィンドウハンドル //-------------------------------------------------------------------// void Play(bool bLoop = false,HWND hWnd = NULL); // 停止 void Stop(); // 巻き戻し void Rewind(); // 一時停止 void Pause(); // 一時停止解除 void Resume(); // 現在位置取得 DWORD GetPos(); // 再生時間取得 DWORD GetLength(); // 閉じる void Close(); }; #endif --------------------------------------------------------------- MCI.cppです ファイルオープン、(ループ)再生、停止などの基本的な機能の実装をしています // MCI.cpp #define _CRT_SECURE_NO_WARNINGS // 警告抑制用 #define _CRT_NON_CONFORMING_SWPRINTFS // 警告抑制用 #include "MCI.h" CMCI::CMCI():m_ID(0) {} CMCI::~CMCI(){ this->Stop(); this->Close(); } // メディアを開く bool CMCI::Open(const TCHAR* FileName,EMEDIA Media){ MCI_OPEN_PARMS MCIOpen = {}; // 開く用 switch(Media){ case WAVE: { MCIOpen.lpstrDeviceType = _T("WaveAudio"); break; } case MIDI: { MCIOpen.lpstrDeviceType = _T("Sequencer"); break; } case MP3: { MCIOpen.lpstrDeviceType = _T("MPEGVideo"); break; } case CD_AUDIO: { MCIOpen.lpstrDeviceType = _T("CDAudio"); break; } case AVI: { MCIOpen.lpstrDeviceType = _T("avivideo"); break; } } MCIOpen.lpstrElementName = FileName; if(mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT, (DWORD_PTR)&MCIOpen) != 0){ TCHAR Buf[MAX_PATH] = {}; _stprintf(Buf,_T("%sが開けませんでした"),FileName); MessageBox(NULL,Buf,NULL,MB_OK); return false; } m_ID = MCIOpen.wDeviceID; // ミリ秒単位に設定 MCI_SET_PARMS MCISet = {}; MCISet.dwTimeFormat = MCI_FORMAT_MILLISECONDS; mciSendCommand(m_ID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD_PTR)&MCISet); return true; } //-------------------------------------------------------------------// // 再生 // ループ再生するときは通知メッセージ処理するので // ウィンドウハンドルを渡すこと // // 引数: bLoop ループ再生フラグ // hWnd 処理終了通知メッセージを受け取るウィンドウハンドル //-------------------------------------------------------------------// void CMCI::Play(bool bLoop,HWND hWnd) { if(bLoop){ MCI_PLAY_PARMS MCIPlay = {}; // MCI再生設定 MCIPlay.dwCallback = (DWORD_PTR)hWnd;// MM_NOTIFYメッセージを受け取るウィンドウ mciSendCommand(m_ID,MCI_PLAY, MCI_NOTIFY,(DWORD_PTR)&MCIPlay); } else{ mciSendCommand(m_ID,MCI_PLAY, 0,0); } } // 停止 void CMCI::Stop(){ mciSendCommand(m_ID,MCI_STOP,0,0); } // 巻き戻し void CMCI::Rewind(){ mciSendCommand(m_ID,MCI_SEEK,MCI_SEEK_TO_START,0); } // 一時停止 void CMCI::Pause(){ mciSendCommand(m_ID,MCI_PAUSE,0,0); } // 一時停止解除 void CMCI::Resume(){ mciSendCommand(m_ID,MCI_RESUME,0,0); } // 閉じる void CMCI::Close(){ MCI_GENERIC_PARMS MCIGeneric = {}; // データ mciSendCommand( m_ID, MCI_CLOSE, 0, (DWORD_PTR)&MCIGeneric); } SIZE(30){ COLOR(#ffaa00){ MCIを制御するにはmciSendCommand関数を使います }} MCIERROR mciSendCommand( MCIDEVICEID IDDevice, // デバイス識別子 UINT uMsg, // コマンドメッセージ DWORD fdwCommand, // フラグ DWORD dwParam // パラメータを保持している構造体 ); デバイス識別子というのはメディアのIDのことです コマンドメッセージはMCIの処理の種類を決めます MCI_OPENを指定するとメディアを開きます MCI_PLAYを指定するとメディアを再生します MCI_STOPを指定するとメディアを停止します MCI_SEEKを指定するとメディアのシークバー位置を変更します MCI_PAUSEを指定するとメディアを一時停止します MCI_RESUMEを指定するとメディアの一時停止を解除します フラグはコマンドメッセージによって異なります パラメータ構造体もコマンドメッセージによって異なります メディアを開くには MCI_OPEN_PARMS構造体を使います lpstrDeviceTypeには開くメディアのタイプを文字列で指定します lpstrElementNameにはファイル名を指定します 実際にメディアを開いているのはこの箇所です if(mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT, (DWORD_PTR)&MCIOpen) != 0){ TCHAR Buf[MAX_PATH] = {}; _stprintf(Buf,_T("%sが開けませんでした"),FileName); MessageBox(NULL,Buf,NULL,MB_OK); return false; } オープンに成功したら一意なIDが wDeviceIDに格納されています このIDは再生、停止などの制御に使うので覚えておきます m_ID = MCIOpen.wDeviceID; 時間の単位をミリ秒に設定します 特に設定しなくても再生などはできますが設定すると制御がしやすくなります // ミリ秒単位に設定 MCI_SET_PARMS MCISet = {}; MCISet.dwTimeFormat = MCI_FORMAT_MILLISECONDS; mciSendCommand(m_ID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD_PTR)&MCISet); 再生箇所は次のようになっています //-------------------------------------------------------------------// // 再生 // ループ再生するときは通知メッセージ処理するので // ウィンドウハンドルを渡すこと // // 引数: bLoop ループ再生フラグ // hWnd 処理終了通知メッセージを受け取るウィンドウハンドル //-------------------------------------------------------------------// void CMCI::Play(bool bLoop,HWND hWnd) { if(bLoop){ MCI_PLAY_PARMS MCIPlay = {}; // MCI再生設定 MCIPlay.dwCallback = (DWORD_PTR)hWnd;// MM_NOTIFYメッセージを受け取るウィンドウ mciSendCommand(m_ID,MCI_PLAY, MCI_NOTIFY,(DWORD_PTR)&MCIPlay); } else{ mciSendCommand(m_ID,MCI_PLAY, 0,0); } } ここでループ再生させるときは、ウィンドウにメディアの再生が終了したときを知らせなければなりません MCI_PLAY_PARMS構造体のdwCallbackに処理終了メッセージを受け取るウィンドウのハンドルを指定します ---------------------------------------------------------------------- main.cppです メインコードに自作のMCI.hをインクルードさせる必要があります また、CMCIクラス変数もグローバル変数として作成しておきましょう (本当はグローバル変数は使いたくないんですが・・・ ウィンドウをクラス化すればこの問題は解決できます) #include "MCI.h" #include <tchar.h> #include <stdio.h> #include <stdlib.h> #include <windows.h> #include <windowsx.h> #include <commctrl.h> #pragma comment(lib,"comctl32.lib") #pragma comment(lib,"winmm.lib") // MCI CMCI g_Media[2]; -------------------------------------------------------------------- メッセージ処理部分です //------------------------------------------------------// // ウィンドウ作成メッセージ処理 // // 引数: hWnd ウィンドウハンドル // lpCreateStruct ウィンドウ作成情報 //------------------------------------------------------// BOOL OnCreate(HWND hWnd,LPCREATESTRUCT lpCreateStruct){ g_Media[0].Open(_T("あぶないおにいちゃんです.mp3"),MP3); g_Media[1].Open(_T("ゆっくりしていってね.wav"),WAVE); g_Media[0].Play(true,hWnd); g_Media[1].Play(); return TRUE; } //------------------------------------------------------// // ウィンドウ破棄メッセージ処理 // // 引数: hWnd ウィンドウハンドル //------------------------------------------------------// void OnDestroy(HWND hWnd){ PostQuitMessage(0); } //-----------------------------------------------------// // ウィンドウプロシージャ // デフォルトの処理はDefWindowProc関数で行う // // 引数: hWnd ウィンドウハンドル // msg メッセージ // wParam パラメータ // lParam パラメータ // // 戻り値:処理結果 //-----------------------------------------------------// LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch(msg){ HANDLE_MSG(hWnd,WM_CREATE,OnCreate); // MCI処理終了通知メッセージ case MM_MCINOTIFY:{ MCI_PLAY_PARMS mciPlay; // 通知メッセージ失敗 if (wParam != MCI_NOTIFY_SUCCESSFUL) return 0; // 初期位置に戻す mciSendCommand((MCIDEVICEID)lParam, MCI_SEEK, MCI_SEEK_TO_START, 0); mciPlay.dwCallback = (DWORD_PTR)hWnd; // ループ再生 mciSendCommand((MCIDEVICEID)lParam, MCI_PLAY, MCI_NOTIFY, (DWORD_PTR)&mciPlay); return 0; } HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy); } return DefWindowProc(hWnd, msg, wParam, lParam); } ウィンドウ作成時にWM_CREATEというメッセージが1度だけ送られてきます ウィンドウに依存する変数の初期化などの処理を行います メッセージクラッカーでOnCreate関数で初期化処理をします HANDLE_MSG(hWnd,WM_CREATE,OnCreate); 今回は初期化時にメディアをオープンし、再生してます Openメソッドの第2引数は、適切なメディアタイプを指定してください。MCI.hで定義しています ループ再生にはPlayメソッドに、ウィンドウハンドルを渡す必要があります g_Media[0].Open(_T("あぶないおにいちゃんです.mp3"),MP3); g_Media[1].Open(_T("ゆっくりしていってね.wav"),WAVE); g_Media[0].Play(true,hWnd); g_Media[1].Play(); 再生終了したときループ再生フラグを立てているメディアには MM_MCINOTIFYメッセージが送られてきます これに関してはメッセージクラッカーは用意されていないので ウィンドウプロシージャで直接処理しています ループ処理自体はシークバー位置を初期位置に戻し 再び再生終了時にMM_MCINOTIFYメッセージを送ることで無限に再生ループをつくっています // MCI処理終了通知メッセージ case MM_MCINOTIFY:{ MCI_PLAY_PARMS mciPlay; // 通知メッセージ失敗 if (wParam != MCI_NOTIFY_SUCCESSFUL) return 0; // 初期位置に戻す mciSendCommand((MCIDEVICEID)lParam, MCI_SEEK, MCI_SEEK_TO_START, 0); mciPlay.dwCallback = (DWORD_PTR)hWnd; // ループ再生 mciSendCommand((MCIDEVICEID)lParam, MCI_PLAY, MCI_NOTIFY, (DWORD_PTR)&mciPlay); return 0; } 全ソースコードと音ファイルは下からダウンロードしてください &ref(main.zip); ソースファイルと音ファイルは 作成したプロジェクトと同じ場所においてください #vote((^ω^)やったお[8],何これwww意味不すぎwww[8],。(`ω´#)。あぁん?最近、だらしねぇな[3]) |(^ω^)やったお|8| |何これwww意味不すぎwww|8| |。(`ω´#)。あぁん?最近、だらしねぇな|3|