山本ワールド
Windowsプログラミング
アルゴリズム Vitual C++ 2008/2013によるWin32/Win64 APIレベルのプログラム 基礎 Vitual C++ 2008/2013によるAPIレベルのプログラム(32/64bit) Wix3でインストーラーを作る Visual C++ 2008 Standard Editonによるフォームアプリケーションのプログラム(32/64bit) Vitual C++ 2008 Standard EditonによるAPIレベルのプログラム(32/64bit) Windows 7対応 Visual C++ 2008 ExpressによるAPIレベルのプログラム Visual C++ 2005 ExpressによるAPIレベルのプログラム Visual C++ Versiosn 5 BORLAND C++ Windowsプログラム全般 Excel VBA その他PlaySound APIによるwavファイルの再生
概要
PlaySound APIを使用しwavファイルの再生を行います。
サウンドイベントの再生・wavファイルの再生・繰返再生・停止・非同期再生と終了検出について解説しています。
サウンドイベントの再生・wavファイルの再生・繰返再生・停止・非同期再生と終了検出について解説しています。
テスト環境
コンパイラ
Visual C++ 2008 Standard 32/64bitVisual C++ 2013 Express 32/64bit
実行環境
Windows 8.1 Enterprise 64bitWindows 7 EnterPrise Service Pack 1 64bit
Windows Vista Ultimate Service Pack 2 32bit
Windows XP Professional Service Pack 3 32bit
定義済みのサウンド識別子を使用してwavファイルを再生
例えば、ログオン時やエラーが発生時に発生する音は、サウンドイベントといいコントロールパネルのサウンドなどで変更できる。
直接wavファイル名を指定しないので、テーマにより音を変えても正常に動作する。
これらの音を発生されるにはPlaySound APIを使用する。音の種類は、定義済みのサウンド識別子で指定できる。
定義済みのサウンド識別子を使用するには、第1引数に定義済みのサウンド識別子、第3引数にSND_ALIASを付加します。
SND_NODEFAULTを付加しない場合、wavファイルが見つからない場合に標準の音を再生します。
SND_SYNCは音の再生が終わるまでPlaySound APIは制御を渡しません。
エラーが発生した場合、FALSEを返します。
例えば、Windowsのログオン時の音を再生させるためのソースコードは以下の通りです。
ZIPファイルに含まれるファイル
例えばWindowsに対するレジストリキーは以下の通りです。
該当Windowsの列で○がある場合はサウンドイベントがレジストリに登録されていることを示します。
Windows XP、Windows Vista、Windows 7 のサウンドイベントに対するwavファイルは、Cドライブにwindowsをインストールした場合、C:¥windows¥mediaに保存されています。
Windows 7でC:¥windows¥mediaを見ると
のように、日本語のファイル名になっていますが、コマンドプロンプトのDIRコマンドで見ると以下の様に英語になっています。
ファイル名を指定してPlay Sound APIを使用する場合は、英語名で使用する必要がある。レジストリも英語名で登録されている。
直接wavファイル名を指定しないので、テーマにより音を変えても正常に動作する。
これらの音を発生されるにはPlaySound APIを使用する。音の種類は、定義済みのサウンド識別子で指定できる。
定義済みのサウンド識別子を使用するには、第1引数に定義済みのサウンド識別子、第3引数にSND_ALIASを付加します。
SND_NODEFAULTを付加しない場合、wavファイルが見つからない場合に標準の音を再生します。
SND_SYNCは音の再生が終わるまでPlaySound APIは制御を渡しません。
エラーが発生した場合、FALSEを返します。
例えば、Windowsのログオン時の音を再生させるためのソースコードは以下の通りです。
// PlaySound API サンプル1
// 定義済みのサウンド識別子により音を指定
#include <windows.h>
#include <tchar.h>
#pragma comment(lib, "winmm.lib" )
int WINAPI _tWinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, TCHAR* CmdLine, int nCmdShow){
if (PlaySound(_TEXT("WindowsLogon"), NULL, SND_ALIAS | SND_SYNC | SND_NODEFAULT) == FALSE)
MessageBox(0,_TEXT("再生できませんでした。"),_TEXT("エラー"),MB_OK);
return 0;
}
ダウンロード playsound_alias.zip(21.2kByte)ZIPファイルに含まれるファイル
playsound_alias.cpp
playsound_alias.exe
サウンドイベントに対するwavファイルはレジストリで定義されています。例えばWindowsに対するレジストリキーは以下の通りです。
¥HKEY_CURRENT_USER¥AppEvents¥Schemes¥Apps¥.Default¥イベント名¥.Current
手持ちのWindowsについてレジストリを抽出して調べたところ下表のとおりでした。該当Windowsの列で○がある場合はサウンドイベントがレジストリに登録されていることを示します。
イベント名 | 定義済みのサウンド識別子 | XP | Vista | 7 | 8.1 |
---|---|---|---|---|---|
一般の警告音 | .Default | ○ | ○ | ○ | ○ |
プログラムエラー | AppGPFault | ○ | ○ | ○ | |
選択 | CCSelect | ○ | ○ | ○ | ○ |
Windowsテーマの変更 | ChangeTheme | ○ | ○ | ||
プログラムの終了 | Close | ○ | ○ | ○ | |
バッテリー切れアラーム | CriticalBatteryAlarm | ○ | ○ | ○ | ○ |
デバイスの接続 | DeviceConnect | ○ | ○ | ○ | ○ |
デバイスの切断 | DeviceDisconnect | ○ | ○ | ○ | ○ |
デバイスの接続の失敗 | DeviceFail | ○ | ○ | ○ | ○ |
新着FAXの通知 | FaxBeep | ○ | ○ | ○ | |
バッテリー低下アラーム | LowBatteryAlarm | ○ | ○ | ○ | ○ |
新着メールの通知 | MailBeep | ○ | ○ | ○ | ○ |
最大化 | Maximize | ○ | ○ | ○ | |
メニューコマンド | MenuCommand | ○ | ○ | ○ | |
メニューポップアップ | MenuPopup | ○ | ○ | ○ | |
メッセージのシェイク | MessageNudge | ○ | |||
最小化 | Minimize | ○ | ○ | ○ | |
通知 | Notification.Default | ○ | |||
インスタントメッセージ通知 | Notification.IM | ○ | |||
アラームサンド1 | Notification.Looping.Alarm | ○ | |||
アラームサンド10 | Notification.Looping.Alarm10 | ○ | |||
アラームサンド2 | Notification.Looping.Alarm2 | ○ | |||
アラームサンド3 | Notification.Looping.Alarm3 | ○ | |||
アラームサンド4 | Notification.Looping.Alarm4 | ○ | |||
アラームサンド5 | Notification.Looping.Alarm5 | ○ | |||
アラームサンド6 | Notification.Looping.Alarm6 | ○ | |||
アラームサンド7 | Notification.Looping.Alarm7 | ○ | |||
アラームサンド8 | Notification.Looping.Alarm8 | ○ | |||
アラームサンド9 | Notification.Looping.Alarm9 | ○ | |||
電話着信サウンド1 | Notification.Looping.Call | ○ | |||
電話着信サウンド10 | Notification.Looping.Call10 | ○ | |||
電話着信サウンド2 | Notification.Looping.Call2 | ○ | |||
電話着信サウンド3 | Notification.Looping.Call3 | ○ | |||
電話着信サウンド4 | Notification.Looping.Call4 | ○ | |||
電話着信サウンド5 | Notification.Looping.Call5 | ○ | |||
電話着信サウンド6 | Notification.Looping.Call6 | ○ | |||
電話着信サウンド7 | Notification.Looping.Call7 | ○ | |||
電話着信サウンド8 | Notification.Looping.Call8 | ○ | |||
電話着信サウンド9 | Notification.Looping.Call9 | ○ | |||
Notification.Mail | ○ | ||||
NFP完了 | Notification.Proximity | ○ | |||
予定表のアラーム | Notification.Reminder | ○ | |||
Notification.SMS | ○ | ||||
プログラムの起動 | Open | ○ | ○ | ○ | |
印刷完了 | PrintComplete | ○ | ○ | ○ | |
NFP接続 | ProximityConnection | ○ | |||
元に戻す(縮小) | RestoreDown | ○ | ○ | ○ | |
元に戻す(拡大) | RestoreUp | ○ | ○ | ○ | |
ツールバーバインドの表示 | ShowBand | ○ | ○ | ○ | ○ |
メッセージ(情報) | SystemAsterisk | ○ | ○ | ○ | ○ |
メッセージ(警告) | SystemExclamation | ○ | ○ | ○ | ○ |
Windowsの終了 | SystemExit | ○ | ○ | ○ | |
システムエラー | SystemHand | ○ | ○ | ○ | ○ |
システム通知 | SystemNotification | ○ | ○ | ○ | ○ |
メッセージ(問い合わせ) | SystemQuestion | ○ | ○ | ○ | |
Windowsの起動 | SystemStart | ○ | |||
Windowsログオフ | WindowsLogoff | ○ | ○ | ○ | |
Windowsログオン | WindowsLogon | ○ | ○ | ○ | ○ |
Windowsユーザーアカウント制御 | WindowsUAC | ○ | ○ | ○ | |
WindowsUnlock | ○ |
Windows 7でC:¥windows¥mediaを見ると
のように、日本語のファイル名になっていますが、コマンドプロンプトのDIRコマンドで見ると以下の様に英語になっています。
ファイル名を指定してPlay Sound APIを使用する場合は、英語名で使用する必要がある。レジストリも英語名で登録されている。
Windows Default.wav
Windows Ding.wav
Windows Error.wav
Windows Exclamation.wav
Windows Feed Discovered.wav
Windows Hardware Fail.wav
Windows Hardware Insert.wav
Windows Hardware Remove.wav
Windows Information Bar.wav
wavファイルの名前を指定して再生
直接wavファイル名を指定して再生します。
PlaySound APIの第1引数にファイル名、第3引数にSND_FILENAMEを付加します。
SND_NODEFAULTを付加しない場合、wavファイルが見つからない場合に標準の音を再生します。
SND_SYNCは音の再生が終わるまでPlaySound APIは制御を渡しません。
エラーが発生した場合、FALSEを返します。
例えば、C:¥WINDOWS¥media¥Windows Battery Critical.wav を再生させるためのソースコードは以下の通りです。
ZIPファイルに含まれるファイル
PlaySound APIの第1引数にファイル名、第3引数にSND_FILENAMEを付加します。
SND_NODEFAULTを付加しない場合、wavファイルが見つからない場合に標準の音を再生します。
SND_SYNCは音の再生が終わるまでPlaySound APIは制御を渡しません。
エラーが発生した場合、FALSEを返します。
例えば、C:¥WINDOWS¥media¥Windows Battery Critical.wav を再生させるためのソースコードは以下の通りです。
// PlaySound API サンプル2
// wavファイル名を指定して再生
#include <windows.h>
#include <tchar.h>
#pragma comment(lib, "winmm.lib" )
int WINAPI _tWinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, TCHAR* CmdLine, int nCmdShow){
if (PlaySound(_TEXT("C:¥¥WINDOWS¥¥media¥¥Windows Battery Critical.wav"), NULL, SND_FILENAME | SND_SYNC | SND_NODEFAULT) == FALSE)
MessageBox(0,_TEXT("再生できませんでした。"),_TEXT("エラー"),MB_OK);
return 0;
}
ダウンロード playsound_file.zip(21.2kByte)ZIPファイルに含まれるファイル
playsound_file.cpp
playsound_file.exe
wavファイルの名前を指定して再生(ループ再生・停止・終了検出)
カレントフォルダーのtest.wavを再生します。
(本プログラムをテストするときは、test.wavをカレントフォルダーに用意してください。)
使用方法
再生ボタン
クリックすると非同期で1回再生します。繰返再生ボタン
クリックすると非同期で繰返再生します。停止ボタン
クリックすると非同期の再生している場合停止します。終了検出再生ボタン
クリックすると新規にスレッドを立ち上げスレッドの中で同期再生を行います。再生中は、秒数が表示されます。再生中は終了ボタン以外はクリックできないようになります。再生が終了するとほかのボタンが押せるようになります。終了ボタン
クリックすると再生中でもプログラムを終了させます。同期再生の場合、再生が終了するまでPlaySoundが制御を返さず、非同期再生の場合再生準備ができたら直ちに制御を返す点が異なります。
再生中のサウンドを停止させる方法
非同期で再生されている場合、PlaySound(NULL,NULL,NULL);を呼び出すと停止できます。 同期再生の場合プログラム自身を終了させます。プログラムソースの説明
自動的に繰り返してサウンドを再生する方法
PlaySoundの第3引数にSND_LOOPを付加します。非同期で再生させますのでPlaySound(NULL,NULL,NULL);で停止させます。
PlaySound APIで再生が終了したことを知る方法
同期再生の場合、呼び出したPlaySound APIから制御が戻れば再生が終了したことがわかります。非同期再生の場合、再生が始まれば制御が戻るため、再生の終了がわかりません。
非同期再生の様に、再生が始めれば制御が戻り、しかも終了がわかるようにするために、新規スレッドで同期再生を行い、Play Sound APIの終了時に呼び出したダイアログボックスへ終了メッセージを送付するようにしました。
本プログラムのThreadPlaySoundを呼び出すと新規スレッドを作成し、そのスレッドの中でPlaySoundで同期再生を行います。再生が終了するとSendMessage APIで呼び出し側にIDC_EXITメッセージを通知します。
再生中は、タイマーにより秒数をカウントし表示します。
ソースコード
playsound_ctl.cpp
// PlaySound API サンプル3
// wavファイルを再生 ループ再生・終了検知などサポート
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include "resource.h"
#pragma comment(lib, "winmm.lib" )
TCHAR* wavFile=_TEXT("test.wav"); // 再生するwavファイル名を指定
// スレッドに渡すパラメータ
struct PlaySoundPara{
TCHAR* name; // PlaySound APIに渡すwavファイル名
DWORD flags; // PlaySound APIに渡すフラグ
HWND hWnd; // PlaySound API終了時にメッセージを渡すウィンドウを指定
};
// ダイアログボックスのプロシージャー
LRESULT CALLBACK DlgProc1(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
int WINAPI _tWinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, TCHAR* CmdLine, int nCmdShow){
DialogBox(hCurInst, TEXT("PLAY_CTL"), 0, (DLGPROC)DlgProc1);
return 0;
}
// CreateThreadにより実行されるスレッド
DWORD WINAPI proc(LPVOID lp){
DWORD r;
PlaySoundPara* p=(PlaySoundPara*)lp;
r = PlaySound(p->name,NULL,p->flags)==FALSE ? FALSE : TRUE;
SendMessage(p->hWnd,WM_COMMAND,IDC_EXIT,r); // PlaySoundの終了をダイアログに知らせる
return 0;
}
HANDLE handle=0; // スレッドのハンドル
// スレッドに渡すパラメータ(ThreadPlaySoundの自動変数として確保すると関数が終了するときに揮発するので注意)
PlaySoundPara para;
// 新規スレッドを作成する
void ThreadPlaySound(HWND hDlg,TCHAR* name,DWORD flags){
DWORD id;
para.name=name;
para.flags=flags;
para.hWnd=hDlg;
handle=CreateThread(NULL,0,proc,(void*)¶,0,&id);
}
// ダイアログボックスのプロシージャー
LRESULT CALLBACK DlgProc1(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam){
DWORD flags=0;
static int count=0;
TCHAR buf[16];
static UINT_PTR timer_id=0;
switch (msg) {
case WM_INITDIALOG:
return TRUE;
case WM_TIMER:
_stprintf_s(buf,sizeof(buf)/sizeof(TCHAR),_TEXT("再生中 %d.%d秒"),count/10,count % 10);
++count;
SetWindowText(GetDlgItem(hDlg,IDC_LABEL1),buf);
return FALSE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDC_EXIT: // 新規スレッドで起動したPlaySoundが終了した場合に呼び出される
KillTimer(hDlg,timer_id); // タイマーを終了
EnableWindow(GetDlgItem(hDlg,IDC_STOP_BUTTON),TRUE);
EnableWindow(GetDlgItem(hDlg,IDC_PLAY_BUTTON),TRUE);
EnableWindow(GetDlgItem(hDlg,IDC_PLAY2_BUTTON),TRUE);
EnableWindow(GetDlgItem(hDlg,IDC_REP_BUTTON),TRUE);
CloseHandle(handle);
handle=0;
if((DWORD)lParam==0)
SetWindowText(GetDlgItem(hDlg,IDC_LABEL1),_TEXT("エラー"));
else
SetWindowText(GetDlgItem(hDlg,IDC_LABEL1),_TEXT("再生を終了しました"));
return FALSE;
case IDC_STOP_BUTTON: // 停止ボタンをクリックした場合
PlaySound(NULL,NULL,NULL);
SetWindowText(GetDlgItem(hDlg,IDC_LABEL1),_TEXT("停止しました"));
return TRUE;
case IDC_PLAY_BUTTON: // 再生ボタンをクリックした場合
flags=SND_FILENAME | SND_NODEFAULT | SND_ASYNC;
PlaySound(wavFile,NULL,flags);
SetWindowText(GetDlgItem(hDlg,IDC_LABEL1),_TEXT("再生を開始しました"));
return TRUE;
case IDC_PLAY2_BUTTON: // 新規スレッドでPlaySoundを起動
flags=SND_FILENAME | SND_NODEFAULT | SND_SYNC;
EnableWindow(GetDlgItem(hDlg,IDC_STOP_BUTTON),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_PLAY_BUTTON),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_PLAY2_BUTTON),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_REP_BUTTON),FALSE);
count=0;
timer_id=SetTimer(hDlg,100,100,0); // 0.1秒のインターバルタイマー
ThreadPlaySound(hDlg,wavFile,flags);
return TRUE;
case IDC_REP_BUTTON: // 繰返再生ボタンをクリックした場合
flags=SND_FILENAME | SND_NODEFAULT | SND_ASYNC | SND_LOOP;
PlaySound(wavFile,NULL,flags);
SetWindowText(GetDlgItem(hDlg,IDC_LABEL1),_TEXT("繰返再生を開始しました"));
return TRUE;
case IDCANCEL: // 終了ボタンをクリックした場合
EndDialog(hDlg, TRUE);
return TRUE;
default:
return FALSE;
}
default:
return FALSE;
}
return TRUE;
}
resource.h
#define IDC_STOP_BUTTON 100
#define IDC_PLAY_BUTTON 101
#define IDC_PLAY2_BUTTON 102
#define IDC_REP_BUTTON 103
#define IDC_LABEL1 104
#define IDC_EXIT 105
resourece.rc
#include <windows.h>
#include "resource.h"
PLAY_CTL DIALOG DISCARDABLE 0, 0, 312, 47
EXSTYLE WS_EX_DLGMODALFRAME
STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_SETFONT
CAPTION "PlaySound API"
FONT 9, "MS 明朝"
{
LTEXT "",IDC_LABEL1,7,7,260,12
CONTROL "停止", IDC_STOP_BUTTON, "BUTTON", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 7, 26, 54, 14
CONTROL "再生", IDC_PLAY_BUTTON, "BUTTON", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 68, 26, 54, 14
CONTROL "終了検出再生", IDC_PLAY2_BUTTON, "BUTTON", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 129, 26, 54, 14
CONTROL "繰返再生", IDC_REP_BUTTON, "BUTTON", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 190, 26, 54, 14
CONTROL "終了", IDCANCEL, "BUTTON", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 251, 26, 54, 14
}
ZIPファイルに含まれるファイル
playsound_ctl.cpp
playsound_ctl.exe
resource.h
resource.rc
Copyright (C) 2012 山本ワールド All Rights Reserved.