MCI(メディア コントロール インターフェイス)を使用することで WAV ファイルや MIDI ファイル等を再生することができます。
mciSendCommand 関数で再生〜停止するには、MCI_OPEN、MCI_PLAY、MCI_STOP、MCI_CLOSE の順でメッセージを送ります。
Windows Media Player のバージョンによりMP3ファイルなども再生できます。
再生〜停止までの mciSendCommand のメッセージ
| メッセージ | 機能 |
|---|---|
| MCI_OPEN | デバイスまたはファイルを初期化します。 |
| MCI_PLAY | 出力データの送信を開始するようにデバイスに指示します。 |
| MCI_STOP | すべての再生または記録シーケンスを停止し、すべての再生バッファをアンロードし、ビデオイメージの表示を停止します。 |
| MCI_CLOSE | デバイスやファイルへのアクセスを解放します。 |
#include <windows.h>
#include <tchar.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
#define IDM_OPEN 100
#define IDM_CLOSE 101
#define IDM_EXIT 102
#define AllocMemory(s) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, s)
#define FreeMemory(p) HeapFree(GetProcessHeap(), 0, p)
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void ShowMciErrorMessage(HWND hwnd, MCIERROR mciError);
HINSTANCE hInst;
LPCTSTR lpszAppName = TEXT("MyApp");
LPCTSTR lpszAppTitle = TEXT("MyApp");
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
MSG msg = {0};
HWND hWnd;
WNDCLASSEX wc = {0};
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(nCmdShow);
//メインウィンドウクラス登録
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = lpszAppName;
wc.hIconSm = NULL;
if(RegisterClassEx(&wc) == 0) {
return 0;
}
hInst = hInstance;
//メニュー作成
HMENU hMenu = CreateMenu();
HMENU hPopMenu = CreatePopupMenu();
AppendMenu(hPopMenu, MF_STRING, IDM_OPEN, TEXT("&Open"));
AppendMenu(hPopMenu, MF_STRING, IDM_CLOSE, TEXT("&Close"));
AppendMenu(hPopMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hPopMenu, MF_STRING, IDM_EXIT, TEXT("&Exit"));
AppendMenu(hMenu, MF_POPUP | MF_STRING, reinterpret_cast<UINT_PTR>(hPopMenu), TEXT("&File"));
//メインウインドウ作成
hWnd = CreateWindow(lpszAppName, lpszAppTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, hMenu, hInstance, NULL
);
if(hWnd == NULL) {
return 0;
}
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
//メイン メッセージ ループ
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static MCIDEVICEID mciDeviceID = 0;
static MCI_PLAY_PARMS mciPlayParms = {0};
static OPENFILENAME ofn = {0};
switch(uMsg) {
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDM_OPEN: //WAVファイル再生
{
//WAVファイルを選択
if(!GetOpenFileName(&ofn)) {
break;
}
//MCIデバイスのオープン
SendMessage(hWnd, WM_COMMAND, IDM_CLOSE, 0);
MCI_OPEN_PARMS mciOpenParms = {0};
DWORD fdwCommand = MCI_WAIT | MCI_OPEN_ALIAS | MCI_OPEN_ELEMENT;
MCIERROR mciError = 0;
TCHAR szAlias[MAX_PATH * sizeof(WCHAR) / sizeof(TCHAR) + 10];
mciOpenParms.lpstrElementName = ofn.lpstrFile;
mciOpenParms.lpstrAlias = szAlias;
int i = 0;
wsprintf(szAlias, TEXT("%s_%x"), ofn.lpstrFile, i++);
mciError = mciSendCommand(0, MCI_OPEN, fdwCommand, reinterpret_cast<DWORD_PTR>(&mciOpenParms));
while(mciError == MCIERR_DUPLICATE_ALIAS) {
wsprintf(szAlias, TEXT("%s_%x"), ofn.lpstrFile, i++);
mciError = mciSendCommand(0, MCI_OPEN, fdwCommand, reinterpret_cast<DWORD_PTR>(&mciOpenParms));
}
if(mciError > 0) { //エラー
ShowMciErrorMessage(hWnd, mciError);
break;
}
mciDeviceID = mciOpenParms.wDeviceID;
//再生
mciPlayParms.dwCallback = reinterpret_cast<DWORD_PTR>(hWnd);
mciPlayParms.dwFrom = 0;
mciError = mciSendCommand(mciDeviceID, MCI_PLAY, MCI_FROM | MCI_NOTIFY, reinterpret_cast<DWORD_PTR>(&mciPlayParms));
if(mciError > 0) { //エラー
ShowMciErrorMessage(hWnd, mciError);
break;
}
}
break;
case IDM_CLOSE: //停止
{
if(mciDeviceID > 0) {
//停止
mciSendCommand(mciDeviceID, MCI_STOP, MCI_WAIT, 0);
//MCIデバイスのクローズ
mciSendCommand(mciDeviceID, MCI_CLOSE, MCI_WAIT, 0);
mciDeviceID = 0;
ZeroMemory(&mciPlayParms, sizeof(MCI_PLAY_PARMS));
}
}
break;
case IDM_EXIT: //終了
SendMessage(hWnd, WM_CLOSE, 0, 0);
break;
}
break;
case MM_MCINOTIFY:
{
//再生が終了したらリピート
if(wParam == MCI_NOTIFY_SUCCESSFUL) {
mciPlayParms.dwFrom = 0;
MCIERROR mciError = mciSendCommand(mciDeviceID, MCI_PLAY, MCI_FROM | MCI_NOTIFY, reinterpret_cast<DWORD_PTR>(&mciPlayParms));
if(mciError > 0) { //エラー
ShowMciErrorMessage(hWnd, mciError);
break;
}
}
}
break;
case WM_CREATE:
{
//初期化
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hWnd;
ofn.lpstrFile = static_cast<LPTSTR>(AllocMemory(sizeof(TCHAR) * (MAX_PATH * sizeof(WCHAR) / sizeof(TCHAR))));
ofn.nMaxFile = MAX_PATH * sizeof(WCHAR) / sizeof(TCHAR);
ofn.lpstrFileTitle = static_cast<LPTSTR>(AllocMemory(sizeof(TCHAR) * (MAX_PATH * sizeof(WCHAR) / sizeof(TCHAR))));
ofn.nMaxFileTitle = MAX_PATH * sizeof(WCHAR) / sizeof(TCHAR);
ofn.lpstrFilter = TEXT("WAV ファイル(*.wav)\0*.wav\0");
ofn.lpstrDefExt = TEXT("wav");
ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
if(ofn.lpstrFile == NULL || ofn.lpstrFileTitle == NULL) {
return -1;
}
}
break;
case WM_DESTROY:
{
SendMessage(hWnd, WM_COMMAND, IDM_CLOSE, 0);
if(ofn.lpstrFile != NULL) {
FreeMemory(ofn.lpstrFile);
}
if(ofn.lpstrFileTitle != NULL) {
FreeMemory(ofn.lpstrFileTitle);
}
PostQuitMessage(0);
}
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
void ShowMciErrorMessage(HWND hwnd, MCIERROR mciError)
{
TCHAR szErrorMsg[MAXERRORLENGTH];
if(mciGetErrorString(mciError, szErrorMsg, sizeof(szErrorMsg))) {
MessageBox(hwnd, szErrorMsg, lpszAppTitle, MB_ICONEXCLAMATION);
}
}